vegastrike  0.5.1.r1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
star_system_generic.cpp
Go to the documentation of this file.
1 #include <assert.h>
2 #include "star_system_generic.h"
3 #include "gfx/vec.h"
4 #include "cmd/planet_generic.h"
5 #include "cmd/unit_generic.h"
6 #include "cmd/unit_collide.h"
7 #include "cmd/collection.h"
8 #include "gfx/cockpit_generic.h"
9 #include "audiolib.h"
10 #include "lin_time.h"
11 #include "cmd/beam.h"
12 #include "cmd/bolt.h"
13 #include <expat.h>
14 #include "cmd/music.h"
15 #include "configxml.h"
16 #include "vs_globals.h"
17 #include "vegastrike.h"
18 #include "universe_generic.h"
19 #include "cmd/nebula_generic.h"
20 #include "galaxy_gen.h"
21 #include "cmd/script/mission.h"
22 #include "in_kb.h"
23 #include "cmd/script/flightgroup.h"
24 #include "load_mission.h"
25 #include "lin_time.h"
26 #include "cmd/unit_util.h"
27 #include "cmd/unit_factory.h"
28 #include "cmd/unit_collide.h"
29 #include "vs_random.h"
30 #include "savegame.h"
31 #include "networking/netclient.h"
32 #include "in_kb_data.h"
33 #include "universe_util.h" //get galaxy faction, dude
34 #include <boost/version.hpp>
35 #if BOOST_VERSION != 102800
36 
37 #if defined (_MSC_VER) && _MSC_VER <= 1200
38 
39 #define Vector Vactor
40 #endif
41 
42 #include "cs_boostpython.h"
43 
44 #if defined (_MSC_VER) && _MSC_VER <= 1200
45 
46 #undef Vector
47 #endif
48 
49 #else
50 
51 #include <boost/python/detail/extension_class.hpp>
52 #endif
53 vector< Vector >perplines;
54 extern std::vector< unorigdest* >pendingjump;
55 
56 void TentativeJumpTo( StarSystem *ss, Unit *un, Unit *jumppoint, const std::string &system )
57 {
58  for (unsigned int i = 0; i < pendingjump.size(); ++i)
59  if (pendingjump[i]->un.GetUnit() == un)
60  return;
61  ss->JumpTo( un, jumppoint, system );
62 }
63 
64 float ScaleJumpRadius( float radius )
65 {
66  static float jump_radius_scale = parse_float( vs_config->getVariable( "physics", "jump_radius_scale", "2" ) );
67  static float game_speed = parse_float( vs_config->getVariable( "physics", "game_speed", "1" ) );
68  //need this because sys scale doesn't affect j-point size
69  radius *= jump_radius_scale*game_speed;
70  return radius;
71 }
72 
74 {
75  stars = NULL;
76  bolts = NULL;
77  collidetable = NULL;
78  collidemap[Unit::UNIT_ONLY] = new CollideMap( Unit::UNIT_ONLY );
79  collidemap[Unit::UNIT_BOLT] = new CollideMap( Unit::UNIT_BOLT );
80 
81  no_collision_time = 0; //(int)(1+2.000/SIMULATION_ATOM);
83  name = NULL;
85  time = 0;
86  zone = 0;
87  sigIter = drawList.createIterator();
88  this->current_sim_location = 0;
89 }
90 
91 StarSystem::StarSystem( const char *filename, const Vector &centr, const float timeofyear )
92 {
93  no_collision_time = 0; //(int)(1+2.000/SIMULATION_ATOM);
94  collidemap[Unit::UNIT_ONLY] = new CollideMap( Unit::UNIT_ONLY );
95  collidemap[Unit::UNIT_BOLT] = new CollideMap( Unit::UNIT_BOLT );
96 
97  this->current_sim_location = 0;
99  name = NULL;
100  zone = 0;
102  bolts = new bolt_draw;
103  collidetable = new CollideTable( this );
105  this->filename = filename;
106  LoadXML( filename, centr, timeofyear );
107  if (!name)
108  name = strdup( filename );
109  sigIter = drawList.createIterator();
110  AddStarsystemToUniverse( filename );
111 
112  time = 0;
114 }
115 
116 extern void ClientServerSetLightContext( int lightcontext );
118 {
123  delete[] name;
124  Unit *unit;
125  for (un_iter iter = drawList.createIterator(); (unit = *iter); ++iter)
126  unit->Kill( false );
127  //if the next line goes ANYWHERE else Vega Strike will CRASH!!!!!
128  //DO NOT MOVE THIS LINE! IT MUST STAY
129  if (collidetable) delete collidetable;
131  vector< StarSystem* >activ;
132  while ( _Universe->getNumActiveStarSystem() ) {
133  if (_Universe->activeStarSystem() != this)
134  activ.push_back( _Universe->activeStarSystem() );
135  else
136  fprintf( stderr, "Avoided fatal error in deleting star system %s\n", getFileName().c_str() );
138  }
139  while ( activ.size() ) {
140  _Universe->pushActiveStarSystem( activ.back() );
141  activ.pop_back();
142  }
146  delete collidemap[Unit::UNIT_ONLY];
147  delete collidemap[Unit::UNIT_BOLT];
148 }
149 
150 /********* FROM STAR SYSTEM XML *********/
151 void setStaticFlightgroup( vector< Flightgroup* > &fg, const std::string &nam, int faction )
152 {
153  while ( faction >= (int) fg.size() ) {
154  fg.push_back( new Flightgroup() );
155  fg.back()->nr_ships = 0;
156  }
157  if (fg[faction]->nr_ships == 0) {
158  fg[faction]->flightgroup_nr = faction;
159  fg[faction]->pos.i = fg[faction]->pos.j = fg[faction]->pos.k = 0;
160  fg[faction]->nr_ships = 0;
161  fg[faction]->ainame = "default";
162  fg[faction]->faction = FactionUtil::GetFaction( faction );
163  fg[faction]->type = "Base";
164  fg[faction]->nr_waves_left = 0;
165  fg[faction]->nr_ships_left = 0;
166  fg[faction]->name = nam;
167  }
168  ++fg[faction]->nr_ships;
169  ++fg[faction]->nr_ships_left;
170 }
171 
172 Flightgroup * getStaticBaseFlightgroup( int faction )
173 {
174  //warning mem leak...not big O(num factions)
175  static vector< Flightgroup* >fg;
176  setStaticFlightgroup( fg, "Base", faction );
177  return fg[faction];
178 }
179 
180 Flightgroup * getStaticStarFlightgroup( int faction )
181 {
182  //warning mem leak...not big O(num factions)
183  static vector< Flightgroup* >fg;
184  setStaticFlightgroup( fg, "Base", faction );
185  return fg[faction];
186 }
187 
189 {
190  static vector< Flightgroup* >fg;
191  setStaticFlightgroup( fg, "Nebula", faction );
192  return fg[faction];
193 }
194 
196 {
197  static vector< Flightgroup* >fg;
198  setStaticFlightgroup( fg, "Asteroid", faction );
199  return fg[faction];
200 }
201 
203 {
204  static vector< Flightgroup* >fg;
205  setStaticFlightgroup( fg, "Unknown", faction );
206  return fg[faction];
207 }
208 
209 void StarSystem::beginElement( void *userData, const XML_Char *name, const XML_Char **atts )
210 {
211  ( (StarSystem*) userData )->beginElement( name, AttributeList( atts ) );
212 }
213 
214 void StarSystem::endElement( void *userData, const XML_Char *name )
215 {
216  ( (StarSystem*) userData )->endElement( name );
217 }
218 
219 extern string RemoveDotSystem( const char *input );
221 {
222  return getStarSystemSector( filename )+string( "/" )+RemoveDotSystem( getStarSystemName( filename ).c_str() );
223 }
224 
226 {
227  return string( name );
228 }
229 
230 void StarSystem::AddUnit( Unit *unit )
231 {
233  stats.CheckVitals( this );
234  if (unit->specInterdiction > 0 || unit->isPlanet() || unit->isJumppoint() || unit->isUnit() == ASTEROIDPTR) {
235  Unit *un;
236  bool found = false;
237  for (un_iter i = gravitationalUnits().createIterator();
238  (un = *i) != NULL;
239  ++i)
240  if (un == unit) {
241  found = true;
242  break;
243  }
244  if (!found)
245  gravitationalUnits().prepend( unit );
246  }
247  drawList.prepend( unit );
248  unit->activeStarSystem = this; //otherwise set at next physics frame...
249  UnitFactory::broadcastUnit( unit, GetZone() );
250  unsigned int priority = UnitUtil::getPhysicsPriority( unit );
251  //Do we need the +1 here or not - need to look at when current_sim_location is changed relative to this function
252  //and relative to this function, when the bucket is processed...
253  unsigned int tmp = 1+( (unsigned int) vsrandom.genrand_int32() )%priority;
254  this->physics_buffer[(this->current_sim_location+tmp)%SIM_QUEUE_SIZE].prepend( unit );
255  stats.AddUnit( unit );
256 }
257 
258 bool StarSystem::RemoveUnit( Unit *un )
259 {
260  for (unsigned int locind = 0; locind < Unit::NUM_COLLIDE_MAPS; ++locind)
261  if ( !is_null( un->location[locind] ) ) {
262  collidemap[locind]->erase( un->location[locind] );
263  set_null( un->location[locind] );
264  }
265  bool removed2 = false;
266  Unit *unit;
267  for (un_iter iter = gravitationalUnits().createIterator(); (unit = *iter); ++iter)
268  if (unit == un) {
269  iter.remove();
270  removed2 = true;
271  break; //Shouldn't be in there twice
272  }
273  //NOTE: not sure why if(1) was here, but safemode removed it
274  bool removed = false;
275  if (1) {
276  for (un_iter iter = drawList.createIterator(); (unit = *iter); ++iter)
277  if (unit == un) {
278  iter.remove();
279  removed = true;
280  break;
281  }
282  }
283  if (removed) {
284  for (unsigned int i = 0; i <= SIM_QUEUE_SIZE; ++i) {
285  Unit *unit;
286  for (un_iter iter = physics_buffer[i].createIterator(); (unit = *iter); ++iter)
287  if (unit == un) {
288  iter.remove();
289  removed = true;
290  //terminate outer loop
291  i = SIM_QUEUE_SIZE+1;
292  break;
293  }
294  }
295  stats.RemoveUnit( un );
296  }
297  return removed;
298 }
299 
301 {
302  try {
303  Unit *unit = NULL;
304  for (un_iter iter = getUnitList().createIterator(); (unit = *iter); ++iter) {
305  unit->ExecuteAI();
306  unit->ResetThreatLevel();
307  }
308  }
309  catch (const boost::python::error_already_set) {
310  if ( PyErr_Occurred() ) {
311  PyErr_Print();
312  PyErr_Clear();
313  fflush( stderr );
314  fflush( stdout );
315  } throw;
316  }
317 }
318 
319 //sorry boyz...I'm just a tourist with a frag nav console--could you tell me where I am?
320 Unit * getTopLevelOwner() //returns terrible memory--don't dereference...ever...not even aligned
321 {
322  return (Unit*) 0x31337; //FIXME How about telling us a little story behind this function? --chuck_starchaser
323 }
324 
325 void CarSimUpdate( Unit *un, float height )
326 {
327  un->SetVelocity( Vector( un->GetVelocity().i, 0, un->GetVelocity().k ) );
328  un->curr_physical_state.position = QVector( un->curr_physical_state.position.i,
329  height,
330  un->curr_physical_state.position.k );
331 }
332 
334 {
336  newfriendlycount = 0;
337  newenemycount = 0;
338  newcitizencount = 0;
339  newneutralcount = 0;
340  friendlycount = 0;
341  enemycount = 0;
342  neutralcount = 0;
343  citizencount = 0;
344  checkIter = 0;
345  navCheckIter = 0;
346 }
347 
349 {
351  if (faction != system_faction) {
352  *this = Statistics(); //invoke copy constructor to clear it
353  this->system_faction = faction;
354  Unit *un;
355  for (un_iter ui = ss->getUnitList().createIterator();
356  (un = *ui) != NULL;
357  ++ui)
358  this->AddUnit( un ); //siege will take some time
359  return; //no need to check vitals now, they're all set
360  }
361  size_t iter = navCheckIter;
362  int k = 0;
363  if ( iter >= navs[0].size() ) {
364  iter -= navs[0].size();
365  k = 1;
366  }
367  if ( iter >= navs[1].size() ) {
368  iter -= navs[1].size();
369  k = 2;
370  }
371  size_t totalnavchecking = 25;
372  size_t totalsyschecking = 25;
373  while ( iter < totalnavchecking && iter < navs[k].size() ) {
374  if (navs[k][iter].GetUnit() == NULL) {
375  navs[k].erase( navs[k].begin()+iter );
376  } else {
377  ++iter;
378  ++navCheckIter;
379  }
380  }
381  if ( k == 2 && iter >= navs[k].size() )
382  navCheckIter = 0; //start over next time
383  size_t sortedsize = ss->collidemap[Unit::UNIT_ONLY]->sorted.size();
384  int sysfac = system_faction;
385  size_t counter = checkIter+totalsyschecking;
386  for (; checkIter < counter && checkIter < sortedsize; ++checkIter) {
387  Collidable *collide = &ss->collidemap[Unit::UNIT_ONLY]->sorted[checkIter];
388  if (collide->radius > 0) {
389  Unit *un = collide->ref.unit;
390  float rel = UnitUtil::getRelationFromFaction( un, sysfac );
391  if ( FactionUtil::isCitizenInt( un->faction ) ) {
392  ++newcitizencount;
393  } else {
394  if (rel > 0.05)
395  ++newfriendlycount;
396  else if (rel < 0.)
397  ++newenemycount;
398  else
399  ++newneutralcount;
400  }
401  }
402  }
403  if (checkIter >= sortedsize && sortedsize
404  > (unsigned int) (enemycount+neutralcount+friendlycount
405  +citizencount)/4 /*suppose at least 1/4 survive a given frame*/) {
406  citizencount = newcitizencount;
407  newcitizencount = 0;
408  enemycount = newenemycount;
409  newenemycount = 0;
410  neutralcount = newneutralcount;
411  newneutralcount = 0;
412  friendlycount = newfriendlycount;
413  newfriendlycount = 0;
414  checkIter = 0; //start over with list
415  }
416 }
417 
419 {
420  float rel = UnitUtil::getRelationFromFaction( un, system_faction );
421  if ( FactionUtil::isCitizenInt( un->faction ) ) {
422  ++citizencount;
423  } else {
424  if (rel > 0.05)
425  ++friendlycount;
426  else if (rel < 0.)
427  ++enemycount;
428  else
429  ++neutralcount;
430  }
431  if ( un->GetDestinations().size() )
432  jumpPoints[un->GetDestinations()[0]].SetUnit( un );
433  if ( UnitUtil::isSignificant( un ) ) {
434  int k = 0;
435  if (rel > 0) k = 1; //base
436  if ( un->isPlanet() && !un->isJumppoint() )
437  k = 1; //friendly planet
438  //asteroid field/debris field
439  if ( UnitUtil::isAsteroid( un ) ) k = 2;
440  navs[k].push_back( UnitContainer( un ) );
441  }
442 }
443 
445 {
446  float rel = UnitUtil::getRelationFromFaction( un, system_faction );
447  if ( FactionUtil::isCitizenInt( un->faction ) ) {
448  --citizencount;
449  } else {
450  if (rel > 0.05)
451  --friendlycount;
452  else if (rel < 0.)
453  --enemycount;
454  else
455  --neutralcount;
456  }
457  if ( un->GetDestinations().size() ) {
458  //make sure it is there
459  jumpPoints[(un->GetDestinations()[0])].SetUnit( NULL );
460  //kill it--stupid I know--but hardly time critical
461  jumpPoints.erase( jumpPoints.find( un->GetDestinations()[0] ) );
462  }
463  if ( UnitUtil::isSignificant( un ) ) {
464  for (int k = 0; k < 3; ++k)
465  for (size_t i = 0; i < navs[k].size();) {
466  if (navs[k][i].GetUnit() == un)
467  //slow but who cares
468  navs[k].erase( navs[k].begin()+i );
469  else ++i; //only increment if you didn't erase current
470  }
471  }
472 }
473 
474 //Variables for debugging purposes only - eliminate later
475 unsigned int physicsframecounter = 1;
476 unsigned int theunitcounter = 0;
477 unsigned int totalprocessed = 0;
478 unsigned int movingavgarray[128] = {0};
479 unsigned int movingtotal = 0;
480 double aggfire = 0;
481 int numprocessed = 0;
482 double targetpick = 0;
483 
484 void StarSystem::RequestPhysics( Unit *un, unsigned int queue )
485 {
486  Unit *unit = NULL;
487  un_iter iter = this->physics_buffer[queue].createIterator();
488  while ( (unit = *iter) && *iter != un )
489  ++iter;
490  if (unit == un) {
491  un->predicted_priority = 0;
492  unsigned int newloc = (current_sim_location+1)%SIM_QUEUE_SIZE;
493  if (newloc != queue)
494  iter.moveBefore( this->physics_buffer[newloc] );
495  }
496 }
497 
498 void StarSystem::UpdateUnitPhysics( bool firstframe )
499 {
500  static bool phytoggle = true;
501  static int batchcount = SIM_QUEUE_SIZE-1;
502  double aitime = 0;
503  double phytime = 0;
504  double collidetime = 0;
505  double flattentime = 0;
506  double bolttime = 0;
507  targetpick = 0;
508  aggfire = 0;
509  numprocessed = 0;
510  stats.CheckVitals( this );
511  if (phytoggle) {
512  for (++batchcount; batchcount > 0; --batchcount) {
513  //BELOW COMMENTS ARE NO LONGER IN SYNCH
514  //NOTE: Randomization is necessary to preserve scattering - otherwise, whenever a
515  //unit goes from low-priority to high-priority and back to low-priority, they
516  //get synchronized and start producing peaks.
517  //NOTE2: But... randomization must come only on priority changes. Otherwise, it may
518  //interfere with subunit scheduling. Luckily, all units that make use of subunit
519  //scheduling also require a constant base priority, since otherwise priority changes
520  //will wreak havoc with subunit interpolation. Luckily again, we only need
521  //randomization on priority changes, so we're fine.
522  try {
523  Unit *unit = NULL;
524  for (un_iter iter = physics_buffer[current_sim_location].createIterator(); (unit = *iter); ++iter) {
525  int priority = UnitUtil::getPhysicsPriority( unit );
526  //Doing spreading here and only on priority changes, so as to make AI easier
527  int predprior = unit->predicted_priority;
528  //If the priority has really changed (not an initial scattering, because prediction doesn't match)
529  if (priority != predprior) {
530  if (predprior == 0)
531  //Validate snapshot of current interpolated state (this is a reschedule)
532  unit->curr_physical_state = unit->cumulative_transformation;
533  //Save priority value as prediction for next scheduling, but don't overwrite yet.
534  predprior = priority;
535  //Scatter, so as to achieve uniform distribution
536  priority = 1+( ( (unsigned int) vsrandom.genrand_int32() )%priority );
537  }
538  float backup = SIMULATION_ATOM;
540  SIMULATION_ATOM *= priority;
541  unit->sim_atom_multiplier = priority;
542  double aa = queryTime();
543  unit->ExecuteAI();
544  double bb = queryTime();
545  unit->ResetThreatLevel();
546  //FIXME "firstframe"-- assume no more than 2 physics updates per frame.
547  unit->UpdatePhysics( identity_transformation, identity_matrix, Vector( 0,
548  0,
549  0 ), priority
550  == 1 ? firstframe : true, &this->gravitationalUnits(), unit );
551  double cc = queryTime();
552  aitime += bb-aa;
553  phytime += cc-bb;
554  SIMULATION_ATOM = backup;
555  unit->predicted_priority = predprior;
556  }
557  }
558  catch (const boost::python::error_already_set) {
559  if ( PyErr_Occurred() ) {
560  PyErr_Print();
561  PyErr_Clear();
562  fflush( stderr );
563  fflush( stdout );
564  } throw;
565  }
566  double c0 = queryTime();
567  Bolt::UpdatePhysics( this );
568  double cc = queryTime();
569  last_collisions.clear();
570  double fl0 = queryTime();
571  collidemap[Unit::UNIT_BOLT]->flatten();
572  if (Unit::NUM_COLLIDE_MAPS > 1)
573  collidemap[Unit::UNIT_ONLY]->flatten( *collidemap[Unit::UNIT_BOLT] );
574  flattentime = queryTime()-fl0;
575  Unit *unit;
576  for (un_iter iter = physics_buffer[current_sim_location].createIterator(); (unit = *iter);) {
577  int priority = unit->sim_atom_multiplier;
578  float backup = SIMULATION_ATOM;
579  SIMULATION_ATOM *= priority;
580  unsigned int newloc = (current_sim_location+priority)%SIM_QUEUE_SIZE;
581  unit->CollideAll();
582  SIMULATION_ATOM = backup;
583  if (newloc == current_sim_location)
584  ++iter;
585  else
586  iter.moveBefore( physics_buffer[newloc] );
587  }
588  double dd = queryTime();
589  collidetime += dd-cc;
590  bolttime += cc-c0;
594  theunitcounter = 0;
595  }
596  } else {
597  Unit *unit = NULL;
598  for (un_iter iter = getUnitList().createIterator(); (unit = *iter); ++iter) {
599  unit->ExecuteAI();
600  last_collisions.clear();
601  unit->UpdatePhysics( identity_transformation, identity_matrix, Vector( 0,
602  0,
603  0 ), firstframe,
604  &this->gravitationalUnits(), unit );
605  unit->CollideAll();
606  }
607  }
608 }
609 
610 extern void TerrainCollide();
611 extern void UpdateAnimatedTexture();
612 extern void UpdateCameraSnds();
613 
614 extern float getTimeCompression();
615 
616 //server
618 {
619  unsigned int curcockpit = _Universe->CurrentCockpit();
620  {
621  for (unsigned int i = 0; i < active_missions.size(); ++i)
622  if (active_missions[i]) {
623  _Universe->SetActiveCockpit( active_missions[i]->player_num );
624  StarSystem *ss = _Universe->AccessCockpit()->activeStarSystem;
625  if (ss) _Universe->pushActiveStarSystem( ss );
627  active_missions[i]->DirectorLoop();
628  if (ss) _Universe->popActiveStarSystem();
629  }
630  }
631  _Universe->SetActiveCockpit( curcockpit );
634  {
635  for (unsigned int i = 1; i < active_missions.size();) {
636  if (active_missions[i]) {
637  if (active_missions[i]->runtime.pymissions) {
638  ++i;
639  } else {
640  unsigned int w = active_missions.size();
641  active_missions[i]->terminateMission();
642  if ( w == active_missions.size() ) {
643  printf( "MISSION NOT ERASED\n" );
644  break;
645  }
646  }
647  } else {
648  active_missions.Get()->erase( active_missions.Get()->begin()+i );
649  }
650  }
651  }
652 }
653 
655 {
656  return(*sigIter);
657 }
658 
659 void StarSystem::Update( float priority )
660 {
661  Unit *unit;
662  bool firstframe = true;
663  //No time compression here
664  float normal_simulation_atom = SIMULATION_ATOM;
665  time += GetElapsedTime();
667  if ( time/SIMULATION_ATOM >= (1./PHY_NUM) ) {
668  while ( time/SIMULATION_ATOM >= (1.) ) {
669  //Chew up all SIMULATION_ATOMs that have elapsed since last update
670  ExecuteDirector();
671  TerrainCollide();
672  Unit::ProcessDeleteQueue();
674  collidetable->Update();
675  for (un_iter iter = drawList.createIterator(); (unit = *iter); ++iter)
676  unit->SetNebula( NULL );
677  UpdateMissiles(); //do explosions
678  UpdateUnitPhysics( firstframe );
679 
680  firstframe = false;
681  }
683  }
684  SIMULATION_ATOM = normal_simulation_atom;
686 }
687 
688 //client
689 void StarSystem::Update( float priority, bool executeDirector )
690 {
691  bool firstframe = true;
692  double pythontime = 0;
694  for (unsigned int k = 0; k < _Universe->numPlayers(); ++k)
695  if (_Universe->AccessCockpit( k )->activeStarSystem == this)
696  priority = 1;
697  float normal_simulation_atom = SIMULATION_ATOM;
698  SIMULATION_ATOM /= ( priority/getTimeCompression() );
700  time += GetElapsedTime();
702  //WARNING PERFORMANCE HACK!!!!!
703  if (time > 2*SIMULATION_ATOM)
704  time = 2*SIMULATION_ATOM;
705  double bolttime = 0;
706  if ( time/SIMULATION_ATOM >= (1./PHY_NUM) ) {
707  //Chew up all SIMULATION_ATOMs that have elapsed since last update
708  while ( time/SIMULATION_ATOM >= (1./PHY_NUM) ) {
710  TerrainCollide();
712  Unit::ProcessDeleteQueue();
713  double pythonidea = queryTime();
716  if (executeDirector)
717  ExecuteDirector();
718  pythontime = queryTime()-pythonidea;
719  static int dothis = 0;
720  if ( this == _Universe->getActiveStarSystem( 0 ) )
721  if ( (++dothis)%2 == 0 )
723  for (unsigned int i = 0; i < active_missions.size(); ++i)
724  //waste of farkin time
725  active_missions[i]->BriefingUpdate();
727  } else if (current_stage == PROCESS_UNIT) {
728  UpdateUnitPhysics( firstframe );
729  UpdateMissiles(); //do explosions
730  collidetable->Update();
731  if ( this == _Universe->getActiveStarSystem( 0 ) )
733  bolttime = queryTime();
734  bolttime = queryTime()-bolttime;
736  firstframe = false;
737  }
738  time -= (1./PHY_NUM)*SIMULATION_ATOM;
739  }
740  unsigned int i = _Universe->CurrentCockpit();
741  for (unsigned int j = 0; j < _Universe->numPlayers(); ++j)
742  if (_Universe->AccessCockpit( j )->activeStarSystem == this) {
744  _Universe->AccessCockpit( j )->updateAttackers();
745  if ( _Universe->AccessCockpit( j )->Update() ) {
746  SIMULATION_ATOM = normal_simulation_atom;
749  return;
750  }
751  }
753  }
754  if ( sigIter.isDone() )
755  sigIter = drawList.createIterator();
756  else
757  ++sigIter;
758  while ( !sigIter.isDone() && !UnitUtil::isSignificant( *sigIter) )
759  ++sigIter;
760  //If it is done, leave it NULL for this frame then.
761  //WARNING cockpit does not get here...
762  SIMULATION_ATOM = normal_simulation_atom;
763  //WARNING cockpit does not get here...
765 }
766 
767 /*
768  **************************************************************************************
769  *** STAR SYSTEM JUMP STUFF **
770  **************************************************************************************
771  */
772 
774 
775 void StarSystem::AddStarsystemToUniverse( const string &mname )
776 {
777  star_system_table.Put( mname, this );
778 }
779 
781 {
782  if ( star_system_table.Get( filename ) )
783  star_system_table.Delete( filename );
784 }
785 
786 StarSystem * GetLoadedStarSystem( const char *system )
787 {
788  StarSystem *ss = star_system_table.Get( string( system ) );
789  std::string ssys( string( system )+string( ".system" ) );
790  if (!ss)
791  ss = star_system_table.Get( ssys );
792  return ss;
793 }
794 
795 std::vector< unorigdest* >pendingjump;
796 
798 {
799  return pendingjump.empty();
800 }
801 
802 extern void SetShieldZero( Unit* );
803 
805 {
806  for (unsigned int kk = 0; kk < pendingjump.size(); ++kk) {
807  Unit *un = pendingjump[kk]->un.GetUnit();
808  if (pendingjump[kk]->delay >= 0) {
809  Unit *jp = pendingjump[kk]->jumppoint.GetUnit();
810  if (un && jp) {
811  QVector delta = ( jp->LocalPosition()-un->LocalPosition() );
812  float dist = delta.Magnitude();
813  if (pendingjump[kk]->delay > 0) {
814  float speed = dist/pendingjump[kk]->delay;
815  bool player = (_Universe->isPlayerStarship( un ) != NULL);
816  if (dist > 10 && player) {
817  if (un->activeStarSystem == pendingjump[kk]->orig)
818  un->SetCurPosition( un->LocalPosition()+SIMULATION_ATOM*delta*(speed/dist) );
819  } else if (!player) {
820  un->SetVelocity( Vector( 0, 0, 0 ) );
821  }
822  static bool setshieldzero =
823  XMLSupport::parse_bool( vs_config->getVariable( "physics", "jump_disables_shields", "true" ) );
824  if (setshieldzero)
825  SetShieldZero( un );
826  }
827  }
828  double time = GetElapsedTime();
829  if (time > 1)
830  time = 1;
831  pendingjump[kk]->delay -= time;
832  continue;
833  } else {
834 #ifdef JUMP_DEBUG
835  VSFileSystem::vs_fprintf( stderr, "Volitalizing pending jump animation.\n" );
836 #endif
838  }
839  int playernum = _Universe->whichPlayerStarship( un );
840  //In non-networking mode or in networking mode or a netplayer wants to jump and is ready or a non-player jump
841  if ( Network == NULL || playernum < 0 || ( Network != NULL && playernum >= 0 && Network[playernum].readyToJump() ) ) {
842  Unit *un = pendingjump[kk]->un.GetUnit();
843  StarSystem *savedStarSystem = _Universe->activeStarSystem();
844  //Download client descriptions of the new zone (has to be blocking)
845  if (Network != NULL)
846  Network[playernum].downloadZoneInfo();
847  if ( un == NULL || !_Universe->StillExists( pendingjump[kk]->dest )
848  || !_Universe->StillExists( pendingjump[kk]->orig ) ) {
849 #ifdef JUMP_DEBUG
850  VSFileSystem::vs_fprintf( stderr, "Adez Mon! Unit destroyed during jump!\n" );
851 #endif
852  delete pendingjump[kk];
853  pendingjump.erase( pendingjump.begin()+kk );
854  --kk;
855  continue;
856  }
857  bool dosightandsound = ( (pendingjump[kk]->dest == savedStarSystem) || _Universe->isPlayerStarship( un ) );
859  if ( un->TransferUnitToSystem( kk, savedStarSystem, dosightandsound ) )
860  un->DecreaseWarpEnergy( false, 1.0f );
861  if (dosightandsound)
863  _Universe->AccessCockpit()->OnJumpEnd(un);
864  delete pendingjump[kk];
865  pendingjump.erase( pendingjump.begin()+kk );
866  --kk;
867  _Universe->setActiveStarSystem( savedStarSystem );
868  //In networking mode we tell the server we want to go back in game
869  if (Network != NULL) {
870  //Find the corresponding networked player
871  if (playernum >= 0) {
872  Network[playernum].inGame();
873  Network[playernum].unreadyToJump();
874  }
875  }
876  }
877  }
878 }
879 
880 double calc_blend_factor( double frac, int priority, unsigned int when_it_will_be_simulated, int cur_simulation_frame )
881 {
882  if (when_it_will_be_simulated == SIM_QUEUE_SIZE) {
883  return 1;
884  } else {
885  int relwas = when_it_will_be_simulated-priority;
886  if (relwas < 0) relwas += SIM_QUEUE_SIZE;
887  int relcur = cur_simulation_frame-relwas-1;
888  if (relcur < 0) relcur += SIM_QUEUE_SIZE;
889  return (relcur+frac)/(double) priority;
890  }
891 }
892 
893 void ActivateAnimation( Unit *jumppoint )
894 {
895  jumppoint->graphicOptions.Animating = 1;
896  Unit *un;
897  for (un_iter i = jumppoint->getSubUnits(); NULL != (un = *i); ++i)
898  ActivateAnimation( un );
899 }
900 
901 static bool isJumping( const vector< unorigdest* > &pending, Unit *un )
902 {
903  for (size_t i = 0; i < pending.size(); ++i)
904  if (pending[i]->un == un)
905  return true;
906  return false;
907 }
908 
909 QVector SystemLocation( std::string system );
910 double howFarToJump();
911 QVector ComputeJumpPointArrival( QVector pos, std::string origin, std::string destination )
912 {
913  QVector finish = SystemLocation( destination );
914  QVector start = SystemLocation( origin );
915  QVector dir = finish-start;
916  if ( dir.MagnitudeSquared() ) {
917  dir.Normalize();
918  dir = -dir;
919  pos = -pos;
920  pos.Normalize();
921  if ( pos.MagnitudeSquared() ) pos.Normalize();
922  return (dir*.5+pos*.125)*howFarToJump();
923  }
924  return QVector( 0, 0, 0 );
925 }
926 
927 bool StarSystem::JumpTo( Unit *un, Unit *jumppoint, const std::string &system, bool force, bool save_coordinates )
928 {
929  if ( ( un->DockedOrDocking()&(~Unit::DOCKING_UNITS) ) != 0 )
930  return false;
931  if (Network == NULL || force) {
932  if (un->jump.drive >= 0)
933  un->jump.drive = -1;
934 #ifdef JUMP_DEBUG
935  VSFileSystem::vs_fprintf( stderr, "jumping to %s. ", system.c_str() );
936 #endif
937  StarSystem *ss = star_system_table.Get( system );
938  std::string ssys( system+".system" );
939  if (!ss)
940  ss = star_system_table.Get( ssys );
941  bool justloaded = false;
942  if (!ss) {
943  justloaded = true;
944  ss = _Universe->GenerateStarSystem( ssys.c_str(), filename.c_str(), Vector( 0, 0, 0 ) );
945  //NETFIXME: Do we want to generate the system if an AI unit jumps?
946  }
947  if ( ss && !isJumping( pendingjump, un ) ) {
948 #ifdef JUMP_DEBUG
949  VSFileSystem::vs_fprintf( stderr, "Pushing back to pending queue!\n" );
950 #endif
951  bool dosightandsound = ( ( this == _Universe->getActiveStarSystem( 0 ) ) || _Universe->isPlayerStarship( un ) );
952  int ani = -1;
953  if (dosightandsound)
955  _Universe->AccessCockpit()->OnJumpBegin(un);
956  pendingjump.push_back( new unorigdest( un, jumppoint, this, ss, un->GetJumpStatus().delay, ani, justloaded,
957  save_coordinates ? ComputeJumpPointArrival( un->Position(), this->getFileName(),
958  system ) : QVector( 0, 0, 0 ) ) );
959  } else {
960 #ifdef JUMP_DEBUG
961  VSFileSystem::vs_fprintf( stderr, "Failed to retrieve!\n" );
962 #endif
963  return false;
964  }
965  if (jumppoint)
966  ActivateAnimation( jumppoint );
967  } else
968  //Networking mode
969  if (jumppoint) {
970  Network->jumpRequest( system, jumppoint->GetSerial() );
971  }
972  return true;
973 }
974