From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_sim_8cpp_source.html | 3930 ++++++++++++++++++++++++++++++++ 1 file changed, 3930 insertions(+) create mode 100644 Doc/doxygen/html/_sim_8cpp_source.html (limited to 'Doc/doxygen/html/_sim_8cpp_source.html') diff --git a/Doc/doxygen/html/_sim_8cpp_source.html b/Doc/doxygen/html/_sim_8cpp_source.html new file mode 100644 index 0000000..8fdc1c5 --- /dev/null +++ b/Doc/doxygen/html/_sim_8cpp_source.html @@ -0,0 +1,3930 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/Sim.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
Sim.cpp
+
+
+Go to the documentation of this file.
1 /* Project Starshatter 5.0
+
2  Destroyer Studios LLC
+
3  Copyright (C) 1997-2007. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: Stars.exe
+
6  FILE: Sim.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  Simulation Universe and Region classes
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "Sim.h"
+
17 #include "SimEvent.h"
+
18 #include "SimObject.h"
+
19 #include "Starshatter.h"
+
20 #include "StarSystem.h"
+
21 #include "Contact.h"
+
22 #include "Ship.h"
+
23 #include "ShipDesign.h"
+
24 #include "Element.h"
+
25 #include "Instruction.h"
+
26 #include "RadioTraffic.h"
+
27 #include "Shot.h"
+
28 #include "Drone.h"
+
29 #include "Explosion.h"
+
30 #include "Debris.h"
+
31 #include "Asteroid.h"
+
32 #include "Drive.h"
+
33 #include "QuantumDrive.h"
+
34 #include "Sensor.h"
+
35 #include "NavLight.h"
+
36 #include "Shield.h"
+
37 #include "Weapon.h"
+
38 #include "WeaponGroup.h"
+
39 #include "Hangar.h"
+
40 #include "FlightDeck.h"
+
41 #include "Sky.h"
+
42 #include "Grid.h"
+
43 #include "MFD.h"
+
44 #include "AudioConfig.h"
+
45 #include "Mission.h"
+
46 #include "MissionEvent.h"
+
47 #include "CameraDirector.h"
+
48 #include "MusicDirector.h"
+
49 #include "Combatant.h"
+
50 #include "CombatGroup.h"
+
51 #include "CombatUnit.h"
+
52 #include "HUDView.h"
+
53 #include "SeekerAI.h"
+
54 #include "ShipAI.h"
+
55 #include "Power.h"
+
56 #include "Callsign.h"
+
57 #include "GameScreen.h"
+
58 #include "Terrain.h"
+
59 #include "TerrainPatch.h"
+
60 
+
61 #include "NetGame.h"
+
62 #include "NetClientConfig.h"
+
63 #include "NetServerConfig.h"
+
64 #include "NetPlayer.h"
+
65 #include "NetUtil.h"
+
66 #include "NetData.h"
+
67 
+
68 #include "Game.h"
+
69 #include "Sound.h"
+
70 #include "Bolt.h"
+
71 #include "Solid.h"
+
72 #include "Sprite.h"
+
73 #include "Light.h"
+
74 #include "Bitmap.h"
+
75 #include "DataLoader.h"
+
76 #include "ParseUtil.h"
+
77 #include "MouseController.h"
+
78 #include "Player.h"
+
79 #include "Random.h"
+
80 #include "Video.h"
+
81 
+
82 const char* FormatGameTime();
+
83 
+
84 // +--------------------------------------------------------------------+
+
85 
+
86 class SimHyper
+
87 {
+
88 public:
+
89  SimHyper(Ship* o, SimRegion* r, const Point& l, int t, bool h, Ship* fc1, Ship* fc2)
+
90  : ship(o), rgn(r), loc(l), type(t), hyperdrive(h), fc_src(fc1), fc_dst(fc2) { }
+
91 
+ + + +
95  int type;
+
96  bool hyperdrive;
+ + +
99 };
+
100 
+
101 // +--------------------------------------------------------------------+
+
102 
+ +
104 {
+
105 public:
+
106  SimSplash(SimRegion* r, const Point& l, double d, double n)
+
107  : rgn(r), loc(l), damage(d), range(n),
+
108  owner_name("Collateral Damage"), missile(false) { }
+
109 
+ + +
112  double damage;
+
113  double range;
+ +
115  bool missile;
+
116 };
+
117 
+
118 // +--------------------------------------------------------------------+
+
119 
+
120 static bool first_frame = true;
+
121 Sim* Sim::sim = 0;
+
122 
+ +
124 : ctrl(c), test_mode(false), grid_shown(false), dust(0),
+
125 star_system(0), active_region(0), mission(0), netgame(0),
+
126 start_time(0)
+
127 {
+ + + + + +
133  MFD::Initialize();
+ +
135 
+
136  if (!sim)
+
137  sim = this;
+
138 
+ +
140 }
+
141 
+ +
143 {
+
144  UnloadMission();
+
145 
+
146  Shot::Close();
+ +
148  NavLight::Close();
+
149  Token::close();
+
150  Asteroid::Close();
+
151 
+
152  if (sim == this)
+
153  sim = 0;
+
154 }
+
155 
+
156 // +--------------------------------------------------------------------+
+
157 
+
158 void
+ +
160 {
+
161  for (int i = 0; i < regions.size(); i++)
+
162  regions[i]->CommitMission();
+
163 
+
164  if (ShipStats::NumStats() > 0) {
+
165  Print("\n\nFINAL SCORE '%s'\n", (const char*) mission->Name());
+
166  Print("Name Kill1 Kill2 Died Colls Points Cmd Pts\n");
+
167  Print("---------------- ----- ----- ----- ----- ------ ------\n");
+
168 
+
169  int tk1 = 0;
+
170  int tk2 = 0;
+
171  int td = 0;
+
172  int tc = 0;
+
173 
+
174  for (int i = 0; i < ShipStats::NumStats(); i++) {
+ +
176  s->Summarize();
+
177 
+
178  Print("%-16s %5d %5d %5d %5d %6d %6d\n",
+
179  s->GetName(),
+
180  s->GetGunKills(),
+
181  s->GetMissileKills(),
+
182  s->GetDeaths(),
+
183  s->GetColls(),
+
184  s->GetPoints(),
+
185  s->GetCommandPoints());
+
186 
+
187  tk1 += s->GetGunKills();
+
188  tk2 += s->GetMissileKills();
+
189  td += s->GetDeaths();
+
190  tc += s->GetColls();
+
191 
+
192  CombatGroup* group = s->GetCombatGroup();
+
193 
+
194  if (group) {
+
195  Combatant* c = group->GetCombatant();
+
196 
+
197  if (c)
+
198  c->AddScore(s->GetPoints());
+
199 
+
200  if (s->GetElementIndex() == 1)
+
201  group->SetSorties(group->Sorties() + 1);
+
202 
+
203  group->SetKills(group->Kills() + s->GetGunKills() + s->GetMissileKills());
+
204  group->SetPoints(group->Points() + s->GetPoints());
+
205  }
+
206 
+
207  if (s->IsPlayer()) {
+ +
209  p->ProcessStats(s, start_time);
+
210 
+
211  if (mission && mission->Type() == Mission::TRAINING &&
+
212  s->GetDeaths() == 0 && s->GetColls() == 0)
+
213  p->SetTrained(mission->Identity());
+
214 
+
215  Player::Save(); // save training state right now before we forget!
+
216  }
+
217  }
+
218 
+
219  Print("--------------------------------------------\n");
+
220  Print("TOTAL %5d %5d %5d %5d\n\n", tk1, tk2, td, tc);
+
221 
+ +
223  }
+
224 }
+
225 
+
226 // +--------------------------------------------------------------------+
+
227 
+
228 void
+ +
230 {
+
231  if (netgame) {
+
232  delete netgame;
+
233  netgame = 0;
+
234  }
+
235 
+
236  HUDView* hud = HUDView::GetInstance();
+
237  if (hud)
+
238  hud->HideAll();
+
239 
+ +
241 
+
242  events.destroy();
+ +
244  elements.destroy();
+
245  finished.destroy();
+
246 
+
247  if (active_region)
+ +
249 
+
250  if (star_system)
+ +
252 
+
253  if (mission) {
+
254  mission->SetActive(false);
+
255  mission->SetComplete(true);
+
256  }
+
257 
+
258  regions.destroy();
+
259  scene.Collect();
+
260 
+ +
262 
+
263  star_system = 0;
+
264  active_region = 0;
+
265  mission = 0;
+
266 
+
267  // reclaim memory used by radio traffic:
+ +
269 
+
270  // release texture memory for 2D screens:
+ +
272  if (stars)
+
273  stars->InvalidateTextureCache();
+
274 
+ +
276  if (cam_dir)
+
277  cam_dir->SetShip(0);
+
278 
+ +
280 }
+
281 
+
282 bool
+ +
284 {
+
285  return mission && mission->IsActive();
+
286 }
+
287 
+
288 bool
+ +
290 {
+
291  return mission && mission->IsComplete();
+
292 }
+
293 
+
294 // +--------------------------------------------------------------------+
+
295 
+
296 void
+
297 Sim::LoadMission(Mission* m, bool preload_textures)
+
298 {
+ +
300 
+
301  if (!mission) {
+
302  mission = m;
+
303  mission->SetActive(true);
+
304 
+
305  if (preload_textures) {
+
306  Video* video = Game::GetVideo();
+
307  List<Model> all_models;
+
308  //List<Bitmap> all_textures;
+
309 
+ +
311  while (++elem_iter) {
+
312  MissionElement* elem = elem_iter.value();
+
313  const ShipDesign* design = elem->GetDesign();
+
314 
+
315  if (design) {
+
316  for (int i = 0; i < 4; i++) {
+
317  List<Model>& models = (List<Model>&) design->models[i]; // cast-away const
+
318 
+
319  ListIter<Model> model_iter = models;
+
320  while (++model_iter) {
+
321  Model* model = model_iter.value();
+
322  if (!all_models.contains(model)) {
+
323  all_models.append(model);
+
324  //model->GetAllTextures(all_textures);
+
325 
+
326  ListIter<Surface> surf_iter = model->GetSurfaces();
+
327  while (++surf_iter) {
+
328  Surface* surface = surf_iter.value();
+
329  video->PreloadSurface(surface);
+
330  }
+
331  }
+
332  }
+
333  }
+
334  }
+
335  }
+
336 
+
337  /*
+
338  if (video && all_textures.size() > 0) {
+
339  ::Print("Preloading %d textures into video texture cache\n", all_textures.size());
+
340  ListIter<Bitmap> bmp_iter = all_textures;
+
341  while (++bmp_iter) {
+
342  Bitmap* bmp = bmp_iter.value();
+
343  video->PreloadTexture(bmp);
+
344  }
+
345  }
+
346  */
+
347  }
+
348  }
+
349 }
+
350 
+
351 void
+ +
353 {
+ +
355 
+
356  if (!mission) {
+
357  Print("Sim::ExecMission() - No mission to execute.\n");
+
358  return;
+
359  }
+
360 
+
361  if (elements.size() || finished.size()) {
+
362  Print("Sim::ExecMission(%s) mission is already executing.\n", mission->Name());
+
363  return;
+
364  }
+
365 
+
366  Print("\nExec Mission: '%s'\n", (const char*) mission->Name());
+
367 
+
368  if (cam_dir)
+
369  cam_dir->Reset();
+
370 
+
371  if (mission->Stardate() > 0)
+ +
373 
+ + +
376 
+
377  int dust_factor = 0;
+
378 
+ +
380  dust_factor = Starshatter::GetInstance()->Dust();
+
381 
+
382  if (star_system->NumDust() * dust_factor) {
+
383  dust = new(__FILE__,__LINE__) Dust(star_system->NumDust() * 2*(dust_factor+1), dust_factor > 1);
+ +
385  }
+
386 
+
387  CreateRegions();
+
388  BuildLinks();
+
389  CreateElements();
+
390  CopyEvents();
+
391 
+
392  if (netgame) {
+
393  delete netgame;
+
394  netgame = 0;
+
395  }
+
396 
+
397  first_frame = true;
+ +
399 
+ +
401 }
+
402 
+
403 // +--------------------------------------------------------------------+
+
404 
+
405 void
+ +
407 {
+
408  const char* active_region_name = 0;
+
409 
+
410  if (mission)
+
411  active_region_name = mission->GetRegion();
+
412 
+ +
414  while (++iter) {
+
415  StarSystem* sys = iter.value();
+
416 
+
417  // insert objects from star system:
+
418  ListIter<OrbitalBody> star = sys->Bodies();
+
419  while (++star) {
+
420  ListIter<OrbitalBody> planet = star->Satellites();
+
421  while (++planet) {
+
422  ListIter<OrbitalBody> moon = planet->Satellites();
+
423  while (++moon) {
+
424  ListIter<OrbitalRegion> rgn = moon->Regions();
+
425  while (++rgn) {
+
426  SimRegion* sim_region = new(__FILE__,__LINE__) SimRegion(this, rgn.value());
+
427  regions.append(sim_region);
+
428  if (!strcmp(active_region_name, sim_region->Name())) {
+
429  ActivateRegion(sim_region);
+
430  }
+
431  }
+
432  }
+
433 
+
434  ListIter<OrbitalRegion> rgn = planet->Regions();
+
435  while (++rgn) {
+
436  SimRegion* sim_region = new(__FILE__,__LINE__) SimRegion(this, rgn.value());
+
437  regions.append(sim_region);
+
438  if (!strcmp(active_region_name, sim_region->Name())) {
+
439  ActivateRegion(sim_region);
+
440  }
+
441  }
+
442  }
+
443 
+
444  ListIter<OrbitalRegion> rgn = star->Regions();
+
445  while (++rgn) {
+
446  SimRegion* sim_region = new(__FILE__,__LINE__) SimRegion(this, rgn.value());
+
447  regions.append(sim_region);
+
448  if (!strcmp(active_region_name, sim_region->Name())) {
+
449  ActivateRegion(sim_region);
+
450  }
+
451  }
+
452  }
+
453  }
+
454 }
+
455 
+
456 // +--------------------------------------------------------------------+
+
457 
+
458 void
+ +
460 {
+ +
462  while (++iter) {
+
463  SimRegion* rgn = iter.value();
+
464  OrbitalRegion* orb = rgn->GetOrbitalRegion();
+
465 
+
466  if (orb) {
+
467  ListIter<Text> lnk_iter = orb->Links();
+
468  while (++lnk_iter) {
+
469  Text* t = lnk_iter.value();
+
470 
+
471  SimRegion* tgt = FindRegion(*t);
+
472 
+
473  if (tgt && !rgn->Links().contains(tgt))
+
474  rgn->Links().append(tgt);
+
475  }
+
476  }
+
477  }
+
478 }
+
479 
+
480 void
+ +
482 {
+ +
484  while (++e_iter) {
+
485  MissionElement* msn_elem = e_iter.value();
+
486 
+
487  // add element to a carrier?
+
488  if (msn_elem->IsSquadron()) {
+
489  Ship* carrier = FindShip(msn_elem->Carrier());
+
490  if (carrier) {
+
491  Hangar* hangar = carrier->GetHangar();
+
492 
+
493  if (hangar) {
+
494  int* def_load = 0;
+
495 
+
496  if (msn_elem->Loadouts().size()) {
+
497  MissionLoad* m = msn_elem->Loadouts().at(0);
+
498 
+
499  if (m->GetName().length()) {
+
500  ShipDesign* dsn = (ShipDesign*) msn_elem->GetDesign();
+
501  ListIter<ShipLoad> sl_iter = dsn->loadouts;
+
502  while (++sl_iter) {
+
503  ShipLoad* sl = sl_iter.value();
+
504 
+
505  if (m->GetName() == sl->name)
+
506  def_load = sl->load;
+
507  }
+
508  }
+
509 
+
510  if (!def_load) {
+
511  def_load = m->GetStations();
+
512  }
+
513  }
+
514 
+
515  hangar->CreateSquadron(msn_elem->Name(), msn_elem->GetCombatGroup(),
+
516  msn_elem->GetDesign(), msn_elem->Count(),
+
517  msn_elem->GetIFF(),
+
518  def_load, msn_elem->MaintCount(), msn_elem->DeadCount());
+
519 
+
520  Element* element = CreateElement(msn_elem->Name(),
+
521  msn_elem->GetIFF(),
+
522  msn_elem->MissionRole());
+
523 
+
524  element->SetCarrier(carrier);
+
525  element->SetCombatGroup(msn_elem->GetCombatGroup());
+
526  element->SetCombatUnit(msn_elem->GetCombatUnit());
+
527  element->SetCount(msn_elem->Count());
+
528  element->SetRogue(false);
+
529  element->SetPlayable(false);
+
530  element->SetLoadout(def_load);
+
531  }
+
532  }
+
533  }
+
534 
+
535  // create the element in space:
+
536  else {
+
537  Ship* carrier = 0;
+
538  Hangar* hangar = 0;
+
539  int squadron = -1;
+
540  int slot = 0;
+
541 
+
542  // first create the package element:
+
543  Element* element = CreateElement(msn_elem->Name(),
+
544  msn_elem->GetIFF(),
+
545  msn_elem->MissionRole());
+
546 
+
547  element->SetPlayer(msn_elem->Player());
+
548  element->SetCombatGroup(msn_elem->GetCombatGroup());
+
549  element->SetCombatUnit(msn_elem->GetCombatUnit());
+
550  element->SetCommandAILevel(msn_elem->CommandAI());
+
551  element->SetHoldTime(msn_elem->HoldTime());
+
552  element->SetZoneLock(msn_elem->ZoneLock() ? true : false);
+
553  element->SetRogue(msn_elem->IsRogue());
+
554  element->SetPlayable(msn_elem->IsPlayable());
+
555  element->SetIntelLevel(msn_elem->IntelLevel());
+
556 
+
557  // if this is the player's element, make sure to activate the region:
+
558  if (msn_elem->Player()) {
+
559  SimRegion* rgn = FindRegion(msn_elem->Region());
+
560 
+
561  if (rgn && rgn != active_region)
+
562  ActivateRegion(rgn);
+
563  }
+
564 
+
565  // if element belongs to a squadron,
+
566  // find the carrier, squadron, flight deck, etc.:
+
567  if (msn_elem->Squadron().length() > 0) {
+
568  MissionElement* squadron_elem = mission->FindElement(msn_elem->Squadron());
+
569 
+
570  if (squadron_elem) {
+
571  element->SetSquadron(msn_elem->Squadron());
+
572 
+
573  Element* cmdr = FindElement(squadron_elem->Carrier());
+
574 
+
575  if (cmdr) {
+
576  element->SetCommander(cmdr);
+
577  carrier = cmdr->GetShip(1);
+
578 
+
579  if (carrier) {
+
580  element->SetCarrier(carrier);
+
581  hangar = carrier->GetHangar();
+
582 
+
583  for (int s = 0; s < hangar->NumSquadrons(); s++) {
+
584  if (hangar->SquadronName(s) == msn_elem->Squadron()) {
+
585  squadron = s;
+
586  break;
+
587  }
+
588  }
+
589  }
+
590  }
+
591  }
+
592  }
+
593 
+
594  else if (msn_elem->Commander().length() > 0) {
+
595  Element* cmdr = FindElement(msn_elem->Commander());
+
596 
+
597  if (cmdr) {
+
598  element->SetCommander(cmdr);
+
599  }
+
600  }
+
601 
+
602  ListIter<Instruction> obj = msn_elem->Objectives();
+
603  while (++obj) {
+
604  Instruction* o = obj.value();
+
605  Instruction* instr = 0;
+
606 
+
607  instr = new(__FILE__,__LINE__) Instruction(*o);
+
608 
+
609  element->AddObjective(instr);
+
610  }
+
611 
+
612  if (msn_elem->Instructions().size() > 0) {
+
613  ListIter<Text> instr = msn_elem->Instructions();
+
614  while (++instr) {
+
615  element->AddInstruction(*instr);
+
616  }
+
617  }
+
618 
+
619  ListIter<Instruction> nav = msn_elem->NavList();
+
620  while (++nav) {
+
621  SimRegion* rgn = FindRegion(nav->RegionName());
+
622 
+
623  if (!rgn)
+
624  rgn = FindRegion(msn_elem->Region());
+
625 
+
626  if (rgn) {
+
627  Instruction* npt = new(__FILE__,__LINE__)
+
628  Instruction(rgn, nav->Location(), nav->Action());
+
629 
+
630  npt->SetStatus(nav->Status());
+
631  npt->SetEMCON(nav->EMCON());
+
632  npt->SetFormation(nav->Formation());
+
633  npt->SetSpeed(nav->Speed());
+
634  npt->SetTarget(nav->TargetName());
+
635  npt->SetHoldTime(nav->HoldTime());
+
636  npt->SetFarcast(nav->Farcast());
+
637 
+
638  element->AddNavPoint(npt);
+
639  }
+
640  }
+
641 
+
642  bool alertPrep = false;
+
643  int* loadout = 0;
+
644  int respawns = msn_elem->RespawnCount();
+
645 
+
646  // if ships are to start on alert,
+
647  // spot them onto the appropriate launch deck:
+
648  if (hangar && element && msn_elem->Count() > 0 && msn_elem->IsAlert()) {
+
649  FlightDeck* deck = 0;
+
650  int queue = 1000;
+
651  const ShipDesign* dsn = msn_elem->GetDesign();
+
652 
+
653  if (dsn) {
+
654  for (int i = 0; i < carrier->NumFlightDecks(); i++) {
+
655  FlightDeck* d = carrier->GetFlightDeck(i);
+
656  int dq = hangar->PreflightQueue(d);
+
657 
+
658  if (d && d->IsLaunchDeck() && d->SpaceLeft(dsn->type) && dq < queue) {
+
659  queue = dq;
+
660  deck = d;
+
661  }
+
662  }
+
663  }
+
664 
+
665  if (deck) {
+
666  alertPrep = true;
+
667 
+
668  // choose best loadout:
+
669  if (msn_elem->Loadouts().size()) {
+
670  MissionLoad* l = msn_elem->Loadouts().at(0);
+
671  if (l->GetName().length()) {
+
672  ListIter<ShipLoad> sl = ((ShipDesign*) dsn)->loadouts;
+
673  while (++sl) {
+
674  if (!_stricmp(sl->name, l->GetName()))
+
675  loadout = sl->load;
+
676  }
+
677  }
+
678 
+
679  else {
+
680  loadout = l->GetStations();
+
681  }
+
682  }
+
683 
+
684  element->SetLoadout(loadout);
+
685 
+
686  for (int i = 0; i < msn_elem->Count(); i++) {
+
687  int squadron = -1;
+
688  int slot = -1;
+
689 
+
690  if (hangar->FindAvailSlot(msn_elem->GetDesign(), squadron, slot)) {
+
691  alertPrep = alertPrep &&
+
692  hangar->GotoAlert(squadron,
+
693  slot,
+
694  deck,
+
695  element,
+
696  loadout,
+
697  true, // package for launch
+
698  true); // expedite
+
699 
+
700  HangarSlot* s = (HangarSlot*) hangar->GetSlot(squadron, slot);
+
701  Ship* alertShip = hangar->GetShip(s);
+
702 
+
703  if (alertShip) {
+
704  alertShip->SetRespawnCount(respawns);
+
705 
+
706  if (msn_elem->Player() == i+1) {
+
707  if (alertShip->GetRegion()) {
+
708  alertShip->GetRegion()->SetPlayerShip(alertShip);
+
709  }
+
710  else {
+
711  ::Print("WARNING: alert ship '%s' region is null\n", alertShip->Name());
+
712  }
+
713  }
+
714  }
+
715  }
+
716  }
+
717  }
+
718  }
+
719 
+
720  if (!alertPrep) {
+
721  // then, create the ships:
+
722  for (int i = 0; i < msn_elem->Count(); i++) {
+
723  MissionShip* msn_ship = 0;
+
724  Text sname = msn_elem->GetShipName(i);
+
725  Text rnum = msn_elem->GetRegistry(i);
+
726  Text rgn_name = msn_elem->Region();
+
727 
+
728  if (msn_elem->Ships().size() > i) {
+
729  msn_ship = msn_elem->Ships()[i];
+
730  sname = msn_ship->Name();
+
731  rnum = msn_ship->RegNum();
+
732  rgn_name = msn_ship->Region();
+
733  }
+
734 
+
735  Point l2 = msn_elem->Location();
+
736 
+
737  if (msn_ship && fabs(msn_ship->Location().x) < 1e9) {
+
738  l2 = msn_ship->Location();
+
739  }
+
740  else if (i) {
+
741  Point offset = RandomPoint();
+
742  offset.z = Random(-1e3, 1e3);
+
743 
+
744  if (msn_elem->Count() < 5)
+
745  offset *= 0.3;
+
746 
+
747  l2 += offset;
+
748  }
+
749 
+
750  // choose best loadout:
+
751  ListIter<MissionLoad> l = msn_elem->Loadouts();
+
752  while (++l) {
+
753  if ((l->GetShip() == i) || (l->GetShip() < 0 && loadout == 0)) {
+
754  if (l->GetName().length()) {
+
755  ListIter<ShipLoad> sl = ((ShipDesign*) msn_elem->GetDesign())->loadouts;
+
756  while (++sl) {
+
757  if (!_stricmp(sl->name, l->GetName()))
+
758  loadout = sl->load;
+
759  }
+
760  }
+
761 
+
762  else {
+
763  loadout = l->GetStations();
+
764  }
+
765  }
+
766  }
+
767 
+
768  element->SetLoadout(loadout);
+
769 
+
770  Ship* ship = CreateShip(sname, rnum,
+
771  (ShipDesign*) msn_elem->GetDesign(),
+
772  rgn_name, l2,
+
773  msn_elem->GetIFF(),
+
774  msn_elem->CommandAI(),
+
775  loadout);
+
776 
+
777  if (ship) {
+
778  double heading = msn_elem->Heading();
+
779  const Skin* skin = msn_elem->GetSkin();
+
780 
+
781  if (msn_ship) {
+
782  heading = msn_ship->Heading();
+
783 
+
784  if (msn_ship->GetSkin())
+
785  skin = msn_ship->GetSkin();
+
786  }
+
787 
+
788  ship->SetRogue(msn_elem->IsRogue());
+
789  ship->SetInvulnerable(msn_elem->IsInvulnerable());
+
790  ship->SetHeading(0, 0, heading + PI);
+
791  ship->SetRespawnCount(respawns);
+
792  ship->UseSkin(skin);
+
793 
+
794  if (!netgame)
+
795  ship->SetRespawnLoc(RandomPoint() * 2);
+
796 
+
797  if (ship->IsStarship())
+
798  ship->SetHelmHeading(heading);
+
799 
+
800  else if (ship->IsAirborne() && ship->AltitudeAGL() > 25)
+
801  ship->SetVelocity(ship->Heading() * 250);
+
802 
+
803  if (element)
+
804  element->AddShip(ship);
+
805 
+
806  if (hangar)
+
807  hangar->FindSlot(ship, squadron, slot, Hangar::ACTIVE);
+
808 
+
809  if (ship->GetRegion() && msn_elem->Player() == i+1)
+
810  ship->GetRegion()->SetPlayerShip(ship);
+
811 
+
812  if (ship->NumFlightDecks()) {
+
813  for (int i = 0; i < ship->NumFlightDecks(); i++) {
+
814  FlightDeck* deck = ship->GetFlightDeck(i);
+
815  if (deck)
+
816  deck->Orient(ship);
+
817  }
+
818  }
+
819 
+
820  if (msn_ship) {
+
821  ship->SetVelocity(msn_ship->Velocity().OtherHand());
+
822  ship->SetIntegrity((float) msn_ship->Integrity());
+
823  ship->SetRespawnCount(msn_ship->Respawns());
+
824 
+
825  if (msn_ship->Ammo()[0] > -10) {
+
826  for (int i = 0; i < 64; i++) {
+
827  Weapon* w = ship->GetWeaponByIndex(i+1);
+
828  if (w)
+
829  w->SetAmmo(msn_ship->Ammo()[i]);
+
830  else
+
831  break;
+
832  }
+
833  }
+
834 
+
835  if (msn_ship->Fuel()[0] > -10) {
+
836  for (int i = 0; i < 4; i++) {
+
837  if (ship->Reactors().size() > i) {
+
838  PowerSource* p = ship->Reactors()[i];
+
839  p->SetCapacity(msn_ship->Fuel()[i]);
+
840  }
+
841  }
+
842  }
+
843 
+
844  if (msn_ship->Decoys() > -10) {
+
845  Weapon* w = ship->GetDecoy();
+
846  if (w)
+
847  w->SetAmmo(msn_ship->Decoys());
+
848  }
+
849 
+
850  if (msn_ship->Probes() > -10) {
+
851  Weapon* w = ship->GetProbeLauncher();
+
852  if (w)
+
853  w->SetAmmo(msn_ship->Probes());
+
854  }
+
855  }
+
856 
+
857  Shield* shield = ship->GetShield();
+
858 
+
859  if (shield) {
+
860  shield->SetPowerLevel(50);
+
861  }
+
862 
+
863  if (ship->Class() > Ship::FRIGATE) {
+
864  ListIter<WeaponGroup> iter = ship->Weapons();
+
865  while (++iter) {
+
866  WeaponGroup* weapon = iter.value();
+
867 
+
868  // anti-air weapon?
+
869  if (weapon->GetDesign()->target_type & Ship::DRONE) {
+ +
871  }
+
872  else {
+ +
874  }
+
875  }
+
876  }
+
877 
+
878  if (ship->Class() > Ship::DRONE && ship->Class() < Ship::STATION) {
+
879  ShipStats* stats = ShipStats::Find(sname);
+
880  if (stats) {
+
881  char design[64];
+
882  sprintf_s(design, "%s %s", ship->Abbreviation(), ship->Design()->display_name);
+
883  stats->SetType(design);
+
884  stats->SetShipClass(ship->Class());
+
885  stats->SetRole(Mission::RoleName(msn_elem->MissionRole()));
+
886  stats->SetIFF(ship->GetIFF());
+
887  stats->SetRegion(msn_elem->Region());
+
888  stats->SetCombatGroup(msn_elem->GetCombatGroup());
+
889  stats->SetCombatUnit(msn_elem->GetCombatUnit());
+
890  stats->SetPlayer(msn_elem->Player() == i+1);
+
891  stats->SetElementIndex(ship->GetElementIndex());
+
892  }
+
893  }
+
894  } // ship
+
895  } // count
+
896  }
+
897  }
+
898  }
+
899 }
+
900 
+
901 void
+ +
903 {
+
904  events.destroy();
+
905 
+
906  if (mission) {
+ +
908  while (++iter) {
+
909  MissionEvent* orig = iter.value();
+
910  MissionEvent* event = new(__FILE__,__LINE__) MissionEvent(*orig);
+
911  events.append(event);
+
912  }
+
913  }
+
914 }
+
915 
+
916 // +--------------------------------------------------------------------+
+
917 
+
918 const char*
+ +
920 {
+
921  const char* call = "Unidentified";
+
922 
+
923  for (int i = 0; i < 32; i++) {
+
924  call = Callsign::GetCallsign(IFF);
+
925 
+
926  if (!FindElement(call))
+
927  break;
+
928  }
+
929 
+
930  return call;
+
931 }
+
932 
+
933 Element*
+
934 Sim::CreateElement(const char* callsign, int IFF, int type)
+
935 {
+
936  Element* elem = new(__FILE__,__LINE__) Element(callsign, IFF, type);
+
937  elements.append(elem);
+
938  return elem;
+
939 }
+
940 
+
941 void
+ +
943 {
+
944  if (elements.contains(elem))
+
945  elements.remove(elem);
+
946 
+
947  delete elem;
+
948 }
+
949 
+
950 Element*
+
951 Sim::FindElement(const char* name)
+
952 {
+ +
954 
+
955  while (++iter) {
+
956  Element* elem = iter.value();
+
957  Text ename = elem->Name();
+
958 
+
959  if (ename == name)
+
960  return elem;
+
961  }
+
962 
+
963  return 0;
+
964 }
+
965 
+
966 // +--------------------------------------------------------------------+
+
967 
+
968 int
+ +
970 {
+
971  assigned.clear();
+
972 
+
973  if (elem) {
+
974  for (int i = 0; i < elements.size(); i++) {
+
975  Element* e = elements.at(i);
+
976  if (!e->IsSquadron() && e->GetAssignment() == elem)
+
977  assigned.append(e);
+
978  }
+
979  }
+
980 
+
981  return assigned.size();
+
982 }
+
983 
+
984 // +--------------------------------------------------------------------+
+
985 
+
986 Ship*
+
987 Sim::CreateShip(const char* name, const char* reg_num, ShipDesign* design, const char* rgn_name, const Point& loc, int IFF, int cmd_ai, const int* loadout)
+
988 {
+
989  if (!design) {
+
990  Print("WARNING: CreateShip(%s): invalid design\n", name);
+
991  return 0;
+
992  }
+
993 
+
994  SimRegion* rgn = FindRegion(rgn_name);
+
995 
+
996  if (!rgn) {
+
997  return 0;
+
998  }
+
999 
+
1000  Ship* ship = new(__FILE__,__LINE__) Ship(name, reg_num, design, IFF, cmd_ai, loadout);
+
1001  ship->MoveTo(loc.OtherHand());
+
1002 
+
1003  if (rgn) {
+
1004  Print("Inserting Ship(%s) into Region(%s) (%s)\n", ship->Name(), rgn->Name(), FormatGameTime());
+
1005  rgn->InsertObject(ship);
+
1006 
+
1007  if (ship->IsAirborne() && ship->AltitudeAGL() > 25)
+
1008  ship->SetVelocity(ship->Heading() * 250);
+
1009  }
+
1010 
+
1011  return ship;
+
1012 }
+
1013 
+
1014 Ship*
+
1015 Sim::FindShip(const char* name, const char* rgn_name)
+
1016 {
+
1017  Ship* ship = 0;
+
1018 
+
1019  if (rgn_name) {
+
1020  SimRegion* rgn = FindRegion(rgn_name);
+
1021  if (rgn)
+
1022  ship = rgn->FindShip(name);
+
1023  }
+
1024 
+
1025  if (!ship) {
+ +
1027  while (++rgn && !ship)
+
1028  ship = rgn->FindShip(name);
+
1029  }
+
1030 
+
1031  return ship;
+
1032 }
+
1033 
+
1034 void
+ +
1036 {
+
1037  SimRegion* rgn = ship->GetRegion();
+
1038  if (rgn)
+
1039  rgn->DestroyShip(ship);
+
1040 }
+
1041 
+
1042 void
+
1043 Sim::NetDockShip(Ship* ship, Ship* carrier, FlightDeck* deck)
+
1044 {
+
1045  SimRegion* rgn = ship->GetRegion();
+
1046  if (rgn)
+
1047  rgn->NetDockShip(ship, carrier, deck);
+
1048 }
+
1049 
+
1050 Ship*
+ +
1052 {
+
1053  Ship* ship = 0;
+
1054 
+ +
1056  while (++rgn && !ship)
+
1057  ship = rgn->FindShipByObjID(objid);
+
1058 
+
1059  return ship;
+
1060 }
+
1061 
+
1062 Shot*
+ +
1064 {
+
1065  Shot* shot = 0;
+
1066 
+ +
1068  while (++rgn && !shot)
+
1069  shot = rgn->FindShotByObjID(objid);
+
1070 
+
1071  return shot;
+
1072 }
+
1073 
+
1074 // +--------------------------------------------------------------------+
+
1075 
+
1076 Orbital*
+
1077 Sim::FindOrbitalBody(const char* name)
+
1078 {
+
1079  Orbital* body = 0;
+
1080 
+
1081  if (mission) {
+ +
1083  while (++iter && !body) {
+
1084  StarSystem* sys = iter.value();
+
1085  body = sys->FindOrbital(name);
+
1086  }
+
1087  }
+
1088 
+
1089  return body;
+
1090 }
+
1091 
+
1092 
+
1093 // +--------------------------------------------------------------------+
+
1094 
+
1095 Shot*
+
1096 Sim::CreateShot(const Point& pos, const Camera& shot_cam, WeaponDesign* design, const Ship* ship, SimRegion* rgn)
+
1097 {
+
1098  Shot* shot = 0;
+
1099 
+
1100  if (design->drone)
+
1101  shot = new(__FILE__,__LINE__) Drone(pos, shot_cam, design, ship);
+
1102  else
+
1103  shot = new(__FILE__,__LINE__) Shot( pos, shot_cam, design, ship);
+
1104 
+
1105  if (rgn)
+
1106  rgn->InsertObject(shot);
+
1107 
+
1108  else if (active_region)
+
1109  active_region->InsertObject(shot);
+
1110 
+
1111  return shot;
+
1112 }
+
1113 
+
1114 // +--------------------------------------------------------------------+
+
1115 
+
1116 Explosion*
+
1117 Sim::CreateExplosion(const Point& pos, const Point& vel, int type, float exp_scale, float part_scale, SimRegion* rgn, SimObject* source, System* sys)
+
1118 {
+
1119  // don't bother creating explosions that can't be seen:
+
1120  if (!rgn || !active_region || rgn != active_region)
+
1121  return 0;
+
1122 
+
1123  Explosion* exp = new(__FILE__,__LINE__) Explosion(type, pos, vel, exp_scale, part_scale, rgn, source);
+
1124 
+
1125  if (rgn)
+
1126  rgn->InsertObject(exp);
+
1127 
+
1128  else if (active_region)
+ +
1130 
+
1131  return exp;
+
1132 }
+
1133 
+
1134 // +--------------------------------------------------------------------+
+
1135 
+
1136 Debris*
+
1137 Sim::CreateDebris(const Point& pos, const Point& vel, Model* model, double mass, SimRegion* rgn)
+
1138 {
+
1139  Debris* debris = new(__FILE__,__LINE__) Debris(model, pos, vel, mass);
+
1140 
+
1141  if (rgn)
+
1142  rgn->InsertObject(debris);
+
1143 
+
1144  else if (active_region)
+
1145  active_region->InsertObject(debris);
+
1146 
+
1147  return debris;
+
1148 }
+
1149 
+
1150 // +--------------------------------------------------------------------+
+
1151 
+
1152 Asteroid*
+
1153 Sim::CreateAsteroid(const Point& pos, int t, double mass, SimRegion* rgn)
+
1154 {
+
1155  Asteroid* asteroid = new(__FILE__,__LINE__) Asteroid(t, pos, mass);
+
1156 
+
1157  if (rgn)
+
1158  rgn->InsertObject(asteroid);
+
1159 
+
1160  else if (active_region)
+
1161  active_region->InsertObject(asteroid);
+
1162 
+
1163  return asteroid;
+
1164 }
+
1165 
+
1166 // +--------------------------------------------------------------------+
+
1167 
+
1168 void
+ +
1170 {
+
1171  if (ship && ship->GetRegion() && ship->Design()->splash_radius > 1) {
+
1172  SimSplash* splash = new(__FILE__,__LINE__)
+
1173  SimSplash(ship->GetRegion(),
+
1174  ship->Location(),
+
1175  ship->Design()->integrity / 4,
+
1176  ship->Design()->splash_radius);
+
1177 
+
1178  splash->owner_name = ship->Name();
+
1179  splashlist.append(splash);
+
1180  }
+
1181 }
+
1182 
+
1183 // +--------------------------------------------------------------------+
+
1184 
+
1185 void
+ +
1187 {
+
1188  if (shot && shot->GetRegion()) {
+
1189  double damage = shot->Damage();
+
1190  if (damage < shot->Design()->damage)
+
1191  damage = shot->Design()->damage;
+
1192 
+
1193  SimSplash* splash = new(__FILE__,__LINE__)
+
1194  SimSplash(shot->GetRegion(),
+
1195  shot->Location(),
+
1196  damage,
+
1197  shot->Design()->lethal_radius);
+
1198 
+
1199  if (shot->Owner())
+
1200  splash->owner_name = shot->Owner()->Name();
+
1201 
+
1202  splash->missile = shot->IsMissile();
+
1203 
+
1204  splashlist.append(splash);
+
1205  CreateExplosion(shot->Location(), Point(), Explosion::SHOT_BLAST, 20.0f, 1.0f, shot->GetRegion());
+
1206  }
+
1207 }
+
1208 
+
1209 // +--------------------------------------------------------------------+
+
1210 
+
1211 void
+
1212 Sim::ShowGrid(int show)
+
1213 {
+
1214  Player* player = Player::GetCurrentPlayer();
+
1215 
+
1216  if (player && player->GridMode() == 0) {
+
1217  show = 0;
+
1218  grid_shown = false;
+
1219  }
+
1220 
+ +
1222  while (++rgn) {
+
1223  rgn->ShowGrid(show);
+
1224  }
+
1225 
+
1226  grid_shown = show?true:false;
+
1227 }
+
1228 
+
1229 bool
+ +
1231 {
+
1232  return grid_shown;
+
1233 }
+
1234 
+
1235 // +--------------------------------------------------------------------+
+
1236 
+ + +
1239 {
+
1240  if (mission)
+
1241  return mission->GetSystemList();
+
1242 
+
1243  static List<StarSystem> dummy_system_list;
+
1244  return dummy_system_list;
+
1245 }
+
1246 
+
1247 // +--------------------------------------------------------------------+
+
1248 
+
1249 void
+ +
1251 {
+
1252  if (active_region)
+ +
1254 }
+
1255 
+
1256 Ship*
+ +
1258 {
+
1259  if (active_region)
+
1260  return active_region->GetPlayerShip();
+
1261 
+ +
1263  if (stars && stars->InCutscene()) {
+
1264  Ship* player = 0;
+
1265 
+ +
1267  while (++rgn && !player) {
+
1268  player = rgn->GetPlayerShip();
+
1269  }
+
1270 
+
1271  return player;
+
1272  }
+
1273 
+
1274  return 0;
+
1275 }
+
1276 
+
1277 Element*
+ +
1279 {
+
1280  Element* elem = 0;
+
1281 
+
1282  for (int i = 0; i < elements.size(); i++) {
+
1283  Element* e = elements[i];
+
1284 
+
1285  if (e->Player() > 0)
+
1286  elem = e;
+
1287  }
+
1288 
+
1289  return elem;
+
1290 }
+
1291 
+
1292 bool
+ +
1294 {
+
1295  if (active_region)
+
1296  return active_region->IsSelected(s);
+
1297 
+
1298  return false;
+
1299 }
+
1300 
+ + +
1303 {
+
1304  if (active_region)
+
1305  return active_region->GetSelection();
+
1306 
+
1307  static List<Ship> empty;
+
1308  return empty;
+
1309 }
+
1310 
+
1311 void
+ +
1313 {
+
1314  if (active_region)
+ +
1316 }
+
1317 
+
1318 void
+ +
1320 {
+
1321  if (active_region)
+ +
1323 }
+
1324 
+
1325 void
+ +
1327 {
+
1328  if (active_region)
+
1329  active_region->SetSelection(newsel);
+
1330 }
+
1331 
+
1332 // +--------------------------------------------------------------------+
+
1333 
+
1334 void
+ +
1336 {
+
1337  test_mode = t;
+
1338  Ship* pship = GetPlayerShip();
+
1339 
+
1340  if (pship)
+
1341  if (IsTestMode())
+
1342  pship->SetControls(0);
+
1343  else
+
1344  pship->SetControls(ctrl);
+
1345 }
+
1346 
+
1347 // +--------------------------------------------------------------------+
+
1348 
+
1349 SimRegion*
+
1350 Sim::FindRegion(const char* name)
+
1351 {
+ +
1353  while (++rgn)
+
1354  if (rgn->name == name)
+
1355  return rgn.value();
+
1356 
+
1357  return 0;
+
1358 }
+
1359 
+
1360 SimRegion*
+ +
1362 {
+ +
1364  while (++rgn)
+
1365  if (rgn->orbital_region == orgn)
+
1366  return rgn.value();
+
1367 
+
1368  return 0;
+
1369 }
+
1370 
+
1371 // +--------------------------------------------------------------------+
+
1372 
+
1373 SimRegion*
+ +
1375 {
+
1376  return FindNearestRegion(object, REAL_SPACE);
+
1377 }
+
1378 
+
1379 SimRegion*
+ +
1381 {
+
1382  return FindNearestRegion(object, AIR_SPACE);
+
1383 }
+
1384 
+
1385 SimRegion*
+ +
1387 {
+
1388  if (!object) return 0;
+
1389 
+
1390  SimRegion* result = 0;
+
1391  double distance = 1.0e40;
+
1392  Point objloc = object->Location();
+
1393 
+
1394  objloc = objloc.OtherHand();
+
1395 
+
1396  if (object->GetRegion())
+
1397  objloc += object->GetRegion()->Location();
+
1398 
+ +
1400  while (++rgn) {
+
1401  if (rgn->Type() == type) {
+
1402  OrbitalRegion* orgn = rgn->GetOrbitalRegion();
+
1403  if (orgn) {
+
1404  double test = fabs((orgn->Location() - objloc).length());
+
1405  if (test < distance) {
+
1406  result = rgn.value();
+
1407  distance = test;
+
1408  }
+
1409  }
+
1410  }
+
1411  }
+
1412 
+
1413  return result;
+
1414 }
+
1415 
+
1416 SimRegion*
+ +
1418 {
+
1419  SimRegion* result = 0;
+
1420 
+
1421  if (!body)
+
1422  return result;
+
1423 
+ +
1425  while (++rgn && !result) {
+
1426  if (rgn->IsOrbital()) {
+
1427  OrbitalRegion* orgn = rgn->GetOrbitalRegion();
+
1428  if (orgn) {
+
1429  ListIter<OrbitalRegion> iter = body->Regions();
+
1430  while (++iter) {
+
1431  if (iter.value() == orgn)
+
1432  result = rgn.value();
+
1433  }
+
1434  }
+
1435  }
+
1436  }
+
1437 
+
1438  return result;
+
1439 }
+
1440 
+
1441 // +--------------------------------------------------------------------+
+
1442 
+
1443 bool
+ +
1445 {
+
1446  if (rgn && active_region != rgn && regions.contains(rgn)) {
+
1447  if (active_region)
+ +
1449 
+
1450  if (!active_region || active_region->System() != rgn->System()) {
+
1451  if (active_region)
+ +
1453  rgn->System()->Activate(scene);
+
1454  }
+
1455 
+
1456  active_region = rgn;
+ +
1458 
+
1459  if (star_system) {
+ +
1461  }
+
1462  else {
+
1463  ::Print("WARNING: Sim::ActivateRegion() No star system found for rgn '%s'", rgn->Name());
+
1464  }
+
1465 
+ +
1467  return true;
+
1468  }
+
1469 
+
1470  return false;
+
1471 }
+
1472 
+
1473 // +--------------------------------------------------------------------+
+
1474 
+
1475 void
+ +
1477 int type, Ship* fc1, Ship* fc2)
+
1478 {
+
1479  bool hyperdrive = false;
+
1480 
+
1481  if (obj->GetQuantumDrive() && obj->GetQuantumDrive()->Subtype() == QuantumDrive::HYPER)
+
1482  hyperdrive = true;
+
1483 
+
1484  jumplist.append(new(__FILE__,__LINE__) SimHyper(obj, rgn, loc, type, hyperdrive, fc1, fc2));
+
1485 }
+
1486 
+
1487 // +--------------------------------------------------------------------+
+
1488 
+
1489 void
+
1490 Sim::ExecFrame(double seconds)
+
1491 {
+
1492  if (first_frame) {
+
1493  first_frame = false;
+ +
1495  }
+
1496 
+
1497  if (netgame)
+
1498  netgame->ExecFrame();
+
1499 
+
1500  if (regions.isEmpty()) {
+
1501  active_region = 0;
+
1502  rgn_queue.clear();
+
1503  jumplist.destroy();
+
1504  scene.Collect();
+
1505  return;
+
1506  }
+
1507 
+
1508  ListIter<Element> elem = elements;
+
1509  while (++elem)
+
1510  if (!elem->IsSquadron())
+
1511  elem->ExecFrame(seconds);
+
1512 
+ +
1514  while (++rgn)
+
1515  if (rgn.value() != active_region && rgn->NumShips() && !rgn_queue.contains(rgn.value()))
+
1516  rgn_queue.append(rgn.value());
+
1517 
+
1518  // execframe for one inactive sim region:
+
1519  if (rgn_queue.size()) {
+
1520  SimRegion* exec_rgn = rgn_queue.removeIndex(0);
+
1521 
+
1522  while (exec_rgn && (exec_rgn->NumShips() == 0 || exec_rgn == active_region))
+
1523  if (rgn_queue.size())
+
1524  exec_rgn = rgn_queue.removeIndex(0);
+
1525  else
+
1526  exec_rgn = 0;
+
1527 
+
1528  if (exec_rgn)
+
1529  exec_rgn->ExecFrame(seconds);
+
1530  }
+
1531 
+
1532  if (active_region)
+
1533  active_region->ExecFrame(seconds);
+
1534 
+
1535  ExecEvents(seconds);
+
1536  ResolveHyperList();
+ +
1538 
+
1539  // GC all the dead objects:
+
1540  scene.Collect();
+
1541 
+
1542  if (!IsTestMode()) {
+
1543  ListIter<Element> e_iter = elements;
+
1544  while (++e_iter) {
+
1545  Element* elem = e_iter.value();
+
1546  if (!elem->IsSquadron() && elem->IsFinished()) {
+
1547  finished.append(e_iter.removeItem());
+
1548  }
+
1549  }
+
1550  }
+
1551 
+
1552  // setup music
+
1553  if (!MusicDirector::IsNoMusic()) {
+ +
1555  if (stars && stars->GetGameMode() == Starshatter::PLAY_MODE) {
+
1556  Ship* player_ship = GetPlayerShip();
+
1557  if (player_ship) {
+
1558  int phase = player_ship->GetFlightPhase();
+
1559 
+
1560  if (phase < Ship::ACTIVE) {
+ +
1562  }
+
1563 
+
1564  else if (phase > Ship::ACTIVE) {
+ +
1566  }
+
1567 
+
1568  else {
+
1569  if (player_ship->IsInCombat()) {
+ +
1571  }
+
1572 
+
1573  else {
+ +
1575  }
+
1576  }
+
1577  }
+
1578  }
+
1579  }
+
1580 }
+
1581 
+
1582 void
+
1583 Sim::ExecEvents(double seconds)
+
1584 {
+ +
1586  while (++iter) {
+
1587  MissionEvent* event = iter.value();
+
1588  event->ExecFrame(seconds);
+
1589  }
+
1590 }
+
1591 
+
1592 void
+ +
1594 {
+
1595  // resolve the hyper space transitions:
+
1596  if (jumplist.size()) {
+
1597  Ship* pship = GetPlayerShip();
+
1598 
+
1599  ListIter<SimHyper> j_iter = jumplist;
+
1600  while (++j_iter) {
+
1601  SimHyper* jump = j_iter.value();
+
1602  Ship* jumpship = jump->ship;
+
1603 
+
1604  if (jumpship) {
+
1605  SimRegion* dest = jump->rgn;
+
1606 
+
1607  if (!dest)
+
1608  dest = FindNearestSpaceRegion(jumpship);
+
1609 
+
1610  if (dest) {
+
1611  // bring along fighters on deck:
+
1612  ListIter<FlightDeck> deck = jumpship->FlightDecks();
+
1613  while (++deck) {
+
1614  for (int i = 0; i < deck->NumSlots(); i++) {
+
1615  Ship* s = deck->GetShip(i);
+
1616 
+
1617  if (s) {
+
1618  dest->InsertObject(s);
+
1619  s->ClearTrack();
+
1620  }
+
1621  }
+
1622  }
+
1623 
+
1624  if (jump->type == 0 && !jump->hyperdrive) {
+
1625  // bring along nearby ships:
+
1626  // have to do it in two parts, because inserting the ships
+
1627  // into the destination corrupts the iter over the current
+
1628  // region's list of ships...
+
1629 
+
1630  // part one: gather the ships that will be jumping:
+
1631  List<Ship> riders;
+
1632  ListIter<Ship> neighbor = jumpship->GetRegion()->Ships();
+
1633  while (++neighbor) {
+
1634  if (neighbor->IsDropship()) {
+
1635  Ship* s = neighbor.value();
+
1636  if (s == jumpship) continue;
+
1637 
+
1638  Point delta = s->Location() - jumpship->Location();
+
1639 
+
1640  if (delta.length() < 5e3) {
+
1641  riders.append(s);
+
1642  }
+
1643  }
+
1644  }
+
1645 
+
1646  // part two: now transfer the list to the destination:
+
1647  for (int i = 0; i < riders.size(); i++) {
+
1648  Ship* s = riders[i];
+
1649  Point delta = s->Location() - jumpship->Location();
+
1650  dest->InsertObject(s);
+
1651  s->MoveTo(jump->loc.OtherHand() + delta);
+
1652  s->ClearTrack();
+
1653 
+
1654  if (jump->fc_dst) {
+
1655  double r = jump->fc_dst->Roll();
+
1656  double p = jump->fc_dst->Pitch();
+
1657  double w = jump->fc_dst->Yaw();
+
1658 
+
1659  s->SetAbsoluteOrientation(r, p, w);
+
1660  s->SetVelocity(jump->fc_dst->Heading() * 500);
+
1661  }
+
1662 
+ +
1664  }
+
1665  }
+
1666 
+
1667  // now it is safe to move the main jump ship:
+
1668  dest->InsertObject(jumpship);
+
1669  jumpship->MoveTo(jump->loc.OtherHand());
+
1670  jumpship->ClearTrack();
+
1671 
+ +
1673  NetUtil::SendObjHyper(jumpship, dest->Name(), jump->loc, jump->fc_src, jump->fc_dst, jump->type);
+
1674 
+
1675  // if using farcaster:
+
1676  if (jump->fc_src) {
+
1677  ::Print("Ship '%s' farcast to '%s'\n", jumpship->Name(), dest->Name());
+
1678  CreateExplosion(jumpship->Location(), Point(0,0,0), Explosion::QUANTUM_FLASH, 1.0f, 0, dest);
+
1679 
+
1680  if (jump->fc_dst) {
+
1681  double r = jump->fc_dst->Roll();
+
1682  double p = jump->fc_dst->Pitch();
+
1683  double w = jump->fc_dst->Yaw();
+
1684 
+
1685  jumpship->SetAbsoluteOrientation(r, p, w);
+
1686  jumpship->SetVelocity(jump->fc_dst->Heading() * 500);
+
1687  }
+
1688 
+
1689  jumpship->SetHelmHeading(jumpship->CompassHeading());
+
1690  jumpship->SetHelmPitch(0);
+
1691  }
+
1692 
+
1693  // break orbit:
+
1694  else if (jump->type == Ship::TRANSITION_DROP_ORBIT) {
+
1695  ::Print("Ship '%s' broke orbit to '%s'\n", jumpship->Name(), dest->Name());
+
1696  jumpship->SetAbsoluteOrientation(0,PI/4,0);
+
1697  jumpship->SetVelocity(jumpship->Heading() * 1.0e3);
+
1698  }
+
1699 
+
1700  // make orbit:
+
1701  else if (jump->type == Ship::TRANSITION_MAKE_ORBIT) {
+
1702  ::Print("Ship '%s' achieved orbit '%s'\n", jumpship->Name(), dest->Name());
+
1703  jumpship->LookAt(Point(0,0,0));
+
1704  jumpship->SetVelocity(jumpship->Heading() * 500.0);
+
1705  }
+
1706 
+
1707  // hyper jump:
+
1708  else {
+
1709  ::Print("Ship '%s' quantum to '%s'\n", jumpship->Name(), dest->Name());
+
1710 
+
1711  if (jump->hyperdrive)
+
1712  CreateExplosion(jumpship->Location(), Point(0,0,0), Explosion::HYPER_FLASH, 1, 1, dest);
+
1713  else
+
1714  CreateExplosion(jumpship->Location(), Point(0,0,0), Explosion::QUANTUM_FLASH, 1, 0, dest);
+
1715 
+
1716  jumpship->LookAt(Point(0,0,0));
+
1717  jumpship->SetVelocity(jumpship->Heading() * 500.0);
+
1718  jumpship->SetHelmHeading(jumpship->CompassHeading());
+
1719  jumpship->SetHelmPitch(0);
+
1720  }
+
1721  }
+
1722 
+
1723  else if (regions.size() > 1) {
+
1724  ::Print("Warning: Unusual jump request for ship '%s'\n", jumpship->Name());
+
1725  regions[1]->InsertObject(jumpship);
+
1726  }
+
1727 
+
1728  Sensor* sensor = jumpship->GetSensor();
+
1729  if (sensor)
+
1730  sensor->ClearAllContacts();
+
1731  }
+
1732  }
+
1733 
+
1734  jumplist.destroy();
+
1735 
+
1736  if (pship && pship->GetRegion()) {
+
1737  if (active_region != pship->GetRegion()) {
+
1738  pship->GetRegion()->SetPlayerShip(pship);
+
1739  }
+
1740  }
+
1741  }
+
1742 }
+
1743 
+
1744 void
+ +
1746 {
+
1747  if (splashlist.size()) {
+ +
1749  while (++iter) {
+
1750  SimSplash* splash = iter.value();
+
1751 
+
1752  if (!splash->rgn)
+
1753  continue;
+
1754 
+
1755  // damage ships:
+
1756  ListIter<Ship> s_iter = splash->rgn->Ships();
+
1757  while (++s_iter) {
+
1758  Ship* ship = s_iter.value();
+
1759 
+
1760  double distance = (ship->Location() - splash->loc).length();
+
1761 
+
1762  if (distance > 1 && distance < splash->range) {
+
1763  double damage = splash->damage * (1 - distance/splash->range);
+
1764  if (!NetGame::IsNetGameClient()) {
+
1765  ship->InflictDamage(damage);
+
1766  }
+
1767 
+
1768  int ship_destroyed = (!ship->InTransition() && ship->Integrity() < 1.0f);
+
1769 
+
1770  // then delete the ship:
+
1771  if (ship_destroyed) {
+ +
1773  Print(" %s Killed %s (%s)\n", (const char*) splash->owner_name, ship->Name(), FormatGameTime());
+
1774 
+
1775  // record the kill
+
1776  ShipStats* killer = ShipStats::Find(splash->owner_name);
+
1777  if (killer) {
+
1778  if (splash->missile)
+
1779  killer->AddEvent(SimEvent::MISSILE_KILL, ship->Name());
+
1780  else
+
1781  killer->AddEvent(SimEvent::GUNS_KILL, ship->Name());
+
1782  }
+
1783 
+
1784  Ship* owner = FindShip(splash->owner_name, splash->rgn->Name());
+
1785  if (owner && owner->GetIFF() != ship->GetIFF()) {
+
1786  if (ship->GetIFF() > 0 || owner->GetIFF() > 1) {
+
1787  killer->AddPoints(ship->Value());
+
1788 
+
1789  Element* elem = owner->GetElement();
+
1790  if (elem) {
+
1791  if (owner->GetElementIndex() > 1) {
+
1792  Ship* s = elem->GetShip(1);
+
1793 
+
1794  if (s) {
+
1795  ShipStats* cmdr_stats = ShipStats::Find(s->Name());
+
1796  if (cmdr_stats) {
+
1797  cmdr_stats->AddCommandPoints(ship->Value()/2);
+
1798  }
+
1799  }
+
1800  }
+
1801 
+
1802  Element* cmdr = elem->GetCommander();
+
1803  if (cmdr) {
+
1804  Ship* s = cmdr->GetShip(1);
+
1805 
+
1806  if (s) {
+
1807  ShipStats* cmdr_stats = ShipStats::Find(s->Name());
+
1808  if (cmdr_stats) {
+
1809  cmdr_stats->AddCommandPoints(ship->Value()/2);
+
1810  }
+
1811  }
+
1812  }
+
1813  }
+
1814  }
+
1815  }
+
1816 
+
1817  ShipStats* killee = ShipStats::Find(ship->Name());
+
1818  if (killee)
+
1819  killee->AddEvent(SimEvent::DESTROYED, splash->owner_name);
+
1820 
+
1821  ship->DeathSpiral();
+
1822  }
+
1823  }
+
1824  }
+
1825 
+
1826  // damage drones:
+
1827  ListIter<Drone> drone_iter = splash->rgn->Drones();
+
1828  while (++drone_iter) {
+
1829  Drone* drone = drone_iter.value();
+
1830 
+
1831  double distance = (drone->Location() - splash->loc).length();
+
1832 
+
1833  if (distance > 1 && distance < splash->range) {
+
1834  double damage = splash->damage * (1 - distance/splash->range);
+
1835  drone->InflictDamage(damage);
+
1836 
+
1837  int destroyed = (drone->Integrity() < 1.0f);
+
1838 
+
1839  // then mark the drone for deletion:
+
1840  if (destroyed) {
+
1841  NetUtil::SendWepDestroy(drone);
+
1842  sim->CreateExplosion(drone->Location(), drone->Velocity(), 21 /* was LARGE_EXP */, 1.0f, 1.0f, splash->rgn);
+
1843  drone->SetLife(0);
+
1844  }
+
1845  }
+
1846  }
+
1847  }
+
1848 
+
1849  splashlist.destroy();
+
1850  }
+
1851 }
+
1852 
+
1853 // +--------------------------------------------------------------------+
+
1854 
+
1855 void
+
1856 Sim::ProcessEventTrigger(int type, int event_id, const char* ship, int param)
+
1857 {
+
1858  Text ship_name = ship;
+
1859 
+ +
1861  while (++iter) {
+
1862  MissionEvent* event = iter.value();
+
1863 
+
1864  if (event->IsPending() && event->Trigger() == type) {
+
1865  switch (type) {
+ + + + + + +
1872  if (event->TriggerParam() <= param) {
+
1873  if (ship_name.indexOf(event->TriggerShip()) == 0)
+
1874  event->Activate();
+
1875  }
+
1876  break;
+
1877 
+ +
1879  if (event->TriggerParam() == param) {
+
1880  if (ship_name.indexOf(event->TriggerShip()) == 0)
+
1881  event->Activate();
+
1882  }
+
1883  break;
+
1884 
+ + +
1887  if (event->TriggerParam() == event_id)
+
1888  event->Activate();
+
1889  break;
+
1890  }
+
1891  }
+
1892  }
+
1893 }
+
1894 
+
1895 double
+ +
1897 {
+
1898  return (Game::GameTime() - start_time) / 1000.0;
+
1899 }
+
1900 
+
1901 // +--------------------------------------------------------------------+
+
1902 
+
1903 void
+ +
1905 {
+ +
1907  if (stars && stars->InCutscene()) {
+ +
1909  bool end = false;
+
1910  double end_time = 0;
+
1911 
+
1912  while (++iter && !end) {
+
1913  MissionEvent* event = iter.value();
+
1914 
+
1915  if (event->IsPending() || event->IsActive()) {
+
1916  if (event->Event() == MissionEvent::END_SCENE ||
+
1917  event->Event() == MissionEvent::END_MISSION) {
+
1918  end = true;
+
1919  end_time = event->Time();
+
1920  }
+
1921 
+
1922  if (event->Event() == MissionEvent::FIRE_WEAPON) {
+
1923  event->Skip();
+
1924  }
+
1925 
+
1926  else {
+
1927  event->Activate();
+
1928  event->Execute(true);
+
1929  }
+
1930  }
+
1931  }
+
1932 
+
1933  double skip_time = end_time - MissionClock();
+
1934  if (skip_time > 0) {
+
1935  Game::SkipGameTime(skip_time);
+
1936  }
+
1937  }
+
1938 }
+
1939 
+
1940 // +--------------------------------------------------------------------+
+
1941 
+
1942 void
+
1943 Sim::ResolveTimeSkip(double seconds)
+
1944 {
+
1945  double skipped = 0;
+
1946 
+
1947  // allow elements to process hold time, and release as needed:
+
1948  ListIter<Element> elem = elements;
+
1949  while (++elem)
+
1950  elem->ExecFrame(seconds);
+
1951 
+
1952  // step through the skip, ten seconds at a time:
+
1953  if (active_region) {
+
1954  double total_skip = seconds;
+
1955  double frame_skip = 10;
+
1956  Ship* player = GetPlayerShip();
+
1957 
+
1958  while (total_skip > frame_skip) {
+
1959  if (active_region->CanTimeSkip()) {
+
1960  active_region->ResolveTimeSkip(frame_skip);
+
1961  total_skip -= frame_skip;
+
1962  skipped += frame_skip;
+
1963  }
+
1964  // break out early if player runs into bad guys...
+
1965  else {
+
1966  total_skip = 0;
+
1967  }
+
1968  }
+
1969 
+
1970  if (total_skip > 0)
+
1971  active_region->ResolveTimeSkip(total_skip);
+
1972  skipped += total_skip;
+
1973  }
+
1974 
+
1975  // give player control after time skip:
+
1976  Ship* player_ship = GetPlayerShip();
+
1977  if (player_ship) {
+
1978  player_ship->SetAutoNav(false);
+
1979  player_ship->SetThrottle(75);
+
1980 
+
1981  HUDView* hud = HUDView::GetInstance();
+
1982  if (hud)
+ +
1984 
+
1985  if (IsTestMode())
+
1986  player_ship->SetControls(0);
+
1987  }
+
1988 
+
1989  Game::SkipGameTime(skipped);
+ +
1991 }
+
1992 
+
1993 // +--------------------------------------------------------------------+
+
1994 
+ + +
1997 {
+ +
1999 
+
2000  ListIter<Element> iter = elements;
+
2001  while (++iter) {
+
2002  Element* elem = iter.value();
+
2003 
+
2004  int num_live_ships = 0;
+
2005 
+
2006  for (int i = 0; i < elem->NumShips(); i++) {
+
2007  Ship* s = elem->GetShip(i+1);
+
2008 
+
2009  if (s && !s->IsDying() && !s->IsDead())
+
2010  num_live_ships++;
+
2011  }
+
2012 
+
2013  if (elem->IsSquadron() || num_live_ships > 0) {
+
2014  MissionElement* msn_elem = CreateMissionElement(elem);
+
2015 
+
2016  if (msn_elem)
+
2017  mission_elements.append(msn_elem);
+
2018  }
+
2019  }
+
2020 
+
2021  return mission_elements;
+
2022 }
+
2023 
+ + +
2026 {
+
2027  MissionElement* msn_elem = 0;
+
2028 
+
2029  if (elem->IsSquadron()) {
+
2030  if (!elem->GetCarrier() || elem->GetCarrier()->Integrity() < 1)
+
2031  return msn_elem;
+
2032  }
+
2033 
+
2034  if (elem && !elem->IsNetObserver()) {
+
2035  msn_elem = new(__FILE__,__LINE__) MissionElement;
+
2036 
+
2037  msn_elem->SetName(elem->Name());
+
2038  msn_elem->SetIFF(elem->GetIFF());
+
2039  msn_elem->SetMissionRole(elem->Type());
+
2040 
+
2041  if (elem->IsSquadron() && elem->GetCarrier()) {
+
2042  Ship* carrier = elem->GetCarrier();
+
2043 
+
2044  msn_elem->SetCarrier(carrier->Name());
+
2045  msn_elem->SetCount(elem->GetCount());
+
2046  msn_elem->SetLocation(carrier->Location().OtherHand());
+
2047 
+
2048  if (carrier->GetRegion())
+
2049  msn_elem->SetRegion(carrier->GetRegion()->Name());
+
2050 
+
2051  int squadron_index = 0;
+
2052  Hangar* hangar = FindSquadron(elem->Name(), squadron_index);
+
2053 
+
2054  if (hangar) {
+
2055  msn_elem->SetDeadCount(hangar->NumShipsDead(squadron_index));
+
2056  msn_elem->SetMaintCount(hangar->NumShipsMaint(squadron_index));
+
2057 
+
2058  const ShipDesign* design = hangar->SquadronDesign(squadron_index);
+
2059  msn_elem->SetDesign(design);
+
2060 
+
2061  Text design_path = design->path_name;
+
2062  design_path.setSensitive(false);
+
2063 
+
2064  if (design_path.indexOf("/Mods/Ships") == 0) {
+
2065  design_path = design_path.substring(11, 1000);
+
2066  msn_elem->SetPath(design_path);
+
2067  }
+
2068  }
+
2069  }
+
2070 
+
2071  else {
+
2072  msn_elem->SetSquadron(elem->GetSquadron());
+
2073  msn_elem->SetCount(elem->NumShips());
+
2074  }
+
2075 
+
2076  if (elem->GetCommander())
+
2077  msn_elem->SetCommander(elem->GetCommander()->Name());
+
2078 
+
2079  msn_elem->SetCombatGroup(elem->GetCombatGroup());
+
2080  msn_elem->SetCombatUnit(elem->GetCombatUnit());
+
2081 
+
2082  Ship* ship = elem->GetShip(1);
+
2083  if (ship) {
+
2084  if (ship->GetRegion())
+
2085  msn_elem->SetRegion(ship->GetRegion()->Name());
+
2086 
+
2087  msn_elem->SetLocation(ship->Location().OtherHand());
+
2088  msn_elem->SetDesign(ship->Design());
+
2089 
+
2090  msn_elem->SetPlayer(elem->Player());
+
2091  msn_elem->SetCommandAI(elem->GetCommandAILevel());
+
2092  msn_elem->SetHoldTime((int) elem->GetHoldTime());
+
2093  msn_elem->SetZoneLock(elem->GetZoneLock());
+
2094  msn_elem->SetHeading(ship->CompassHeading());
+
2095 
+
2096  msn_elem->SetPlayable(elem->IsPlayable());
+
2097  msn_elem->SetRogue(elem->IsRogue());
+
2098  msn_elem->SetIntelLevel(elem->IntelLevel());
+
2099 
+
2100  Text design_path = ship->Design()->path_name;
+
2101  design_path.setSensitive(false);
+
2102 
+
2103  if (design_path.indexOf("/Mods/Ships") == 0) {
+
2104  design_path = design_path.substring(11, 1000);
+
2105  msn_elem->SetPath(design_path);
+
2106  }
+
2107 
+
2108  msn_elem->SetRespawnCount(ship->RespawnCount());
+
2109  }
+
2110 
+
2111  MissionLoad* loadout = new(__FILE__,__LINE__) MissionLoad;
+
2112  CopyMemory(loadout->GetStations(), elem->Loadout(), 16 * sizeof(int));
+
2113 
+
2114  msn_elem->Loadouts().append(loadout);
+
2115 
+
2116  int num_obj = elem->NumObjectives();
+
2117  for (int i = 0; i < num_obj; i++) {
+
2118  Instruction* o = elem->GetObjective(i);
+
2119  Instruction* instr = 0;
+
2120 
+
2121  instr = new(__FILE__,__LINE__) Instruction(*o);
+
2122 
+
2123  msn_elem->AddObjective(instr);
+
2124  }
+
2125 
+
2126  int num_inst = elem->NumInstructions();
+
2127  for (int i = 0; i < num_inst; i++) {
+
2128  Text instr = elem->GetInstruction(i);
+
2129  msn_elem->AddInstruction(instr);
+
2130  }
+
2131 
+
2132  ListIter<Instruction> nav_iter = elem->GetFlightPlan();
+
2133  while (++nav_iter) {
+
2134  Instruction* nav = nav_iter.value();
+
2135  Instruction* npt = new(__FILE__,__LINE__)
+
2136  Instruction(nav->RegionName(), nav->Location(), nav->Action());
+
2137 
+
2138  npt->SetFormation(nav->Formation());
+
2139  npt->SetSpeed(nav->Speed());
+
2140  npt->SetTarget(nav->TargetName());
+
2141  npt->SetHoldTime(nav->HoldTime());
+
2142  npt->SetFarcast(nav->Farcast());
+
2143  npt->SetStatus(nav->Status());
+
2144 
+
2145  msn_elem->AddNavPoint(npt);
+
2146  }
+
2147 
+
2148  for (int i = 0; i < elem->NumShips(); i++) {
+
2149  ship = elem->GetShip(i+1);
+
2150 
+
2151  if (ship) {
+
2152  MissionShip* s = new(__FILE__,__LINE__) MissionShip;
+
2153 
+
2154  s->SetName(ship->Name());
+
2155  s->SetRegNum(ship->Registry());
+
2156  s->SetRegion(ship->GetRegion()->Name());
+
2157  s->SetLocation(ship->Location().OtherHand());
+
2158  s->SetVelocity(ship->Velocity().OtherHand());
+
2159 
+
2160  s->SetRespawns(ship->RespawnCount());
+
2161  s->SetHeading(ship->CompassHeading());
+
2162  s->SetIntegrity(ship->Integrity());
+
2163 
+
2164  if (ship->GetDecoy())
+
2165  s->SetDecoys(ship->GetDecoy()->Ammo());
+
2166 
+
2167  if (ship->GetProbeLauncher())
+
2168  s->SetProbes(ship->GetProbeLauncher()->Ammo());
+
2169 
+
2170  int n;
+
2171  int ammo[16];
+
2172  int fuel[4];
+
2173 
+
2174  for (n = 0; n < 16; n++) {
+
2175  Weapon* w = ship->GetWeaponByIndex(n+1);
+
2176 
+
2177  if (w)
+
2178  ammo[n] = w->Ammo();
+
2179  else
+
2180  ammo[n] = -10;
+
2181  }
+
2182 
+
2183  for (n = 0; n < 4; n++) {
+
2184  if (ship->Reactors().size() > n)
+
2185  fuel[n] = ship->Reactors()[n]->Charge();
+
2186  else
+
2187  fuel[n] = -10;
+
2188  }
+
2189 
+
2190  s->SetAmmo(ammo);
+
2191  s->SetFuel(fuel);
+
2192 
+
2193  msn_elem->Ships().append(s);
+
2194  }
+
2195  }
+
2196  }
+
2197 
+
2198  return msn_elem;
+
2199 }
+
2200 
+
2201 Hangar*
+
2202 Sim::FindSquadron(const char* name, int& index)
+
2203 {
+
2204  Hangar* hangar = 0;
+
2205 
+ +
2207  while (++iter && !hangar) {
+
2208  SimRegion* rgn = iter.value();
+
2209 
+
2210  ListIter<Ship> s_iter = rgn->Carriers();
+
2211  while (++s_iter && !hangar) {
+
2212  Ship* carrier = s_iter.value();
+
2213  Hangar* h = carrier->GetHangar();
+
2214 
+
2215  for (int i = 0; i < h->NumSquadrons() && !hangar; i++) {
+
2216  if (h->SquadronName(i) == name) {
+
2217  hangar = h;
+
2218  index = i;
+
2219  }
+
2220  }
+
2221  }
+
2222  }
+
2223 
+
2224  return hangar;
+
2225 }
+
2226 
+
2227 // +===================================================================-+
+
2228 
+
2229 SimRegion::SimRegion(Sim* s, const char* n, int t)
+
2230 : sim(s), name(n), type(t), orbital_region(0), star_system(0)
+
2231 , player_ship(0), grid(0), active(false), current_view(0), sim_time(0)
+
2232 , ai_index(0), terrain(0)
+
2233 {
+
2234  if (sim) {
+ +
2236  }
+
2237 }
+
2238 
+ +
2240 : sim(s), orbital_region(r), type(REAL_SPACE), star_system(0)
+
2241 , player_ship(0), grid(0), active(false), current_view(0), sim_time(0)
+
2242 , ai_index(0), terrain(0)
+
2243 {
+
2244  if (r) {
+
2245  star_system = r->System();
+
2246  }
+
2247 
+
2248  if (orbital_region) {
+
2249  name = orbital_region->Name();
+
2250  grid = new(__FILE__,__LINE__) Grid((int) orbital_region->Radius(),
+
2251  (int) orbital_region->GridSpace());
+
2252 
+
2253 
+
2254  if (orbital_region->Type() == Orbital::TERRAIN) {
+ +
2256  terrain = new(__FILE__,__LINE__) Terrain(trgn);
+
2257 
+
2258  type = AIR_SPACE;
+
2259  }
+
2260 
+
2261  else if (orbital_region->Asteroids() > 0) {
+ +
2263 
+
2264  for (int i = 0; i < asteroids; i++) {
+
2265  Point init_loc((rand()-16384.0f) * 30,
+
2266  (rand()-16384.0f) * 3,
+
2267  (rand()-16384.0f) * 30);
+
2268  sim->CreateAsteroid(init_loc, i, Random(1e7, 1e8), this);
+
2269  }
+
2270  }
+
2271  }
+
2272  else {
+
2273  name = Game::GetText("Unknown");
+
2274  }
+
2275 }
+
2276 
+ +
2278 {
+ +
2280  delete terrain;
+
2281  explosions.destroy();
+
2282  shots.destroy();
+
2283  ships.destroy();
+
2284  debris.destroy();
+
2285  asteroids.destroy();
+
2286  dead_ships.destroy();
+
2287 
+
2288  for (int i = 0; i < 5; i++)
+
2289  track_database[i].destroy();
+
2290 }
+
2291 
+
2292 int
+ +
2294 {
+ +
2296 }
+
2297 
+
2298 int
+ +
2300 {
+ +
2302 }
+
2303 
+
2304 // +--------------------------------------------------------------------+
+
2305 
+
2306 void
+ +
2308 {
+
2309  // there can only be a player ship when playing the game locally
+
2310  if (Starshatter::GetInstance()) {
+
2311  int player_index = ships.index(ship);
+
2312 
+
2313  if (player_index >= 0) {
+
2314  if (sim->GetActiveRegion() != this)
+
2315  sim->ActivateRegion(this);
+
2316 
+
2317  AttachPlayerShip(player_index);
+
2318  }
+
2319 
+
2320  else {
+
2321  Print("SimRegion %s could not set player ship '%s' - not in region\n",
+
2322  name.data(), ship ? ship->Name() : "(null)");
+
2323  }
+
2324  }
+
2325 
+
2326  // if this is a stand-alone server, set player ship to null
+
2327  else {
+
2328  if (player_ship)
+ +
2330 
+
2331  current_view = -1;
+
2332  player_ship = 0;
+
2333  }
+
2334 }
+
2335 
+
2336 void
+ +
2338 {
+
2339  if (player_ship)
+ +
2341 
+
2342  current_view = index;
+ +
2344 
+ +
2346  if (cam_dir)
+
2347  cam_dir->SetShip(player_ship);
+
2348 
+
2349  if (sim->dust)
+ +
2351 
+
2352  if (!sim->IsTestMode())
+ +
2354 
+ +
2356  if (mouse_con)
+
2357  mouse_con->SetActive(false);
+
2358 }
+
2359 
+
2360 void
+ +
2362 {
+
2363  if (ships.size()) {
+
2364  int original_view = current_view;
+
2365 
+
2366  do {
+
2367  current_view++;
+
2368  if (current_view >= ships.size()) {
+
2369  current_view = 0;
+
2370  }
+
2371  }
+
2372  while (ships[current_view]->Life() == 0 && current_view != original_view);
+
2373 
+
2374  if (current_view != original_view) {
+
2375  ClearSelection();
+
2376 
+
2377  if (!sim->IsTestMode())
+ +
2379 
+
2380  if (player_ship->Rep())
+
2381  player_ship->Rep()->Show();
+
2382 
+ +
2384  }
+
2385  }
+
2386 }
+
2387 
+
2388 bool
+ +
2390 {
+
2391  return selection.contains(s);
+
2392 }
+
2393 
+ + +
2396 {
+
2397  return selection;
+
2398 }
+
2399 
+
2400 void
+ +
2402 {
+
2403  selection.clear();
+
2404  selection.append(newsel);
+
2405 }
+
2406 
+
2407 void
+ +
2409 {
+
2410  selection.clear();
+
2411 }
+
2412 
+
2413 void
+ +
2415 {
+
2416  if (!newsel ||
+
2417  newsel->GetFlightPhase() < Ship::ACTIVE ||
+
2418  newsel->GetFlightPhase() >= Ship::RECOVERY)
+
2419  return;
+
2420 
+
2421  if (!selection.contains(newsel))
+
2422  selection.append(newsel);
+
2423 }
+
2424 
+
2425 // +--------------------------------------------------------------------+
+
2426 
+
2427 void
+ +
2429 {
+
2430  if (!sim) return;
+
2431 
+
2432  ListIter<Ship> ship = ships;
+
2433  while (++ship)
+
2434  ship->Activate(sim->scene);
+
2435 
+
2436  ListIter<Shot> shot = shots;
+
2437  while (++shot)
+
2438  shot->Activate(sim->scene);
+
2439 
+ +
2441  while (++exp)
+
2442  exp->Activate(sim->scene);
+
2443 
+
2444  ListIter<Debris> deb = debris;
+
2445  while (++deb)
+
2446  deb->Activate(sim->scene);
+
2447 
+ +
2449  while (++a)
+
2450  a->Activate(sim->scene);
+
2451 
+
2452  if (grid)
+ +
2454 
+
2455  if (terrain)
+ +
2457 
+
2458  player_ship = 0;
+
2459  active = true;
+
2460 }
+
2461 
+
2462 // +--------------------------------------------------------------------+
+
2463 
+
2464 void
+ +
2466 {
+
2467  if (!sim) return;
+
2468 
+
2469  ListIter<Ship> ship = ships;
+
2470  while (++ship)
+
2471  ship->Deactivate(sim->scene);
+
2472 
+
2473  ListIter<Shot> shot = shots;
+
2474  while (++shot)
+
2475  shot->Deactivate(sim->scene);
+
2476 
+ +
2478  while (++exp)
+
2479  exp->Deactivate(sim->scene);
+
2480 
+
2481  ListIter<Debris> deb = debris;
+
2482  while (++deb)
+
2483  deb->Deactivate(sim->scene);
+
2484 
+ +
2486  while (++a)
+
2487  a->Deactivate(sim->scene);
+
2488 
+
2489  if (grid)
+ +
2491 
+
2492  if (terrain)
+ +
2494 
+
2495  player_ship = 0;
+
2496  active = false;
+
2497 
+
2498  for (int i = 0; i < 5; i++)
+
2499  track_database[i].destroy();
+
2500 }
+
2501 
+
2502 // +--------------------------------------------------------------------+
+
2503 
+
2504 void
+ +
2506 {
+
2507  if (!sim) return;
+
2508 
+
2509  double seconds = secs;
+
2510 
+
2511  // DON'T REALLY KNOW WHAT PURPOSE THIS SERVES....
+
2512  if (!active) {
+
2513  double max_frame = 3 * Game::GetMaxFrameLength();
+
2514  long new_time = Game::GameTime();
+
2515  double delta = new_time - sim_time;
+
2516  seconds = delta / 1000.0;
+
2517 
+
2518  if (seconds > max_frame)
+
2519  seconds = max_frame;
+
2520  }
+
2521 
+ +
2523 
+
2524  if (orbital_region)
+ +
2526 
+ +
2528 
+
2529  Point ref;
+
2530 
+
2531  if (active && cam_dir) {
+
2532  ref = cam_dir->GetCamera()->Pos();
+
2533  UpdateSky(seconds, ref);
+
2534  }
+
2535 
+
2536  if (terrain)
+
2537  terrain->ExecFrame(seconds);
+
2538 
+
2539  UpdateTracks(seconds);
+
2540  UpdateShips(seconds);
+
2541  UpdateShots(seconds);
+
2542  UpdateExplosions(seconds);
+
2543 
+
2544  if (!Game::Paused()) {
+
2545  DamageShips();
+
2546  DockShips();
+
2547 
+
2548  if (active) {
+
2549  CollideShips();
+
2550  CrashShips();
+
2551  }
+
2552 
+
2553  DestroyShips();
+
2554  }
+
2555 
+
2556  if (active && cam_dir && player_ship) {
+
2557  Sound::SetListener(*(cam_dir->GetCamera()), player_ship->Velocity());
+
2558  }
+
2559 }
+
2560 
+
2561 // +--------------------------------------------------------------------+
+
2562 
+
2563 void
+ +
2565 {
+
2566  if (grid) {
+
2567  if (show)
+
2568  grid->Show();
+
2569  else
+
2570  grid->Hide();
+
2571  }
+
2572 }
+
2573 
+
2574 // +--------------------------------------------------------------------+
+
2575 
+
2576 void
+
2577 SimRegion::UpdateSky(double seconds, const Point& ref)
+
2578 {
+
2579  Dust* dust = sim->dust;
+
2580 
+
2581  if (dust) {
+ +
2583  dust->Hide();
+
2584  }
+
2585  else {
+
2586  dust->Show();
+
2587 
+
2588  dust->ExecFrame(seconds, ref);
+
2589 
+
2590  if (player_ship && dust->Hidden()) {
+
2591  dust->Reset(player_ship->Location());
+
2592  dust->Show();
+
2593  }
+
2594  }
+
2595  }
+
2596 
+ +
2598  while (++a) {
+
2599  a->ExecFrame(seconds);
+
2600  }
+
2601 }
+
2602 
+
2603 // +--------------------------------------------------------------------+
+
2604 
+
2605 void
+
2606 SimRegion::UpdateShips(double seconds)
+
2607 {
+
2608  int ship_index = 0;
+
2609  if (ai_index > ships.size())
+
2610  ai_index = 0;
+
2611 
+
2612  ListIter<Ship> ship_iter = ships;
+
2613  Ship* ship = 0;
+
2614 
+
2615  while (++ship_iter) {
+
2616  ship = ship_iter.value();
+
2617 
+
2618  if (ship_index == ai_index || ship == player_ship)
+
2619  ship->SetAIMode(2);
+
2620  else
+
2621  ship->SetAIMode(1);
+
2622 
+
2623  ship->ExecFrame(seconds);
+
2624  ship_index++;
+
2625  }
+
2626 
+
2627  ai_index++;
+
2628 }
+
2629 
+
2630 // +--------------------------------------------------------------------+
+
2631 
+
2632 void
+
2633 SimRegion::UpdateShots(double seconds)
+
2634 {
+
2635  ListIter<Shot> shot_iter = shots;
+
2636  while (++shot_iter) {
+
2637  Shot* shot = shot_iter.value();
+
2638  shot->ExecFrame(seconds);
+
2639 
+
2640  if (shot->Design()->flak) {
+
2641  SeekerAI* seeker = (SeekerAI*) shot->GetDirector();
+
2642 
+
2643  if (shot->Life() < 0.02 || seeker && seeker->Overshot()) {
+
2644  shot->SetFuse(0.001); // set lifetime to ~zero
+
2645  sim->CreateSplashDamage(shot);
+
2646  }
+
2647  }
+
2648 
+
2649  if (shot->Life() < 0.01) { // died of old age
+ +
2651 
+
2652  if (shot->IsDrone())
+
2653  drones.remove((Drone*) shot);
+
2654 
+
2655  shot_iter.removeItem();
+
2656  delete shot;
+
2657  shot = 0;
+
2658  }
+
2659  }
+
2660 }
+
2661 
+
2662 // +--------------------------------------------------------------------+
+
2663 
+
2664 void
+ +
2666 {
+
2667  ListIter<Explosion> exp_iter = explosions;
+
2668  while (++exp_iter) {
+
2669  Explosion* exp = exp_iter.value();
+
2670  exp->ExecFrame(seconds);
+
2671 
+
2672  if (exp->Life() < 0.01) { // died of old age
+
2673  exp_iter.removeItem();
+
2674  delete exp;
+
2675  }
+
2676  }
+
2677 
+
2678  ListIter<Debris> debris_iter = debris;
+
2679  while (++debris_iter) {
+
2680  Debris* d = debris_iter.value();
+
2681  d->ExecFrame(seconds);
+
2682 
+
2683  if (d->Life() < 0.01) { // died of old age
+
2684  debris_iter.removeItem();
+
2685  delete d;
+
2686  }
+
2687  }
+
2688 }
+
2689 
+
2690 // +--------------------------------------------------------------------+
+
2691 // Check for collisions between ships and shots, and apply damage.
+
2692 // Also look for damage to drones and debris.
+
2693 
+
2694 void
+ +
2696 {
+
2697  if (ships.size() == 0 || shots.size() == 0)
+
2698  return;
+
2699 
+
2700  Point impact;
+
2701 
+
2702  // FOR EACH SHOT IN THE REGION:
+
2703  ListIter<Shot> shot_iter = shots;
+
2704  while (++shot_iter) {
+
2705  Shot* shot = shot_iter.value();
+
2706  const Ship* owner = shot->Owner();
+
2707  const char* owner_name;
+
2708 
+
2709  if (owner)
+
2710  owner_name = owner->Name();
+
2711  else
+
2712  owner_name = "[KIA]";
+
2713 
+
2714  // CHECK FOR COLLISION WITH A SHIP:
+
2715  ListIter<Ship> ship_iter = ships;
+
2716  while (shot && ++ship_iter) {
+
2717  Ship* ship = ship_iter.value();
+
2718  int hit = ship->HitBy(shot, impact);
+
2719 
+
2720  if (hit) {
+
2721  // recon imager:
+
2722  if (shot->Damage() < 0) {
+
2723  ShipStats* shooter = ShipStats::Find(owner_name);
+
2724  if (shooter) {
+
2725  shooter->AddEvent(SimEvent::SCAN_TARGET, ship->Name());
+
2726  }
+
2727  }
+
2728 
+
2729  // live round:
+
2730  else if (shot->Damage() > 0) {
+
2731  int ship_destroyed = (!ship->InTransition() && ship->Integrity() < 1.0f);
+
2732 
+
2733  // then delete the ship:
+
2734  if (ship_destroyed) {
+ +
2736  Director* director;
+
2737 
+
2738  Print(" %s Killed %s (%s)\n", owner_name, ship->Name(), FormatGameTime());
+
2739 
+
2740  if (owner)
+
2741  director = owner->GetDirector();
+
2742 
+
2743  // alert the killer
+
2744  if (director && director->Type() > SteerAI::SEEKER && director->Type() < SteerAI::GROUND) {
+
2745  ShipAI* shipAI = (ShipAI*) director;
+
2746  shipAI->Splash(ship);
+
2747  }
+
2748 
+
2749  // record the kill
+
2750  ShipStats* killer = ShipStats::Find(owner_name);
+
2751  if (killer) {
+
2752  if (shot->IsMissile())
+
2753  killer->AddEvent(SimEvent::MISSILE_KILL, ship->Name());
+
2754  else
+
2755  killer->AddEvent(SimEvent::GUNS_KILL, ship->Name());
+
2756  }
+
2757 
+
2758  if (owner && owner->GetIFF() != ship->GetIFF()) {
+
2759  if (ship->GetIFF() > 0 || owner->GetIFF() > 1) {
+
2760  killer->AddPoints(ship->Value());
+
2761 
+
2762  Element* elem = owner->GetElement();
+
2763  if (elem) {
+
2764  if (owner->GetElementIndex() > 1) {
+
2765  Ship* s = elem->GetShip(1);
+
2766 
+
2767  if (s) {
+
2768  ShipStats* cmdr_stats = ShipStats::Find(s->Name());
+
2769  if (cmdr_stats) {
+
2770  cmdr_stats->AddCommandPoints(ship->Value()/2);
+
2771  }
+
2772  }
+
2773  }
+
2774 
+
2775  Element* cmdr = elem->GetCommander();
+
2776  if (cmdr) {
+
2777  Ship* s = cmdr->GetShip(1);
+
2778 
+
2779  if (s) {
+
2780  ShipStats* cmdr_stats = ShipStats::Find(s->Name());
+
2781  if (cmdr_stats) {
+
2782  cmdr_stats->AddCommandPoints(ship->Value()/2);
+
2783  }
+
2784  }
+
2785  }
+
2786  }
+
2787  }
+
2788  }
+
2789 
+
2790  ShipStats* killee = ShipStats::Find(ship->Name());
+
2791  if (killee)
+
2792  killee->AddEvent(SimEvent::DESTROYED, owner_name);
+
2793 
+
2794  ship->DeathSpiral();
+
2795  }
+
2796  }
+
2797 
+
2798  // finally, consume the shot:
+
2799  if (!shot->IsBeam()) {
+
2800  if (owner) {
+
2801  ShipStats* stats = ShipStats::Find(owner_name);
+
2802  if (shot->Design()->primary)
+
2803  stats->AddGunHit();
+
2804  else if (shot->Damage() > 0)
+
2805  stats->AddMissileHit();
+
2806  }
+
2807 
+ +
2809 
+
2810  if (shot->IsDrone())
+
2811  drones.remove((Drone*) shot);
+
2812 
+
2813  shot_iter.removeItem();
+
2814  delete shot;
+
2815  shot = 0;
+
2816  }
+
2817  else if (!shot->HitTarget()) {
+
2818  shot->SetHitTarget(true);
+
2819 
+
2820  if (owner) {
+
2821  ShipStats* stats = ShipStats::Find(owner_name);
+
2822  if (shot->Design()->primary)
+
2823  stats->AddGunHit();
+
2824  }
+
2825  }
+
2826  }
+
2827  }
+
2828 
+
2829  // CHECK FOR COLLISION WITH A DRONE:
+
2830  if (shot && shot->Design()->target_type & Ship::DRONE) {
+
2831  ListIter<Drone> drone_iter = drones;
+
2832  while (shot && ++drone_iter) {
+
2833  Drone* d = drone_iter.value();
+
2834 
+
2835  if (d == shot || d->Owner() == owner)
+
2836  continue;
+
2837 
+
2838  int hit = d->HitBy(shot, impact);
+
2839  if (hit) {
+
2840  int destroyed = (d->Integrity() < 1.0f);
+
2841 
+
2842  // then mark the drone for deletion:
+
2843  if (destroyed) {
+ +
2845  sim->CreateExplosion(d->Location(), d->Velocity(), 21, 1.0f, 1.0f, this);
+
2846  d->SetLife(0);
+
2847  }
+
2848 
+
2849  // finally, consume the shot:
+
2850  if (!shot->IsBeam()) {
+
2851  if (owner) {
+
2852  ShipStats* stats = ShipStats::Find(owner_name);
+
2853  if (shot->Design()->primary)
+
2854  stats->AddGunHit();
+
2855  else
+
2856  stats->AddMissileHit();
+
2857  }
+
2858 
+ +
2860 
+
2861  if (shot->IsDrone())
+
2862  drones.remove((Drone*) shot);
+
2863 
+
2864  shot_iter.removeItem();
+
2865  delete shot;
+
2866  shot = 0;
+
2867  }
+
2868  }
+
2869  }
+
2870  }
+
2871 
+
2872  // CHECK FOR COLLISION WITH DEBRIS:
+
2873  ListIter<Debris> debris_iter = debris;
+
2874  while (shot && ++debris_iter) {
+
2875  Debris* d = debris_iter.value();
+
2876 
+
2877  if (d->Radius() < 50)
+
2878  continue;
+
2879 
+
2880  int hit = d->HitBy(shot, impact);
+
2881  if (hit) {
+
2882  int destroyed = (d->Integrity() < 1.0f);
+
2883 
+
2884  // then delete the debris:
+
2885  if (destroyed) {
+
2886  sim->CreateExplosion(d->Location(), d->Velocity(), Explosion::LARGE_EXPLOSION, 1.0f, 1.0f, this);
+
2887  debris_iter.removeItem();
+
2888  delete d;
+
2889  }
+
2890 
+
2891  // finally, consume the shot:
+
2892  if (!shot->IsBeam()) {
+ +
2894  if (shot->IsDrone())
+
2895  drones.remove((Drone*) shot);
+
2896 
+
2897  shot_iter.removeItem();
+
2898  delete shot;
+
2899  shot = 0;
+
2900  }
+
2901  }
+
2902  }
+
2903 
+
2904  // CHECK FOR COLLISION WITH ASTEROIDS:
+
2905  ListIter<Asteroid> a_iter = asteroids;
+
2906  while (shot && ++a_iter) {
+
2907  Asteroid* a = a_iter.value();
+
2908 
+
2909  int hit = a->HitBy(shot, impact);
+
2910  if (hit) {
+
2911  if (!shot->IsBeam()) {
+
2912  if (shot->IsDrone())
+
2913  drones.remove((Drone*) shot);
+
2914 
+
2915  shot_iter.removeItem();
+
2916  delete shot;
+
2917  shot = 0;
+
2918  }
+
2919  }
+
2920  }
+
2921  }
+
2922 }
+
2923 
+
2924 // +--------------------------------------------------------------------+
+
2925 
+
2926 void
+ +
2928 {
+
2929  if (ships.size() < 2 && debris.size() < 1)
+
2930  return;
+
2931 
+
2932  List<Ship> kill_list;
+
2933 
+
2934  int s_index = 0;
+
2935 
+
2936  ListIter<Ship> ship_iter = ships;
+
2937  while (++ship_iter) {
+
2938  Ship* ship = ship_iter.value();
+
2939 
+
2940  if (ship->InTransition() ||
+
2941  ship->GetFlightPhase() < Ship::ACTIVE ||
+
2942  ship->MissionClock() < 10000 ||
+
2943  ship->IsNetObserver())
+
2944  continue;
+
2945 
+
2946  int t_index = 0;
+
2947  ListIter<Ship> targ_iter = ships;
+
2948  while (++targ_iter) {
+
2949  Ship* targ = targ_iter.value();
+
2950 
+
2951  if (t_index++ <= s_index) continue;
+
2952 
+
2953  if (targ == ship) continue;
+
2954 
+
2955  if (targ->InTransition() ||
+
2956  targ->GetFlightPhase() < Ship::ACTIVE ||
+
2957  targ->MissionClock() < 10000 ||
+
2958  targ->IsNetObserver())
+
2959  continue;
+
2960 
+
2961  // ignore AI fighter collisions:
+
2962  if (ship->IsDropship() &&
+
2963  ship != player_ship &&
+
2964  targ->IsDropship() &&
+
2965  targ != player_ship)
+
2966  continue;
+
2967 
+
2968  // don't collide with own runway!
+
2969  if (ship->IsAirborne() && ship->GetCarrier() == targ)
+
2970  continue;
+
2971  if (targ->IsAirborne() && targ->GetCarrier() == ship)
+
2972  continue;
+
2973 
+
2974  // impact:
+
2975  if (ship->CollidesWith(*targ)) {
+
2976  Vec3 tv1 = targ->Velocity();
+
2977  Vec3 sv1 = ship->Velocity();
+
2978 
+
2979  Physical::SemiElasticCollision(*ship, *targ);
+
2980 
+
2981  Vec3 tv2 = targ->Velocity();
+
2982  Vec3 sv2 = ship->Velocity();
+
2983 
+
2984  double dvs = (sv2-sv1).length();
+
2985  double dvt = (tv2-tv1).length();
+
2986 
+
2987  if (dvs > 20) dvs *= dvs;
+
2988  if (dvt > 20) dvt *= dvt;
+
2989 
+
2990  if (!NetGame::IsNetGameClient()) {
+
2991  double old_integrity = ship->Integrity();
+
2992  ship->InflictDamage(dvs);
+
2993  double hull_damage = old_integrity - ship->Integrity();
+
2994  NetUtil::SendObjDamage(ship, hull_damage);
+
2995 
+
2996  old_integrity = targ->Integrity();
+
2997  targ->InflictDamage(dvt);
+
2998  hull_damage = old_integrity - targ->Integrity();
+
2999  NetUtil::SendObjDamage(targ, hull_damage);
+
3000  }
+
3001 
+
3002  // then delete the ship:
+
3003  if (targ->Integrity() < 1.0f) {
+ +
3005  Print(" ship %s died in collision with %s (%s)\n", targ->Name(), ship->Name(), FormatGameTime());
+
3006  if (!kill_list.contains(targ)) {
+
3007  ShipStats* r = ShipStats::Find(targ->Name());
+
3008  if (r) r->AddEvent(SimEvent::COLLIDE, ship->Name());
+
3009 
+
3010  if (targ->GetIFF() > 0 && ship->GetIFF() != targ->GetIFF()) {
+
3011  r = ShipStats::Find(ship->Name());
+
3012  if (r) r->AddPoints(targ->Value());
+
3013  }
+
3014 
+
3015  kill_list.insert(targ);
+
3016  }
+
3017  }
+
3018 
+
3019  if (ship->Integrity() < 1.0f) {
+ +
3021  Print(" ship %s died in collision with %s (%s)\n", ship->Name(), targ->Name(), FormatGameTime());
+
3022  if (!kill_list.contains(ship)) {
+
3023  ShipStats* r = ShipStats::Find(ship->Name());
+
3024  if (r) r->AddEvent(SimEvent::COLLIDE, targ->Name());
+
3025 
+
3026  if (ship->GetIFF() > 0 && ship->GetIFF() != targ->GetIFF()) {
+
3027  r = ShipStats::Find(targ->Name());
+
3028  if (r) r->AddPoints(ship->Value());
+
3029  }
+
3030 
+
3031  kill_list.insert(ship);
+
3032  }
+
3033  }
+
3034  }
+
3035  }
+
3036 
+
3037  ListIter<Debris> debris_iter = debris;
+
3038  while (++debris_iter) {
+
3039  Debris* d = debris_iter.value();
+
3040 
+
3041  if (d->Radius() < 50)
+
3042  continue;
+
3043 
+
3044  if (ship->CollidesWith(*d)) {
+
3045  Vec3 tv1 = d->Velocity();
+
3046  Vec3 sv1 = ship->Velocity();
+
3047 
+
3048  Physical::SemiElasticCollision(*ship, *d);
+
3049 
+
3050  Vec3 tv2 = d->Velocity();
+
3051  Vec3 sv2 = ship->Velocity();
+
3052 
+
3053  if (!NetGame::IsNetGameClient()) {
+
3054  ship->InflictDamage((sv2-sv1).length());
+
3055  }
+
3056 
+
3057  d->InflictDamage((tv2-tv1).length());
+
3058 
+
3059  // then delete the debris:
+
3060  if (d->Integrity() < 1.0f) {
+
3061  sim->CreateExplosion(d->Location(), d->Velocity(), Explosion::LARGE_EXPLOSION, 1.0f, 1.0f, this);
+
3062  debris_iter.removeItem();
+
3063  delete d;
+
3064  }
+
3065 
+
3066  if (ship->Integrity() < 1.0f) {
+
3067  if (!kill_list.contains(ship)) {
+
3068  ShipStats* r = ShipStats::Find(ship->Name());
+
3069  if (r) r->AddEvent(SimEvent::COLLIDE, Game::GetText("DEBRIS"));
+
3070 
+
3071  kill_list.insert(ship);
+
3072  }
+
3073  }
+
3074  }
+
3075  }
+
3076 
+
3077  ListIter<Asteroid> a_iter = asteroids;
+
3078  while (++a_iter) {
+
3079  Asteroid* a = a_iter.value();
+
3080 
+
3081  if (ship->CollidesWith(*a)) {
+
3082  Vec3 sv1 = ship->Velocity();
+
3083  Physical::SemiElasticCollision(*ship, *a);
+
3084  Vec3 sv2 = ship->Velocity();
+
3085 
+
3086  if (!NetGame::IsNetGameClient()) {
+
3087  ship->InflictDamage((sv2-sv1).length() * 10);
+
3088  }
+
3089 
+
3090  if (ship->Integrity() < 1.0f) {
+
3091  if (!kill_list.contains(ship)) {
+
3092  ShipStats* r = ShipStats::Find(ship->Name());
+
3093  if (r) r->AddEvent(SimEvent::COLLIDE, Game::GetText("ASTEROID"));
+
3094 
+
3095  kill_list.insert(ship);
+
3096  }
+
3097  }
+
3098  }
+
3099  }
+
3100 
+
3101  s_index++;
+
3102  }
+
3103 
+
3104  ListIter<Ship> killed(kill_list);
+
3105  while (++killed) {
+
3106  Ship* kill = killed.value();
+
3107  kill->DeathSpiral();
+
3108  }
+
3109 }
+
3110 
+
3111 // +--------------------------------------------------------------------+
+
3112 
+
3113 void
+ +
3115 {
+ +
3117  return;
+
3118 
+
3119  ListIter<Ship> ship_iter = ships;
+
3120  while (++ship_iter) {
+
3121  Ship* ship = ship_iter.value();
+
3122 
+
3123  if (!ship->IsGroundUnit() &&
+
3124  !ship->InTransition() &&
+
3125  ship->Class() != Ship::LCA &&
+
3126  ship->AltitudeAGL() < ship->Radius()/2) {
+
3127  if (ship->GetFlightPhase() == Ship::ACTIVE || ship->GetFlightPhase() == Ship::APPROACH) {
+
3128  ship->InflictDamage(1e6);
+
3129 
+
3130  if (ship->Integrity() < 1.0f) {
+
3131  Print(" ship destroyed by crash: %s (%s)\n", ship->Name(), FormatGameTime());
+
3132  ShipStats* r = ShipStats::Find(ship->Name());
+
3133  if (r) r->AddEvent(SimEvent::CRASH);
+
3134 
+
3135  ship->DeathSpiral();
+
3136  }
+
3137  }
+
3138  }
+
3139  }
+
3140 
+
3141  ListIter<Shot> shot_iter = shots;
+
3142  while (++shot_iter) {
+
3143  Shot* shot = shot_iter.value();
+
3144 
+
3145  if (shot->IsBeam() || shot->IsDecoy())
+
3146  continue;
+
3147 
+
3148  if (shot->AltitudeMSL() < 5e3 &&
+
3149  shot->AltitudeAGL() < 5) {
+
3150 
+
3151  // shot hit the ground, destroy it:
+ +
3153 
+
3154  if (shot->IsDrone())
+
3155  drones.remove((Drone*) shot);
+
3156 
+
3157  shot_iter.removeItem();
+
3158  delete shot;
+
3159  }
+
3160  }
+
3161 }
+
3162 
+
3163 // +--------------------------------------------------------------------+
+
3164 
+
3165 void
+ +
3167 {
+
3168  ListIter<Ship> ship_iter = ships;
+
3169  while (++ship_iter) {
+
3170  Ship* ship = ship_iter.value();
+
3171 
+
3172  if (ship->IsDead()) {
+
3173  // must use the iterator to remove the current
+
3174  // item from the container:
+
3175  ship_iter.removeItem();
+
3176  DestroyShip(ship);
+
3177  }
+
3178  }
+
3179 }
+
3180 
+
3181 // +--------------------------------------------------------------------+
+
3182 
+
3183 void
+ +
3185 {
+
3186  if (!ship) return;
+
3187 
+
3188  Ship* spawn = 0;
+
3189 
+
3190  ships.remove(ship);
+
3191  carriers.remove(ship);
+
3192  selection.remove(ship);
+
3193 
+
3194  Text rgn_name;
+
3195  if (ship->GetRegion())
+
3196  rgn_name = ship->GetRegion()->Name();
+
3197 
+
3198  bool player_destroyed = (player_ship == ship);
+
3199 
+
3200  char ship_name[64];
+
3201  char ship_reg[64];
+
3202  strcpy_s(ship_name, ship->Name());
+
3203  strcpy_s(ship_reg, ship->Registry());
+
3204 
+
3205  ShipDesign* ship_design = (ShipDesign*) ship->Design();
+
3206  int ship_iff = ship->GetIFF();
+
3207  int cmd_ai = ship->GetCommandAILevel();
+
3208  bool respawn = sim->IsTestMode() && !ship->IsGroundUnit();
+
3209  bool observe = false;
+
3210 
+
3211  if (!respawn)
+
3212  respawn = ship->RespawnCount() > 0;
+
3213 
+
3214  if (sim->netgame) {
+
3215  if (!respawn)
+
3216  observe = player_destroyed;
+
3217  }
+
3218 
+
3219  if (respawn || observe) {
+
3220  if (!sim->netgame || !respawn)
+
3221  ship->SetRespawnLoc(RandomPoint() * 2);
+
3222 
+
3223  Point spawn_loc = ship->RespawnLoc();
+
3224 
+
3225  if (ship->IsAirborne() && spawn_loc.z < 5e3)
+
3226  spawn_loc.z = Random(8e3, 10e3);
+
3227 
+
3228  spawn = sim->CreateShip(ship_name, ship_reg, ship_design, rgn_name, spawn_loc, ship_iff, cmd_ai, observe ? 0 : ship->GetLoadout());
+
3229  spawn->SetRespawnCount(ship->RespawnCount() - 1);
+
3230  spawn->SetNetObserver(observe);
+
3231 
+
3232  if (sim->netgame && respawn)
+
3233  sim->netgame->Respawn(ship->GetObjID(), spawn);
+
3234 
+
3235  int n = strlen(ship_name);
+
3236  if (ship_name[n-2] == ' ' && isdigit(ship_name[n-1]))
+
3237  ship_name[n-2] = 0;
+
3238 
+
3239  Element* elem = sim->FindElement(ship_name);
+
3240  if (elem)
+
3241  elem->AddShip(spawn, ship->GetOrigElementIndex());
+
3242  else
+
3243  Print("Warning: No Element found for '%s' on respawn.\n", ship_name);
+
3244 
+
3245  if (player_destroyed)
+
3246  SetPlayerShip(spawn);
+
3247  }
+
3248  else {
+
3249  // close mission, return to menu:
+
3250  if (player_destroyed) {
+ +
3252  if (stars)
+ +
3254  }
+
3255  }
+
3256 
+ +
3258 
+
3259  dead_ships.insert(ship);
+
3260  ship->Destroy();
+
3261 }
+
3262 
+
3263 // +--------------------------------------------------------------------+
+
3264 
+
3265 void
+ +
3267 {
+
3268  if (!ship || !carrier || !deck) return;
+
3269 
+
3270  deck->Dock(ship);
+
3271 }
+
3272 
+
3273 // +--------------------------------------------------------------------+
+
3274 
+
3275 Ship*
+
3276 SimRegion::FindShip(const char* ship_name)
+
3277 {
+
3278  Ship* ship = 0;
+
3279 
+
3280  if (ship_name && *ship_name) {
+
3281  int name_len = strlen(ship_name);
+
3282 
+
3283  ListIter<Ship> ship_iter = ships;
+
3284  while (++ship_iter && !ship) {
+
3285  Ship* test = ship_iter.value();
+
3286  if (!strncmp(test->Name(), ship_name, name_len)) {
+
3287  int test_len = strlen(test->Name());
+
3288 
+
3289  // The only fuzzy match is for element indices.
+
3290  // The desired name "Alpha" matches "Alpha 1" and "Alpha 2"
+
3291  // but not "Alpha-Centauri"
+
3292 
+
3293  if (test_len > name_len && test->Name()[name_len] != ' ')
+
3294  continue;
+
3295 
+
3296  ship = test;
+
3297  }
+
3298  }
+
3299  }
+
3300 
+
3301  return ship;
+
3302 }
+
3303 
+
3304 Ship*
+ +
3306 {
+
3307  Ship* ship = 0;
+
3308 
+
3309  ListIter<Ship> ship_iter = ships;
+
3310  while (++ship_iter && !ship) {
+
3311  Ship* test = ship_iter.value();
+
3312  if (test->GetObjID() == objid)
+
3313  ship = test;
+
3314  }
+
3315 
+
3316  return ship;
+
3317 }
+
3318 
+
3319 Shot*
+ +
3321 {
+
3322  Shot* shot = 0;
+
3323 
+
3324  ListIter<Shot> shot_iter = shots;
+
3325  while (++shot_iter && !shot) {
+
3326  Shot* test = shot_iter.value();
+
3327  if (test->GetObjID() == objid)
+
3328  shot = test;
+
3329  }
+
3330 
+
3331  if (!shot) {
+
3332  ListIter<Drone> drone_iter = drones;
+
3333  while (++drone_iter && !shot) {
+
3334  Drone* test = drone_iter.value();
+
3335  if (test->GetObjID() == objid)
+
3336  shot = test;
+
3337  }
+
3338  }
+
3339 
+
3340  return shot;
+
3341 }
+
3342 
+
3343 // +--------------------------------------------------------------------+
+
3344 
+
3345 void
+ +
3347 {
+
3348  if (ships.size() == 0)
+
3349  return;
+
3350 
+
3351  ListIter<Ship> ship_iter = ships;
+
3352  while (++ship_iter) {
+
3353  Ship* ship = ship_iter.value();
+
3354  int docked = (ship->GetFlightPhase() == Ship::DOCKED);
+
3355 
+
3356  if (docked) {
+ +
3358 
+
3359  // who did this ship dock with?
+
3360  Ship* carrier = ship->GetCarrier();
+
3361 
+
3362  if (carrier) {
+
3363  ShipStats* s = ShipStats::Find(ship->Name());
+
3364  if (s) {
+
3365  if (ship->IsAirborne())
+
3366  s->AddEvent(SimEvent::LAND, carrier->Name());
+
3367  else
+
3368  s->AddEvent(SimEvent::DOCK, carrier->Name());
+
3369  }
+
3370 
+
3371  ShipStats* c = ShipStats::Find(carrier->Name());
+
3372  if (c) c->AddEvent(SimEvent::RECOVER_SHIP, ship->Name());
+
3373  }
+
3374 
+
3375  // then delete the ship:
+
3376  int player_docked = (player_ship == ship);
+
3377  char ship_name[33];
+
3378  strcpy_s(ship_name, ship->Name());
+
3379 
+
3380  selection.remove(ship);
+
3381  dead_ships.insert(ship_iter.removeItem());
+
3382  ship->Destroy();
+
3383 
+
3384  if (player_docked) {
+
3385  // close mission, return to menu:
+ +
3387  if (stars)
+ +
3389  }
+
3390 
+
3391  if (carrier)
+
3392  Print(" %s Docked with %s\n", ship_name, carrier->Name());
+
3393  }
+
3394  }
+
3395 }
+
3396 
+
3397 // +--------------------------------------------------------------------+
+
3398 
+
3399 void
+ +
3401 {
+
3402  if (!ship) return;
+
3403 
+
3404  SimRegion* orig = ship->GetRegion();
+
3405 
+
3406  if (orig != this) {
+
3407  if (orig != 0) {
+
3408  if (orig->active)
+
3409  ship->Deactivate(sim->scene);
+
3410 
+
3411  orig->ships.remove(ship);
+
3412  orig->carriers.remove(ship);
+
3413  orig->selection.remove(ship);
+
3414  }
+
3415 
+
3416  ships.append(ship);
+
3417 
+
3418  if (ship->NumFlightDecks())
+
3419  carriers.append(ship);
+
3420 
+
3421  TranslateObject(ship);
+
3422  ship->SetRegion(this);
+
3423 
+
3424  if (active)
+
3425  ship->Activate(sim->scene);
+
3426  }
+
3427 }
+
3428 
+
3429 void
+ +
3431 {
+
3432  if (!shot) return;
+
3433 
+
3434  SimRegion* orig = shot->GetRegion();
+
3435 
+
3436  if (orig != this) {
+
3437  if (orig != 0)
+
3438  orig->shots.remove(shot);
+
3439 
+
3440  shots.append(shot);
+
3441  if (shot->IsDrone())
+
3442  drones.append((Drone*) shot);
+
3443 
+
3444  TranslateObject(shot);
+
3445  shot->SetRegion(this);
+
3446 
+
3447  if (active)
+
3448  shot->Activate(sim->scene);
+
3449  }
+
3450 }
+
3451 
+
3452 void
+ +
3454 {
+
3455  if (!exp) return;
+
3456 
+
3457  SimRegion* orig = exp->GetRegion();
+
3458 
+
3459  if (orig != this) {
+
3460  if (orig != 0)
+
3461  orig->explosions.remove(exp);
+
3462 
+
3463  explosions.append(exp);
+
3464  TranslateObject(exp);
+
3465  exp->SetRegion(this);
+
3466 
+
3467  if (active)
+
3468  exp->Activate(sim->scene);
+
3469  }
+
3470 }
+
3471 
+
3472 void
+ +
3474 {
+
3475  if (!d) return;
+
3476 
+
3477  SimRegion* orig = d->GetRegion();
+
3478 
+
3479  if (orig != this) {
+
3480  if (orig != 0)
+
3481  orig->debris.remove(d);
+
3482 
+
3483  debris.append(d);
+
3484  TranslateObject(d);
+
3485  d->SetRegion(this);
+
3486 
+
3487  if (active)
+
3488  d->Activate(sim->scene);
+
3489  }
+
3490 }
+
3491 
+
3492 void
+ +
3494 {
+
3495  if (!a) return;
+
3496 
+
3497  SimRegion* orig = a->GetRegion();
+
3498 
+
3499  if (orig != this) {
+
3500  if (orig != 0)
+
3501  orig->asteroids.remove(a);
+
3502 
+
3503  asteroids.append(a);
+
3504  TranslateObject(a);
+
3505  a->SetRegion(this);
+
3506 
+
3507  if (active)
+
3508  a->Activate(sim->scene);
+
3509  }
+
3510 }
+
3511 
+
3512 // +--------------------------------------------------------------------+
+
3513 
+
3514 void
+ +
3516 {
+
3517  if (orbital_region)
+ +
3519 
+
3520  if (object) {
+
3521  SimRegion* orig = object->GetRegion();
+
3522  if (orig) {
+
3523  Point delta = Location() - orig->Location();
+
3524  delta = delta.OtherHand();
+
3525  object->TranslateBy(delta);
+
3526  }
+
3527  }
+
3528 }
+
3529 
+
3530 // +--------------------------------------------------------------------+
+
3531 
+ + +
3534 {
+
3535  if (iff >= 0 && iff < 5)
+
3536  return track_database[iff];
+
3537 
+
3538  static List<Contact> empty;
+
3539  return empty;
+
3540 }
+
3541 
+
3542 void
+ +
3544 {
+
3545  for (int i = 0; i < 5; i++) {
+
3546  ListIter<Contact> track_iter = track_database[i];
+
3547 
+
3548  while (++track_iter) {
+
3549  Contact* t = track_iter.value();
+
3550  Ship* c_ship = t->GetShip();
+
3551  Shot* c_shot = t->GetShot();
+
3552  double c_life = 0;
+
3553 
+
3554  if (c_ship) {
+
3555  c_life = c_ship->Life();
+
3556 
+
3557  // look for quantum jumps and orbit transitions:
+
3558  if (c_ship->GetRegion() != this || c_ship->IsNetObserver())
+
3559  c_life = 0;
+
3560  }
+
3561 
+
3562  else if (c_shot)
+
3563  c_life = c_shot->Life();
+
3564 
+
3565  if (t->Age() < 0 || c_life == 0) {
+
3566  track_iter.removeItem();
+
3567  delete t;
+
3568  }
+
3569 
+
3570  else {
+
3571  t->Reset();
+
3572  }
+
3573  }
+
3574  }
+
3575 }
+
3576 
+
3577 // +--------------------------------------------------------------------+
+
3578 
+
3579 bool
+ +
3581 {
+
3582  bool ok = false;
+
3583 
+
3584  if (player_ship) {
+
3585  ok = true;
+
3586 
+
3587  for (int i = 0; ok && i < ships.size(); i++) {
+
3588  Ship* s = ships[i];
+
3589 
+
3590  if (s != player_ship && s->GetIFF() && s->GetIFF() != player_ship->GetIFF()) {
+
3591  double dist = Point(s->Location() - player_ship->Location()).length();
+
3592 
+
3593  if (s->IsStarship())
+
3594  ok = dist > 60e3;
+
3595  else
+
3596  ok = dist > 30e3;
+
3597  }
+
3598  }
+
3599  }
+
3600 
+
3601  return ok;
+
3602 }
+
3603 
+
3604 // +--------------------------------------------------------------------+
+
3605 
+
3606 void
+ +
3608 {
+
3609  for (int i = 0; i < ships.size(); i++) {
+
3610  Ship* ship = ships[i];
+
3611  Ship* ward = ship->GetWard();
+
3612 
+
3613  // remember to burn fuel and fix stuff...
+
3614  ship->ExecSystems(seconds);
+
3615  ship->ExecMaintFrame(seconds);
+
3616 
+
3617  ship->ClearTrack();
+
3618  ListIter<Contact> contact = ship->ContactList();
+
3619  while (++contact)
+
3620  contact->ClearTrack();
+
3621 
+
3622  if (ship->IsStatic())
+
3623  continue;
+
3624 
+
3625  // if ship is cleared inbound, land him:
+
3626  InboundSlot* inbound = ship->GetInbound();
+
3627  if (inbound) {
+
3628  if (inbound->Cleared()) {
+
3629  FlightDeck* deck = inbound->GetDeck();
+
3630 
+
3631  if (deck) {
+
3632  ship->SetCarrier((Ship*) deck->GetCarrier(), deck);
+ +
3634  ship->Stow();
+
3635  deck->Clear(inbound->Index());
+
3636  }
+
3637  }
+
3638 
+
3639  // cleared or not, once you're inbound, don't seek navpoints:
+
3640  continue;
+
3641  }
+
3642 
+
3643  if (ship->GetHangar()) {
+
3644  ship->GetHangar()->ExecFrame(seconds);
+
3645 
+
3646  List<FlightDeck>& flight_decks = ship->FlightDecks();
+
3647  for (int n = 0; n < flight_decks.size(); n++)
+
3648  flight_decks[n]->ExecFrame(seconds);
+
3649  }
+
3650 
+
3651  Instruction* navpt = ship->GetNextNavPoint();
+
3652  Point dest = ship->Location();
+
3653  double speed = 500;
+
3654  double space = 2.0e3 * (ship->GetElementIndex() - 1);
+
3655 
+
3656  if (ship->IsStarship())
+
3657  space *= 5;
+
3658 
+
3659  if (navpt && navpt->Action() == Instruction::LAUNCH) {
+
3660  ship->SetNavptStatus(navpt, Instruction::COMPLETE);
+
3661  navpt = ship->GetNextNavPoint();
+
3662  }
+
3663 
+
3664  if (navpt) {
+
3665  dest = navpt->Location().OtherHand();
+
3666  speed = navpt->Speed();
+
3667  }
+
3668 
+
3669  else if (ward) {
+
3670  Point delta = ship->Location() - ward->Location();
+
3671  delta.y = 0;
+
3672 
+
3673  if (delta.length() > 25e3) {
+
3674  delta.Normalize();
+
3675  dest = ward->Location() + delta * 25e3;
+
3676  }
+
3677  }
+
3678 
+
3679  Point delta = dest - ship->Location();
+
3680  Point unit = delta;
+
3681  double dist = unit.Normalize() - space;
+
3682 
+
3683  if (dist > 1e3) {
+
3684  if (speed < 50)
+
3685  speed = 500;
+
3686 
+
3687  double etr = dist / speed;
+
3688 
+
3689  if (etr > seconds)
+
3690  etr = seconds;
+
3691 
+
3692  Point trans = unit * (speed * etr);
+
3693 
+
3694  if (ship->GetFuelLevel() > 1) {
+
3695  ship->MoveTo(ship->Location() + trans);
+
3696  ship->SetVelocity(unit * speed);
+
3697  }
+
3698  ship->LookAt(dest);
+
3699 
+
3700  if (ship->IsStarship()) {
+ +
3702  ship->SetHelmHeading(ship->CompassHeading());
+
3703  ship->SetHelmPitch(ship->CompassPitch());
+
3704  }
+
3705  }
+
3706 
+
3707  else if (navpt && navpt->Status() <= Instruction::ACTIVE) {
+
3708  ship->SetNavptStatus(navpt, Instruction::COMPLETE);
+
3709  }
+
3710 
+
3711  if (ward) {
+
3712  Point ward_heading = ward->Heading();
+
3713  ward_heading.y = 0;
+
3714  ward_heading.Normalize();
+
3715 
+
3716  if (ship->GetFuelLevel() > 1) {
+
3717  ship->SetVelocity(ward->Velocity());
+
3718  }
+
3719  ship->LookAt(ship->Location() + ward_heading * 1e6);
+
3720 
+
3721  if (ship->IsStarship()) {
+ +
3723  ship->SetHelmHeading(ship->CompassHeading());
+
3724  ship->SetHelmPitch(ship->CompassPitch());
+
3725  }
+
3726  }
+
3727 
+
3728  if (dist > 1 || ward) {
+
3729  for (int j = 0; j < ships.size(); j++) {
+
3730  Ship* test = ships[j];
+
3731 
+
3732  if (ship != test && test->Mass() >= ship->Mass()) {
+
3733  Point delta = ship->Location() - test->Location();
+
3734 
+
3735  if (delta.length() < ship->Radius() * 2 + test->Radius() * 2) {
+
3736  ship->MoveTo(test->Location() + RandomPoint().OtherHand());
+
3737  }
+
3738  }
+
3739  }
+
3740  }
+
3741  }
+
3742 
+
3743  DockShips();
+
3744 }
+
3745 
+
3746 // +--------------------------------------------------------------------+
+
3747 
+
3748 void
+ +
3750 {
+
3751  for (int i = 0; i < dead_ships.size(); i++) {
+
3752  Ship* s = dead_ships[i];
+
3753 
+
3754  if (s->GetCombatUnit() && s->GetFlightPhase() != Ship::DOCKED)
+
3755  s->GetCombatUnit()->Kill(1);
+
3756  }
+
3757 
+
3758  for (int i = 0; i < ships.size(); i++) {
+
3759  Ship* s = ships[i];
+
3760  CombatUnit* u = s->GetCombatUnit();
+
3761 
+
3762  if (u) {
+
3763  Point u_loc = s->Location().OtherHand();
+
3764  if (u_loc.z > 20e3)
+
3765  u_loc.z = 20e3;
+
3766  else if (u_loc.z < -20e3)
+
3767  u_loc.z = -20e3;
+
3768 
+
3769  if (u->IsStarship()) {
+
3770  u->SetRegion(s->GetRegion()->Name());
+
3771  u->MoveTo(u_loc);
+
3772  }
+
3773 
+
3774  if (!u->IsDropship()) {
+
3775  if (s->Integrity() < 1)
+
3776  u->Kill(1);
+
3777  else
+
3778  u->SetSustainedDamage(s->Design()->integrity - s->Integrity());
+
3779  }
+
3780 
+
3781  CombatGroup* g = u->GetCombatGroup();
+
3782  if (g && g->Type() > CombatGroup::FLEET && g->GetFirstUnit() == u) {
+
3783  if (!g->IsZoneLocked())
+
3784  g->SetRegion(s->GetRegion()->Name());
+
3785  else
+
3786  u->SetRegion(g->GetRegion());
+
3787 
+
3788  g->MoveTo(u_loc);
+
3789  }
+
3790  }
+
3791  }
+
3792 }
+
3793 
+
3794 // +--------------------------------------------------------------------+
+
3795 
+
3796 const char* FormatGameTime()
+
3797 {
+
3798  static char txt[64];
+
3799 
+
3800  int t = Game::GameTime();
+
3801 
+
3802  int h = ( t / 3600000);
+
3803  int m = ((t - h*3600000) / 60000);
+
3804  int s = ((t - h*3600000 - m*60000) / 1000);
+
3805  int e = ( t - h*3600000 - m*60000 - s*1000);
+
3806 
+
3807  if (h > 0)
+
3808  sprintf_s(txt, "%02d:%02d:%02d.%03d", h,m,s,e);
+
3809  else
+
3810  sprintf_s(txt, "%02d:%02d.%03d", m,s,e);
+
3811 
+
3812  return txt;
+
3813 }
+
+
+ + + + -- cgit v1.1