Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cockpit_generic.cpp
Go to the documentation of this file.
1 #include "in.h"
2 #include "vsfilesystem.h"
3 #include "vs_globals.h"
4 #include "vegastrike.h"
5 #include "cockpit_generic.h"
6 #include "universe_generic.h"
7 #include "star_system_generic.h"
8 #include "cmd/unit_generic.h"
9 #include "cmd/unit_factory.h"
10 #include "cmd/unit_util.h"
11 #include "cmd/collection.h"
12 #include "lin_time.h" //for fps
13 #include "configxml.h"
14 #include "cmd/images.h"
15 #include "cmd/script/mission.h"
16 #include "cmd/script/msgcenter.h"
17 //#include "cmd/ai/flyjoystick.h"
18 //#include "cmd/ai/firekeyboard.h"
19 #include "cmd/ai/aggressive.h"
20 //#include "main_loop.h"
21 #include <assert.h> //needed for assert() calls
22 #include "savegame.h"
23 //#include "animation.h"
24 //#include "mesh.h"
25 #include "universe_util.h"
26 #include "cmd/ai/fire.h"
27 #include "background.h"
28 //#include "in_mouse.h"
29 //#include "gui/glut_support.h"
30 #include "networking/netclient.h"
31 #include "save_util.h"
32 
33 #include <algorithm>
34 
35 #define SWITCH_CONST (0.9)
36 
37 vector< int >respawnunit;
38 vector< int >switchunit;
39 vector< int >turretcontrol;
40 
41 void Cockpit::beginElement( void *userData, const XML_Char *name, const XML_Char **atts )
42 {
43  ( (Cockpit*) userData )->beginElement( name, AttributeList( atts ) );
44 }
45 
46 void Cockpit::endElement( void *userData, const XML_Char *name )
47 {
48  ( (Cockpit*) userData )->endElement( name );
49 }
50 
52 {
53  float most = -1024;
54  for (int i = 0; i < GetNumMounts(); i++)
55  if ( mounts[i].type->type == weapon_info::PROJECTILE
56  || ( mounts[i].type->size
59  if (mounts[i].status == Mount::ACTIVE && mounts[i].type->LockTime > 0) {
60  float rat = mounts[i].time_to_lock/mounts[i].type->LockTime;
61  if (rat < .99)
62  if (rat > most)
63  most = rat;
64  }
65  }
66  return (most == -1024) ? 1 : most;
67 }
69 {
70  ejecting = true;
71  going_to_dock_screen = false;
72 }
73 
75 {
76  ejecting = true;
77  going_to_dock_screen = true;
78 }
79 
80 using namespace VSFileSystem;
81 void Cockpit::Init( const char *file, bool isDisabled )
82 {
83  retry_dock = 0;
84  shakin = 0;
85  autopilot_time = 0;
86  bool f404 = false;
87  if (file == NULL || strlen( file ) == 0) {
88  if (isDisabled)
89  file = "cockpit.cpt";
90  else
91  file = "disabled-cockpit.cpt";
92  f404 = true;
93  }
94  if (isDisabled == true) {
95  std::string disname = std::string( "disabled-" )+file;
96  Init( disname.c_str() );
97  return;
98  }
99  VSFile f;
100  VSError err = f.OpenReadOnly( file, CockpitFile );
101  if (err > Ok) {
102  //File not found...
103  if ( isDisabled == false && (string( file ).find( "disabled-" ) == string::npos) )
104  Init( file, true );
105  else if (!f404)
106  Init( NULL );
107  return;
108  }
109  Delete();
110  LoadXML( f );
111  f.Close();
112 }
114 {
115  Unit *un = parentturret.GetUnit();
116  if (!un)
117  un = parent.GetUnit();
118  return un;
119 }
120 void Cockpit::SetParent( Unit *unit, const char *filename, const char *unitmodname, const QVector &pos )
121 {
122  if (unit->getFlightgroup() != NULL)
123  fg = unit->getFlightgroup();
124  if (!SERVER)
125  activeStarSystem = _Universe->activeStarSystem(); //cannot switch to units in other star systems.
126  parent.SetUnit( unit );
127  savegame->SetPlayerLocation( pos );
128  if (filename[0] != '\0') {
129  this->GetUnitFileName() = std::string( filename );
130  this->unitmodname = std::string( unitmodname );
131  }
132  if (unit) {
133  this->unitfaction = unit->faction;
134  unit->ArmorData( StartArmor );
135  if (StartArmor[0] == 0) StartArmor[0] = 1;
136  if (StartArmor[1] == 0) StartArmor[1] = 1;
137  if (StartArmor[2] == 0) StartArmor[2] = 1;
138  if (StartArmor[3] == 0) StartArmor[3] = 1;
139  if (StartArmor[4] == 0) StartArmor[4] = 1;
140  if (StartArmor[5] == 0) StartArmor[5] = 1;
141  if (StartArmor[6] == 0) StartArmor[6] = 1;
142  if (StartArmor[7] == 0) StartArmor[7] = 1;
143  maxfuel = unit->FuelData();
144  maxhull = unit->GetHull();
145  }
146 }
148 {
149  //int i;
150  viewport_offset = cockpit_offset = 0;
151 }
153 {
154  static float maxgodliness = XMLSupport::parse_float( vs_config->getVariable( "physics", "player_godliness", "0" ) );
155  godliness = maxgodliness;
156  if (godliness > maxgodliness)
157  godliness = maxgodliness;
158 }
159 
161 {
162  radar_time = 0;
163  cockpit_time = 0;
164 }
166 {
167  static float autopilot_term_distance =
168  XMLSupport::parse_float( vs_config->getVariable( "physics", "auto_pilot_termination_distance", "6000" ) );
169  Unit *targ = autopilot_target.GetUnit();
170  if (targ)
171  return UnitUtil::getSignificantDistance( un, targ ) < autopilot_term_distance*2.5; //if both guys just auto'd in.
172  else
173  return false;
174 }
175 static float getInitialZoomFactor()
176 {
177  static float inizoom = XMLSupport::parse_float( vs_config->getVariable( "graphics", "inital_zoom_factor", "2.25" ) );
178  return inizoom;
179 }
180 Cockpit::Cockpit( const char *file, Unit *parent, const std::string &pilot_name ) : view( CP_FRONT )
181  , parent( parent )
182  , cockpit_offset( 0 )
183  , viewport_offset( 0 )
184  , zoomfactor( getInitialZoomFactor() )
185  , savegame( new SaveGame( pilot_name ) )
186 {
187  //static int headlag = XMLSupport::parse_int (vs_config->getVariable("graphics","head_lag","10"));
188  //int i;
192  fg = NULL;
193  jumpok = 0;
194  TimeOfLastCollision = -200;
195  /*
196  * for (i=0;i<headlag;i++) {
197  * headtrans.push_back (Matrix());
198  * Identity(headtrans.back());
199  * }
200  * for (i=0;i<UnitImages::NUMGAUGES;i++) {
201  * gauges[i]=NULL;
202  * }
203  */
204  activeStarSystem = NULL;
205  InitStatic();
206  //mesh=NULL;
207  ejecting = false;
208  currentcamera = 0;
209  going_to_dock_screen = false;
210  //Radar=Pit[0]=Pit[1]=Pit[2]=Pit[3]=NULL;
212 
213  /*
214  * draw_all_boxes=XMLSupport::parse_bool(vs_config->getVariable("graphics","hud","drawAllTargetBoxes","false"));
215  * draw_line_to_target=XMLSupport::parse_bool(vs_config->getVariable("graphics","hud","drawLineToTarget","false"));
216  * draw_line_to_targets_target=XMLSupport::parse_bool(vs_config->getVariable("graphics","hud","drawLineToTargetsTarget","false"));
217  * draw_line_to_itts=XMLSupport::parse_bool(vs_config->getVariable("graphics","hud","drawLineToITTS","false"));
218  * always_itts=XMLSupport::parse_bool(vs_config->getVariable("graphics","hud","drawAlwaysITTS","false"));
219  * radar_type=vs_config->getVariable("graphics","hud","radarType","WC");
220  *
221  * friendly=GFXColor(-1,-1,-1,-1);
222  * enemy=GFXColor(-1,-1,-1,-1);
223  * neutral=GFXColor(-1,-1,-1,-1);
224  * targeted=GFXColor(-1,-1,-1,-1);
225  * targetting=GFXColor(-1,-1,-1,-1);
226  * planet=GFXColor(-1,-1,-1,-1);
227  * if (friendly.r==-1) {
228  * vs_config->getColor ("enemy",&enemy.r);
229  * vs_config->getColor ("friend",&friendly.r);
230  * vs_config->getColor ("neutral",&neutral.r);
231  * vs_config->getColor("target",&targeted.r);
232  * vs_config->getColor("targetting_ship",&targetting.r);
233  * vs_config->getColor("planet",&planet.r);
234  * }
235  */
236 
237  Init( file );
238 }
239 /*
240  * static vector <int> respawnunit;
241  * static vector <int> switchunit;
242  * static vector <int> turretcontrol;
243  * static vector <int> suicide;
244  * void RespawnNow (Cockpit * cp) {
245  * while (respawnunit.size()<=_Universe->numPlayers())
246  * respawnunit.push_back(0);
247  * for (unsigned int i=0;i<_Universe->numPlayers();i++) {
248  * if (_Universe->AccessCockpit(i)==cp) {
249  * respawnunit[i]=2;
250  * }
251  * }
252  * }
253  * void Cockpit::SwitchControl (const KBData&,KBSTATE k) {
254  * if (k==PRESS) {
255  * while (switchunit.size()<=_Universe->CurrentCockpit())
256  * switchunit.push_back(0);
257  * switchunit[_Universe->CurrentCockpit()]=1;
258  * }
259  *
260  * }
261  *
262  * void Cockpit::Respawn (const KBData&,KBSTATE k) {
263  * if (k==PRESS) {
264  * while (respawnunit.size()<=_Universe->CurrentCockpit())
265  * respawnunit.push_back(0);
266  * respawnunit[_Universe->CurrentCockpit()]=1;
267  * }
268  * }
269  */
270 
271 void Cockpit::recreate( const std::string &pilot_name )
272 {
273  savegame->SetCallsign( pilot_name );
274  Init( "" );
275 }
276 static void FaceTarget( Unit *un )
277 {
278  Unit *targ = un->Target();
279  if (targ) {
280  QVector dir( targ->Position()-un->Position() );
281  dir.Normalize();
282  Vector p, q, r;
283  un->GetOrientation( p, q, r );
284  QVector qq( q.Cast() );
285  qq = qq+QVector( .001, .001, .001 );
286  un->SetOrientation( qq, dir );
287  }
288 }
289 int Cockpit::Autopilot( Unit *target )
290 {
291  int retauto = 0;
292  if (target) {
293  Unit *un = NULL;
294  if ( ( un = GetParent() ) ) {
295  if ( ( retauto = un->AutoPilotTo( un, false ) ) ) {
296  //can he even start to autopilot
297  //SetView (CP_PAN);
298  un->AutoPilotTo( target, false );
299  static bool face_target_on_auto =
300  XMLSupport::parse_bool( vs_config->getVariable( "physics", "face_on_auto", "false" ) );
301  if (face_target_on_auto)
302  FaceTarget( un );
303  static double averagetime = GetElapsedTime()/getTimeCompression();
304  static double numave = 1.0;
305  averagetime += GetElapsedTime()/getTimeCompression();
306  //static float autospeed = XMLSupport::parse_float (vs_config->getVariable ("physics","autospeed",".020"));//10 seconds for auto to kick in;
307  numave++;
308  /*
309  * AccessCamera(CP_PAN)->myPhysics.SetAngularVelocity(Vector(0,0,0));
310  * AccessCamera(CP_PAN)->myPhysics.ApplyBalancedLocalTorque(_Universe->AccessCamera()->P,
311  * _Universe->AccessCamera()->R,
312  * averagetime*autospeed/(numave));
313  */
314  static float initialzoom =
315  XMLSupport::parse_float( vs_config->getVariable( "graphics", "inital_zoom_factor", "2.25" ) );
316  zoomfactor = initialzoom;
317  static float autotime = XMLSupport::parse_float( vs_config->getVariable( "physics", "autotime", "10" ) ); //10 seconds for auto to kick in;
318 
319  autopilot_time = autotime;
320  autopilot_target.SetUnit( target );
321  }
322  }
323  }
324  return retauto;
325 }
326 
327 extern void SwitchUnits2( Unit *nw );
328 void SwitchUnits( Unit *ol, Unit *nw )
329 {
330  bool pointingtool = false;
331  bool pointingtonw = false;
332  for (unsigned int i = 0; i < _Universe->numPlayers(); ++i)
333  if ( i != _Universe->CurrentCockpit() ) {
334  if (_Universe->AccessCockpit( i )->GetParent() == ol)
335  pointingtool = true;
336  if (_Universe->AccessCockpit( i )->GetParent() == nw)
337  pointingtonw = true;
338  }
339  if ( ol && (!pointingtool) ) {
340  Unit *oltarg = ol->Target();
341  if (oltarg)
342  if (ol->getRelation( oltarg ) >= 0)
343  ol->Target( NULL );
344  ol->PrimeOrders();
345  ol->SetAI( new Orders::AggressiveAI( "default.agg.xml" ) );
346  ol->SetVisible( true );
347  }
348  SwitchUnits2( nw );
349 }
350 static void SwitchUnitsTurret( Unit *ol, Unit *nw )
351 {
352  static bool FlyStraightInTurret =
353  XMLSupport::parse_bool( vs_config->getVariable( "physics", "ai_pilot_when_in_turret", "true" ) );
354  if (FlyStraightInTurret) {
355  SwitchUnits( ol, nw );
356  } else {
357  ol->PrimeOrders();
358  SwitchUnits( NULL, nw );
359  }
360 }
361 
362 Unit * GetFinalTurret( Unit *baseTurret )
363 {
364  Unit *un = baseTurret;
365  Unit *tur;
366  for (un_iter uj = un->getSubUnits(); (tur = *uj); ++uj) {
367  SwitchUnits( NULL, tur );
368  un = GetFinalTurret( tur );
369  }
370  return un;
371 }
372 
374 {
375  if (autopilot_time != 0) {
377  if (autopilot_time <= 0) {
378  autopilot_time = 0;
379  Unit *par = GetParent();
380  if (par) {
381  Unit *autoun = autopilot_target.GetUnit();
382  autopilot_target.SetUnit( NULL );
383  if (autoun)
384  par->AutoPilotTo( autoun, false );
385  }
386  }
387  }
388 }
389 
390 extern void DoCockpitKeys();
391 static float dockingdistance( Unit *port, Unit *un )
392 {
393  vector< DockingPorts >::const_iterator i = port->GetImageInformation().dockingports.begin();
394  vector< DockingPorts >::const_iterator end = port->GetImageInformation().dockingports.end();
396  float mag = FLT_MAX;
397  for (; i != end; ++i) {
398  float tmag = (pos.Cast()-(*i).GetPosition()).Magnitude()-un->rSize()-(*i).GetRadius();
399  if (tmag < mag)
400  mag = tmag;
401  }
402  if (mag == FLT_MAX)
403  return UnitUtil::getDistance( port, un );
404  return mag;
405 }
406 static bool too_many_attackers = false;
408 {
409  return too_many_attackers;
410 }
411 
413 {
414  static int max_attackers = XMLSupport::parse_int( vs_config->getVariable( "AI", "max_player_attackers", "0" ) );
415  if (max_attackers == 0) return;
416  static un_iter attack_iterator = _Universe->activeStarSystem()->getUnitList().createIterator();
417  static StarSystem *ss = _Universe->activeStarSystem();
418  if ( ss != _Universe->activeStarSystem() ) {
419  attack_iterator = _Universe->activeStarSystem()->getUnitList().createIterator();
420  ss = _Universe->activeStarSystem();
421  }
422  bool isDone = attack_iterator.isDone();
423  if (_Universe->AccessCockpit( _Universe->numPlayers()-1 ) == this) {
424  if (!isDone)
425  ++attack_iterator;
426  else
427  attack_iterator = _Universe->activeStarSystem()->getUnitList().createIterator();
428  //too_many_attackers=false;
429  }
430  if (isDone) {
431  if (_Universe->AccessCockpit( 0 ) == this)
432  too_many_attackers = false;
433  //printf ("There are %d folks attacking player\n",partial_number_of_attackers);
434  number_of_attackers = partial_number_of_attackers; //reupdate the count
436  too_many_attackers = max_attackers > 0 && (too_many_attackers || number_of_attackers > max_attackers);
437  }
438  Unit *un;
439  if (attack_iterator.isDone() == false && (un = *attack_iterator) != NULL) {
440  Unit *targ = un->Target();
441  float speed = 0, range = 0, mmrange = 0;
442  if (parent == targ && targ != NULL) {
443  un->getAverageGunSpeed( speed, range, mmrange );
444  float dist = UnitUtil::getDistance( targ, un );
445  if (dist <= range*2 || dist <= mmrange)
447  }
448  } else {
449  //
450 
451  //partial_number_of_attackers=-1;
452  }
453 }
454 void PowerDownShield( Shield *shield, float howmuch )
455 {
456  switch (shield->number)
457  {
458  case 2:
459  if (shield->shield2fb.front/howmuch > shield->shield2fb.frontmax)
460  shield->shield2fb.front = shield->shield2fb.frontmax*howmuch;
461  if (shield->shield2fb.back/howmuch > shield->shield2fb.backmax)
462  shield->shield2fb.back = shield->shield2fb.backmax*howmuch;
463  break;
464  case 4:
465  if (shield->shield4fbrl.front/howmuch > shield->shield4fbrl.frontmax)
466  shield->shield4fbrl.front = shield->shield4fbrl.frontmax*howmuch;
467  if (shield->shield4fbrl.right/howmuch > shield->shield4fbrl.rightmax)
468  shield->shield4fbrl.right = shield->shield4fbrl.rightmax*howmuch;
469  if (shield->shield4fbrl.left/howmuch > shield->shield4fbrl.leftmax)
470  shield->shield4fbrl.left = shield->shield4fbrl.leftmax*howmuch;
471  if (shield->shield4fbrl.back/howmuch > shield->shield4fbrl.backmax)
472  shield->shield4fbrl.back = shield->shield4fbrl.backmax*howmuch;
473  break;
474  case 8:
475  if (shield->shield8.frontlefttop/howmuch > shield->shield8.frontlefttopmax)
476  shield->shield8.frontlefttop = shield->shield8.frontlefttopmax*howmuch;
477  if (shield->shield8.frontleftbottom/howmuch > shield->shield8.frontleftbottommax)
478  shield->shield8.frontleftbottom = shield->shield8.frontleftbottommax*howmuch;
479  if (shield->shield8.frontrighttop/howmuch > shield->shield8.frontrighttopmax)
480  shield->shield8.frontrighttop = shield->shield8.frontrighttopmax*howmuch;
481  if (shield->shield8.frontrightbottom/howmuch > shield->shield8.frontrightbottommax)
482  shield->shield8.frontrightbottom = shield->shield8.frontrightbottommax*howmuch;
483  if (shield->shield8.backlefttop/howmuch > shield->shield8.backlefttopmax)
484  shield->shield8.backlefttop = shield->shield8.backlefttopmax*howmuch;
485  if (shield->shield8.backleftbottom/howmuch > shield->shield8.backleftbottommax)
486  shield->shield8.backleftbottom = shield->shield8.backleftbottommax*howmuch;
487  if (shield->shield8.backrighttop/howmuch > shield->shield8.backrighttopmax)
488  shield->shield8.backrighttop = shield->shield8.backrighttopmax*howmuch;
489  if (shield->shield8.backrightbottom/howmuch > shield->shield8.backrightbottommax)
490  shield->shield8.backrightbottom = shield->shield8.backrightbottommax*howmuch;
491  break;
492  default:
493  break;
494  }
495 }
496 
498 {
499  if (retry_dock && !SERVER && Network == NULL) {
500  QVector vec;
502  }
503  if (jumpok)
504  jumpok++;
505  if (jumpok > 5)
506  jumpok = 0;
507  UpdAutoPilot();
508  Unit *par = GetParent();
509  if (par != NULL) {
510  static float minEnergyForShieldDownpower =
511  XMLSupport::parse_float( vs_config->getVariable( "physics", "shield_energy_downpower", "-.125" ) );
512  static float minEnergyShieldTime =
513  XMLSupport::parse_float( vs_config->getVariable( "physics", "shield_energy_downpower_time", "5" ) );
514  static float minEnergyShieldPercent =
515  XMLSupport::parse_float( vs_config->getVariable( "physics", "shield_energy_downpower_percent", ".66666666666666" ) );
516 
517  bool toolittleenergy = (par->EnergyData() <= minEnergyForShieldDownpower);
518  if (toolittleenergy) {
520  if (secondsWithZeroEnergy > minEnergyShieldTime) {
522  PowerDownShield( &par->shield, minEnergyShieldPercent );
523  }
524  } else {
526  }
527  }
528  if ( turretcontrol.size() > _Universe->CurrentCockpit() ) {
531  Unit *par = GetParent();
532  //this being here, it will require poking the turret from the undock script
533  if (par) {
534  if (par->name == "return_to_cockpit") {
535  //if (par->owner->isUnit()==UNITPTR ) this->SetParent(par->owner,GetUnitFileName().c_str(),this->unitmodname.c_str(),savegame->GetPlayerLocation()); // this warps back to the parent unit if we're eject-docking. in this position it also causes badness upon loading a game.
536 
537  Unit *temp = findUnitInStarsystem( par->owner );
538  if (temp) {
539  SwitchUnits( NULL, temp );
540  this->SetParent( temp, GetUnitFileName().c_str(), this->unitmodname.c_str(), temp->Position() ); //this warps back to the parent unit if we're eject-docking. causes badness upon loading a game.
541  }
542  par->Kill();
543  }
544  }
545  if (par) {
546  static int index = 0;
547  int i = 0;
548  bool tmp = false;
549  bool tmpgot = false;
550  if (parentturret.GetUnit() == NULL) {
551  tmpgot = true;
552  Unit *un;
553  for (un_iter ui = par->getSubUnits(); (un = *ui);) {
554  if ( _Universe->isPlayerStarship( un ) ) {
555  ++ui;
556  continue;
557  }
558  if (i++ == index) {
559  //NOTE : this may have been a correction to the conditional bug
560  ++index;
561  if (un->name.get().find( "accessory" ) == string::npos) {
562  tmp = true;
563  SwitchUnitsTurret( par, un );
564  parentturret.SetUnit( par );
565  Unit *finalunit = GetFinalTurret( un );
566  this->SetParent( finalunit, GetUnitFileName().c_str(),
567  this->unitmodname.c_str(), savegame->GetPlayerLocation() );
568  break;
569  }
570  }
571  ++ui;
572  }
573  }
574  if (tmp == false) {
575  if (tmpgot) index = 0;
576  Unit *un = parentturret.GetUnit();
577  if ( un && ( !_Universe->isPlayerStarship( un ) ) ) {
578  SetParent( un, GetUnitFileName().c_str(), this->unitmodname.c_str(), savegame->GetPlayerLocation() );
579  SwitchUnits( NULL, un );
580  parentturret.SetUnit( NULL );
581  un->SetTurretAI();
582  un->DisableTurretAI();
583  }
584  }
585  }
586  }
587  }
588  static bool autoclear = XMLSupport::parse_bool( vs_config->getVariable( "AI", "autodock", "false" ) );
589  if (autoclear && par) {
590  Unit *targ = par->Target();
591  if (targ) {
592  static float autopilot_term_distance =
593  XMLSupport::parse_float( vs_config->getVariable( "physics", "auto_pilot_termination_distance", "6000" ) );
594  float doubled = dockingdistance( targ, par );
595  if ( ( (targ->isUnit() != PLANETPTR
596  && doubled < autopilot_term_distance)
598  par ) <= 0) )
599  && ( !( par->IsCleared( targ ) || targ->IsCleared( par ) || par->isDocked( targ )
600  || targ->isDocked( par ) ) ) && (par->getRelation( targ ) >= 0) && (targ->getRelation( par ) >= 0) ) {
601  if ( targ->isUnit() != PLANETPTR || targ->GetDestinations().empty() )
602  RequestClearence( par, targ, 0 ); //sex is always 0... don't know how to get it.
603  } else if ( ( par->IsCleared( targ )
604  || targ->IsCleared( par ) ) && ( !( par->isDocked( targ ) ) || targ->isDocked( par ) )
605  && ( (targ->isUnit() == PLANETPTR && UnitUtil::getSignificantDistance( par, targ ) > 0)
606  || ( ( targ->isUnit() != PLANETPTR
607  && UnitUtil::getSignificantDistance( par, targ ) > ( targ->rSize()+par->rSize() ) )
608  && (doubled >= autopilot_term_distance) ) ) ) {
609  if ( targ->isUnit() != PLANETPTR || targ->GetDestinations().empty() ) {
610  par->EndRequestClearance( targ );
611  targ->EndRequestClearance( par );
612  }
613  }
614  }
615  }
616  if ( switchunit.size() > _Universe->CurrentCockpit() ) {
618  parentturret.SetUnit( NULL );
619 
620  static float initialzoom =
621  XMLSupport::parse_float( vs_config->getVariable( "graphics", "inital_zoom_factor", "2.25" ) );
622  zoomfactor = initialzoom;
623  static int index = 0;
625  static bool switch_nonowned_units =
626  XMLSupport::parse_bool( vs_config->getVariable( "AI", "switch_nonowned_units", "true" ) );
627 //switch_nonowned_units = true;
628  //static bool switch_to_fac=XMLSupport::parse_bool(vs_config->getVariable("AI","switch_to_whole_faction","true"));
629 
630  Unit *un;
631  bool found = false;
632  int i = 0;
633  for (un_iter ui = _Universe->activeStarSystem()->getUnitList().createIterator(); (un = *ui); ++ui)
634  if (un->faction == this->unitfaction) {
635 //this switches units UNLESS we're an ejected pilot. Instead, if we are an ejected
636 //pilot, switch only if we're close enough.
637 //the trigger is to allow switching only between ships that are actually owned by you, this prevents
638 //stealing a ship from a hired wingman.
639  if ( ( ( (par != NULL)
640  && (i++) >= index )
641  || par == NULL ) && ( !_Universe->isPlayerStarship( un ) )
642  && ( switch_nonowned_units
643  || (par != NULL
644  && un->owner == par->owner)
645  || (par != NULL
646  && un == par->owner)
647  || (par != NULL
648  && un->owner == par)
649  || (par == NULL
650  && un->owner) ) && (un->name != "eject") && (un->name != "Pilot")
651  && (un->isUnit() != MISSILEPTR) ) {
652  found = true;
653  ++index;
654  Unit *k = GetParent();
655  bool proceed = true;
656  if (k)
657  if (k->name == "eject" || k->name == "Pilot" || k->name == "return_to_cockpit")
658  proceed = false;
659  //we are an ejected pilot, so, if we can get close enough to the related unit, jump into it and remove the seat. This said, always allow
660  //switching from the "fake" ejection seat (ejectdock).
661  if ( !proceed && k && ( k->Position()-un->Position() ).Magnitude() < ( un->rSize()+5*k->rSize() ) ) {
662  if ( !(k->name == "return_to_cockpit") )
663  SwitchUnits( k, un );
664  //this refers to cockpit
665  if ( !(k->name == "return_to_cockpit") )
666  this->SetParent( un, GetUnitFileName().c_str(),
667  this->unitmodname.c_str(), savegame->GetPlayerLocation() );
668  if ( !(k->name == "return_to_cockpit") )
669  k->Kill();
670  //un->SetAI(new FireKeyboard ())
671  }
672  if (proceed) {
673  //k->PrimeOrdersLaunched();
674 //k->SetAI (new Orders::AggressiveAI ("interceptor.agg.xml"));
675 //k->SetTurretAI();
676 
677 //Flightgroup * fg = k->getFlightgroup();
678 //if (fg!=NULL) {
679 //
680 //un->SetFg (fg,fg->nr_ships++);
681 //fg->nr_ships_left++;
682 //fg->leader.SetUnit(un);
683 //fg->directive="b";
684 //}
685  SwitchUnits( k, un );
686  this->SetParent( un, GetUnitFileName().c_str(),
687  this->unitmodname.c_str(), savegame->GetPlayerLocation() );
688  //un->SetAI(new FireKeyboard ())
689  }
690  break;
691  }
692  }
693  if (!found)
694  index = 0;
695  }
696  }
697  //this causes the physical ejecting. Check going_to_dock_screen in here, also.
698  if (ejecting) {
699  ejecting = false;
700 //going_to_dock_screen=true; // NO, clear this only after we've UNDOCKED that way we know we don't have issues.
701 
702  Unit *un = GetParent();
703  if (un) {
704  if (going_to_dock_screen == false)
705  un->EjectCargo( (unsigned int) -1 );
706  if (going_to_dock_screen == true) {
707  un->EjectCargo( (unsigned int) -2 );
708  going_to_dock_screen = false;
709  }
710  }
711  }
712  if (!par) {
713  if ( respawnunit.size() > _Universe->CurrentCockpit() ) {
715  static float initialzoom =
716  XMLSupport::parse_float( vs_config->getVariable( "graphics", "inital_zoom_factor", "2.25" ) );
717  zoomfactor = initialzoom;
718  if (Network != NULL) {
721  } else {
722  parentturret.SetUnit( NULL );
724  std::string savegamefile = mission->getVariable( "savegame", "" );
725  unsigned int k;
726  for (k = 0; k < _Universe->numPlayers(); ++k)
727  if (_Universe->AccessCockpit( k ) == this)
728  break;
729  if ( k == _Universe->numPlayers() ) k = 0;
730  if (active_missions.size() > 1) {
731  for (int i = active_missions.size()-1; i > 0; --i) //don't terminate zeroth mission
732  if (active_missions[i]->player_num == k)
733  active_missions[i]->terminateMission();
734  }
735  unsigned int whichcp = k;
736  string newsystem;
737  QVector pos;
738  bool setplayerXloc;
739  savegame->SetStarSystem( "" );
740  QVector tmpoldpos = savegame->GetPlayerLocation();
741  savegame->SetPlayerLocation( QVector( FLT_MAX, FLT_MAX, FLT_MAX ) );
742  vector< string > packedInfo;
743  savegame->ParseSaveGame( savegamefile,
744  newsystem,
745  newsystem,
746  pos,
747  setplayerXloc,
748  this->credits,
749  packedInfo,
750  k );
751  UnpackUnitInfo(packedInfo);
752  if (pos.i == FLT_MAX && pos.j == FLT_MAX && pos.k == FLT_MAX)
753  pos = tmpoldpos;
754  savegame->SetPlayerLocation( pos );
755  CopySavedShips( savegame->GetCallsign(), whichcp, packedInfo, true );
756  bool actually_have_save = false;
757  static bool persistent_on_load =
758  XMLSupport::parse_bool( vs_config->getVariable( "physics", "persistent_on_load", "true" ) );
759  if (savegame->GetStarSystem() != "") {
760  actually_have_save = true;
761  newsystem = savegame->GetStarSystem()+".system";
762  } else {
763  newsystem = _Universe->activeStarSystem()->getFileName();
764  if (newsystem.find( ".system" ) == string::npos)
765  newsystem += ".system";
766  }
767  Background::BackgroundClone savedtextures = {
768  {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
769  };
770  if (persistent_on_load) {
772  } else {
774  savedtextures = tmp->Cache();
776  }
777  StarSystem *ss = _Universe->GenerateStarSystem( newsystem.c_str(), "", Vector( 0, 0, 0 ) );
778  if (!persistent_on_load)
779  savedtextures.FreeClone();
780  this->activeStarSystem = ss;
782 
783  vector< StarSystem* >saved;
784  while ( _Universe->getNumActiveStarSystem() ) {
785  saved.push_back( _Universe->activeStarSystem() );
787  }
788  if ( !saved.empty() )
789  saved.back() = ss;
790  unsigned int mysize = saved.size();
791  for (unsigned int i = 0; i < mysize; i++) {
792  _Universe->pushActiveStarSystem( saved.back() );
793  saved.pop_back();
794  }
795  ss->SwapIn();
796  int fgsnumber = 0;
797  if (fg) {
798  fgsnumber = fg->flightgroup_nr++;
799  fg->nr_ships++;
800  fg->nr_ships_left++;
801  }
803  GetUnitFileName().c_str(), false, this->unitfaction, unitmodname, fg, fgsnumber );
805  ss->AddUnit( un );
806 
807  this->SetParent( un, GetUnitFileName().c_str(), unitmodname.c_str(), savegame->GetPlayerLocation() );
808  SwitchUnits( NULL, un );
809  this->credits = savegame->GetSavedCredits();
810  DoCockpitKeys();
815  if (actually_have_save && !SERVER && Network == NULL) {
816  QVector vec;
817  DockToSavedBases( whichcp, vec );
818  }
821  if (!persistent_on_load)
823  return true;
824  }
825  }
826  }
827  }
828  return false;
829 }
830 
831 void visitSystemHelp( Cockpit *cp, string systemname, float num )
832 {
833  string key( string( "visited_" )+systemname );
834  vector< float > *v = &cp->savegame->getMissionData( key );
835  if ( v->empty() )
836  v->push_back( num );
837  else if ( (*v)[0] != 1.0 && num == 1 )
838  (*v)[0] = num;
839 }
841 {
842  visitSystemHelp( this, systemname, 1.0 );
843  int adj = UniverseUtil::GetNumAdjacentSystems( systemname );
844  for (int i = 0; i < adj; ++i)
845  visitSystemHelp( this, UniverseUtil::GetAdjacentSystem( systemname, i ), 0.0 );
846 }
847 
849 {
850  Delete();
851  if (savegame != NULL)
852  delete savegame;
853 }
854 
856 {
857  // No-op in generic cockpits
858 }
859 
861 {
862  // No-op in generic cockpits
863 }
864 
865 void Cockpit::PackUnitInfo(vector< std::string > &info) const
866 {
867  info.clear();
868 
869  // First entry, current ship
870  if (GetNumUnits() > 0)
871  info.push_back(GetUnitFileName());
872 
873  // Following entries, ship/location pairs
874  for (size_t i=1,n=GetNumUnits(); i<n; ++i) {
875  info.push_back(GetUnitFileName(i));
876  info.push_back(GetUnitSystemName(i) + "@" + GetUnitBaseName(i));
877  }
878 }
879 
880 void Cockpit::UnpackUnitInfo(vector< std::string > &info)
881 {
882  vector< string > filenames, systemnames, basenames;
883 
884  // First entry, current ship
885  if (!info.empty()) {
886  filenames.push_back( info[0] );
887  systemnames.push_back( "" );
888  basenames.push_back( "" );
889  }
890 
891  // Following entries, ship/location pairs
892  for (size_t i=1, n=info.size(); i < n; i += 2) {
893  filenames.push_back( info[i] );
894 
895  string location = ((i+1) < n) ? info[i+1] : "";
896  string::size_type atpos = location.find_first_of('@');
897 
898  systemnames.push_back(location.substr(0, atpos));
899  basenames.push_back((atpos != string::npos) ? location.substr(atpos+1) : "");
900  }
901 
902  unitfilename.swap(filenames);
903  unitsystemname.swap(systemnames);
904  unitbasename.swap(basenames);
905 }
906 
907 static const std::string emptystring;
908 
909 const std::string& Cockpit::GetUnitFileName(unsigned int which) const
910 {
911  if ( which >= unitfilename.size() )
912  return emptystring;
913  else
914  return unitfilename[which];
915 }
916 
917 const std::string& Cockpit::GetUnitSystemName(unsigned int which) const
918 {
919  if ( which >= unitsystemname.size() )
920  return emptystring;
921  else
922  return unitsystemname[which];
923 }
924 
925 const std::string& Cockpit::GetUnitBaseName(unsigned int which) const
926 {
927  if ( which >= unitbasename.size() )
928  return emptystring;
929  else
930  return unitbasename[which];
931 }
932 
933 void Cockpit::RemoveUnit(unsigned int which)
934 {
935  if (which < unitfilename.size())
936  unitfilename.erase(unitfilename.begin()+which);
937  if (which < unitsystemname.size())
938  unitsystemname.erase(unitsystemname.begin()+which);
939  if (which < unitbasename.size())
940  unitbasename.erase(unitbasename.begin()+which);
941 }
942 
943 string Cockpit::MakeBaseName(const Unit *base)
944 {
945  string name;
946  if (base != NULL) {
947  if (base->getFlightgroup() != NULL)
948  name = base->getFlightgroup()->name + ':';
949  name += base->getFullname();
950  if (base->getFgSubnumber() > 0)
951  name += ':' + XMLSupport::tostring(base->getFgSubnumber());
952  }
953 
954  // remove all whitespace, it breaks savegames
955  std::replace(name.begin(), name.end(), ' ', '_');
956 
957  return name;
958 }