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/_flight_deck_8cpp_source.html | 1303 ++++++++++++++++++++++++ 1 file changed, 1303 insertions(+) create mode 100644 Doc/doxygen/html/_flight_deck_8cpp_source.html (limited to 'Doc/doxygen/html/_flight_deck_8cpp_source.html') diff --git a/Doc/doxygen/html/_flight_deck_8cpp_source.html b/Doc/doxygen/html/_flight_deck_8cpp_source.html new file mode 100644 index 0000000..736cdb7 --- /dev/null +++ b/Doc/doxygen/html/_flight_deck_8cpp_source.html @@ -0,0 +1,1303 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/FlightDeck.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
FlightDeck.cpp
+
+
+Go to the documentation of this file.
1 /* Project Starshatter 4.5
+
2  Destroyer Studios LLC
+
3  Copyright © 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: Stars.exe
+
6  FILE: FlightDeck.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  Everything needed to launch and recover space craft...
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "FlightDeck.h"
+
17 #include "Ship.h"
+
18 #include "ShipCtrl.h"
+
19 #include "ShipDesign.h"
+
20 #include "Element.h"
+
21 #include "Mission.h"
+
22 #include "MissionEvent.h"
+
23 #include "Drive.h"
+
24 #include "Sim.h"
+
25 #include "Instruction.h"
+
26 #include "Hoop.h"
+
27 #include "LandingGear.h"
+
28 #include "RadioMessage.h"
+
29 #include "RadioTraffic.h"
+
30 #include "SimEvent.h"
+
31 #include "AudioConfig.h"
+
32 #include "CameraDirector.h"
+
33 #include "Combatant.h"
+
34 #include "CombatGroup.h"
+
35 #include "CombatUnit.h"
+
36 
+
37 #include "NetData.h"
+
38 #include "NetUtil.h"
+
39 
+
40 #include "Game.h"
+
41 #include "Solid.h"
+
42 #include "Light.h"
+
43 #include "Sound.h"
+
44 #include "DataLoader.h"
+
45 
+
46 static Sound* tire_sound = 0;
+
47 static Sound* catapult_sound = 0;
+
48 
+
49 // +======================================================================+
+
50 
+ +
52 {
+
53 public:
+
54  FlightDeckSlot() : ship(0), state(0), sequence(0), time(0), filter(0xf) { }
+
55  int operator == (const FlightDeckSlot& that) const { return this == &that; }
+
56 
+ + + +
60 
+
61  int state;
+
62  int sequence;
+
63  double time;
+
64  double clearance;
+
65  DWORD filter;
+
66 };
+
67 
+
68 // +======================================================================+
+
69 
+
70 InboundSlot::InboundSlot(Ship* s, FlightDeck* d, int squad, int index)
+
71 : ship(s), deck(d), squadron(squad), slot(index), cleared(0), final(0), approach(0)
+
72 {
+
73  if (ship)
+
74  Observe(ship);
+
75 
+
76  if (deck && deck->GetCarrier())
+
77  Observe((SimObject*) deck->GetCarrier());
+
78 }
+
79 
+
80 int InboundSlot::operator < (const InboundSlot& that) const
+
81 {
+
82  double dthis = 0;
+
83  double dthat = 0;
+
84 
+
85  if (ship == that.ship) {
+
86  return false;
+
87  }
+
88 
+
89  if (cleared && !that.cleared) {
+
90  return true;
+
91  }
+
92 
+
93  if (!cleared && that.cleared) {
+
94  return false;
+
95  }
+
96 
+
97  if (ship && deck && that.ship) {
+
98  dthis = Point(ship->Location() - deck->MountLocation()).length();
+
99  dthat = Point(that.ship->Location() - deck->MountLocation()).length();
+
100  }
+
101 
+
102  if (dthis == dthat) {
+
103  return (DWORD) this < (DWORD) &that;
+
104  }
+
105 
+
106  return dthis < dthat;
+
107 }
+
108 
+ +
110 {
+
111  double dthis = 0;
+
112  double dthat = 0;
+
113 
+
114  if (ship == that.ship)
+
115  return true;
+
116 
+
117  if (cleared && !that.cleared)
+
118  return true;
+
119 
+
120  if (!cleared && that.cleared)
+
121  return false;
+
122 
+
123  if (ship && deck && that.ship) {
+
124  dthis = Point(ship->Location() - deck->MountLocation()).length();
+
125  dthat = Point(that.ship->Location() - deck->MountLocation()).length();
+
126  }
+
127 
+
128  return dthis <= dthat;
+
129 }
+
130 
+ +
132 {
+
133  return this == &that;
+
134 }
+
135 
+
136 void InboundSlot::Clear(bool c)
+
137 {
+
138  if (ship)
+
139  cleared = c;
+
140 }
+
141 
+ +
143 {
+
144  if (ship && deck) {
+
145  return Point(ship->Location() - deck->MountLocation()).length();
+
146  }
+
147 
+
148  return 1e9;
+
149 }
+
150 
+
151 // +----------------------------------------------------------------------+
+
152 
+
153 bool
+ +
155 {
+
156  if (obj->Type() == SimObject::SIM_SHIP) {
+
157  Ship* s = (Ship*) obj;
+
158 
+
159  if (s == ship) {
+
160  ship = 0;
+
161  }
+
162 
+
163  // Actually, this can't happen. The flight deck
+
164  // owns the slot. When the carrier is destroyed,
+
165  // the flight decks and slots are destroyed before
+
166  // the carrier updates the observers.
+
167 
+
168  // I'm leaving this block in, just in case.
+
169 
+
170  else if (deck && s == deck->GetCarrier()) {
+
171  ship = 0;
+
172  deck = 0;
+
173  }
+
174  }
+
175 
+
176  return SimObserver::Update(obj);
+
177 }
+
178 
+
179 const char*
+ +
181 {
+
182  return "InboundSlot";
+
183 }
+
184 
+
185 // +======================================================================+
+
186 
+ +
188 : System(FLIGHT_DECK, FLIGHT_DECK_LAUNCH, "Flight Deck", 1, 1),
+
189 carrier(0), index(0), num_slots(0), slots(0), cycle_time(5), num_hoops(0), hoops(0),
+
190 azimuth(0), light(0), num_catsounds(0), num_approach_pts(0)
+
191 {
+
192  name = Game::GetText("sys.flight-deck");
+
193  abrv = Game::GetText("sys.flight-deck.abrv");
+
194 }
+
195 
+
196 // +----------------------------------------------------------------------+
+
197 
+ +
199 : System(s),
+
200 carrier(0), index(0), start_rel(s.start_rel),
+
201 end_rel(s.end_rel), cam_rel(s.cam_rel),
+
202 cycle_time(s.cycle_time),
+
203 num_slots(s.num_slots), slots(0),
+
204 num_hoops(0), hoops(0), azimuth(s.azimuth), light(0),
+
205 num_catsounds(0), num_approach_pts(s.num_approach_pts)
+
206 {
+
207  Mount(s);
+
208 
+
209  slots = new(__FILE__,__LINE__) FlightDeckSlot[num_slots];
+
210  for (int i = 0; i < num_slots; i++) {
+
211  slots[i].spot_rel = s.slots[i].spot_rel;
+
212  slots[i].filter = s.slots[i].filter;
+
213  }
+
214 
+
215  for (int i = 0; i < NUM_APPROACH_PTS; i++)
+
216  approach_rel[i] = s.approach_rel[i];
+
217 
+
218  for (int i = 0; i < 2; i++)
+
219  runway_rel[i] = s.runway_rel[i];
+
220 
+
221  if (s.light) {
+
222  light = new(__FILE__,__LINE__) Light(*s.light);
+
223  }
+
224 }
+
225 
+
226 // +--------------------------------------------------------------------+
+
227 
+ +
229 {
+
230  if (hoops && num_hoops) {
+
231  for (int i = 0; i < num_hoops; i++) {
+
232  Hoop* h = &hoops[i];
+
233  Scene* scene = h->GetScene();
+
234  if (scene)
+
235  scene->DelGraphic(h);
+
236  }
+
237  }
+
238 
+
239  delete [] slots;
+
240  delete [] hoops;
+
241 
+ +
243 
+ +
245 }
+
246 
+
247 // +--------------------------------------------------------------------+
+
248 
+
249 void
+ +
251 {
+
252  static int initialized = 0;
+
253  if (initialized) return;
+
254 
+
255  DataLoader* loader = DataLoader::GetLoader();
+
256  loader->SetDataPath("Sounds/");
+
257 
+
258  const int SOUND_FLAGS = Sound::LOCALIZED |
+ +
260 
+
261  loader->LoadSound("Tires.wav", tire_sound, SOUND_FLAGS);
+
262  loader->LoadSound("Catapult.wav", catapult_sound, SOUND_FLAGS);
+
263  loader->SetDataPath(0);
+
264 
+
265  if (tire_sound)
+
266  tire_sound->SetMaxDistance(2.5e3f);
+
267 
+
268  if (catapult_sound)
+
269  catapult_sound->SetMaxDistance(0.5e3f);
+
270 
+
271  initialized = 1;
+
272 }
+
273 
+
274 // +--------------------------------------------------------------------+
+
275 
+
276 void
+ +
278 {
+
279  delete tire_sound;
+
280  delete catapult_sound;
+
281 
+
282  tire_sound = 0;
+
283  catapult_sound = 0;
+
284 }
+
285 
+
286 // +--------------------------------------------------------------------+
+
287 
+
288 void
+
289 FlightDeck::ExecFrame(double seconds)
+
290 {
+
291  System::ExecFrame(seconds);
+
292 
+
293  bool advance_queue = false;
+
294  long max_vol = AudioConfig::EfxVolume();
+
295  long volume = -1000;
+
296  Sim* sim = Sim::GetSim();
+
297 
+
298  if (volume > max_vol)
+
299  volume = max_vol;
+
300 
+
301  // update ship status:
+
302  for (int i = 0; i < num_slots; i++) {
+
303  FlightDeckSlot* slot = &slots[i];
+
304  Ship* slot_ship = 0;
+
305 
+
306  if (slot->ship == 0) {
+
307  slot->state = CLEAR;
+
308  }
+
309  else {
+
310  slot_ship = slot->ship;
+
311  slot_ship->SetThrottle(0);
+
312  }
+
313 
+
314  switch (slot->state) {
+
315  case CLEAR:
+
316  if (slot->time > 0) {
+
317  slot->time -= seconds;
+
318  }
+
319  else if (IsRecoveryDeck()) {
+
320  GrantClearance();
+
321  }
+
322  break;
+
323 
+
324  case READY: {
+
325  Camera c;
+
326  c.Clone(carrier->Cam());
+
327  c.Yaw(azimuth);
+
328 
+
329  if (slot_ship) {
+
330  slot_ship->CloneCam(c);
+
331  slot_ship->MoveTo(slot->spot_loc);
+
332  slot_ship->TranslateBy(carrier->Cam().vup() * slot->clearance);
+
333  slot_ship->SetVelocity(carrier->Velocity());
+
334  }
+
335  slot->time = 0;
+
336  }
+
337  break;
+
338 
+
339  case QUEUED:
+
340  if (slot->time > 0) {
+
341  Camera c;
+
342  c.Clone(carrier->Cam());
+
343  c.Yaw(azimuth);
+
344 
+
345  slot->time -= seconds;
+
346  if (slot_ship) {
+
347  slot_ship->CloneCam(c);
+
348  slot_ship->MoveTo(slot->spot_loc);
+
349  slot_ship->TranslateBy(carrier->Cam().vup() * slot->clearance);
+
350  slot_ship->SetFlightPhase(Ship::ALERT);
+
351  }
+
352  }
+
353 
+
354  if (slot->sequence == 1 && slot->time <= 0) {
+
355  bool clear_for_launch = true;
+
356  for (int i = 0; i < num_slots; i++)
+
357  if (slots[i].state == LOCKED)
+
358  clear_for_launch = false;
+
359 
+
360  if (clear_for_launch) {
+
361  slot->sequence = 0;
+
362  slot->state = LOCKED;
+
363  slot->time = cycle_time;
+
364  if (slot_ship)
+
365  slot_ship->SetFlightPhase(Ship::LOCKED);
+
366  num_catsounds = 0;
+
367 
+
368  advance_queue = true;
+
369  }
+
370  }
+
371  break;
+
372 
+
373  case LOCKED:
+
374  if (slot->time > 0) {
+
375  slot->time -= seconds;
+
376 
+
377  if (slot_ship) {
+
378  double ct4 = cycle_time/4;
+
379 
+
380  double dx = start_rel.x - slot->spot_rel.x;
+
381  double dy = start_rel.z - slot->spot_rel.z;
+
382  double dyaw = atan2(dx,dy) - azimuth;
+
383 
+
384  Camera c;
+
385  c.Clone(carrier->Cam());
+
386  c.Yaw(azimuth);
+
387 
+
388  // rotate:
+
389  if (slot->time > 3*ct4) {
+
390  double step = 1 - (slot->time - 3*ct4) / ct4;
+
391  c.Yaw(dyaw * step);
+
392  slot_ship->CloneCam(c);
+
393  slot_ship->MoveTo(slot->spot_loc);
+
394  slot_ship->TranslateBy(carrier->Cam().vup() * slot->clearance);
+
395 
+
396  if (carrier->IsGroundUnit()) {
+
397  slot_ship->SetThrottle(25);
+
398  }
+
399 
+
400  else if (num_catsounds < 1) {
+
401  if (catapult_sound) {
+
402  Sound* sound = catapult_sound->Duplicate();
+
403  sound->SetLocation(slot_ship->Location());
+
404  sound->SetVolume(volume);
+
405  sound->Play();
+
406  }
+
407  num_catsounds = 1;
+
408  }
+
409  }
+
410 
+
411  // translate:
+
412  else if (slot->time > 2*ct4) {
+
413  double step = (slot->time - 2*ct4) / ct4;
+
414 
+
415  Point loc = start_point +
+
416  (slot->spot_loc - start_point) * step;
+
417 
+
418  c.Yaw(dyaw);
+
419  slot_ship->CloneCam(c);
+
420  slot_ship->MoveTo(loc);
+
421  slot_ship->TranslateBy(carrier->Cam().vup() * slot->clearance);
+
422 
+
423  if (carrier->IsGroundUnit()) {
+
424  slot_ship->SetThrottle(25);
+
425  }
+
426 
+
427  else if (num_catsounds < 2) {
+
428  if (catapult_sound) {
+
429  Sound* sound = catapult_sound->Duplicate();
+
430  sound->SetLocation(slot_ship->Location());
+
431  sound->SetVolume(volume);
+
432  sound->Play();
+
433  }
+
434  num_catsounds = 2;
+
435  }
+
436  }
+
437 
+
438  // rotate:
+
439  else if (slot->time > ct4) {
+
440  double step = (slot->time - ct4) / ct4;
+
441  c.Yaw(dyaw*step);
+
442  slot_ship->CloneCam(c);
+
443  slot_ship->MoveTo(start_point);
+
444  slot_ship->TranslateBy(carrier->Cam().vup() * slot->clearance);
+
445 
+
446  if (carrier->IsGroundUnit()) {
+
447  slot_ship->SetThrottle(25);
+
448  }
+
449 
+
450  else if (num_catsounds < 3) {
+
451  if (catapult_sound) {
+
452  Sound* sound = catapult_sound->Duplicate();
+
453  sound->SetLocation(slot_ship->Location());
+
454  sound->SetVolume(volume);
+
455  sound->Play();
+
456  }
+
457  num_catsounds = 3;
+
458  }
+
459  }
+
460 
+
461  // wait:
+
462  else {
+
463  slot_ship->SetThrottle(100);
+
464  slot_ship->CloneCam(c);
+
465  slot_ship->MoveTo(start_point);
+
466  slot_ship->TranslateBy(carrier->Cam().vup() * slot->clearance);
+
467  }
+
468 
+
469  slot_ship->SetFlightPhase(Ship::LOCKED);
+
470  }
+
471  }
+
472  else {
+
473  slot->state = LAUNCH;
+
474  slot->time = 0;
+
475 
+
476  }
+
477  break;
+
478 
+
479  case LAUNCH:
+
480  LaunchShip(slot_ship);
+
481  break;
+
482 
+
483  case DOCKING:
+
484  if (slot_ship && !slot_ship->IsAirborne()) {
+
485  // do arresting gear stuff:
+
486  if (slot_ship->GetFlightModel() == Ship::FM_ARCADE)
+
487  slot_ship->ArcadeStop();
+
488 
+
489  slot_ship->SetVelocity(carrier->Velocity());
+
490  }
+
491 
+
492  if (slot->time > 0) {
+
493  slot->time -= seconds;
+
494  }
+
495  else {
+
496  if (slot_ship) {
+
497  slot_ship->SetFlightPhase(Ship::DOCKED);
+
498  slot_ship->Stow();
+
499 
+ +
501  }
+
502 
+
503  Clear(i);
+
504  }
+
505  break;
+
506 
+
507  default:
+
508  break;
+
509  }
+
510  }
+
511 
+
512  if (advance_queue) {
+
513  for (int i = 0; i < num_slots; i++) {
+
514  FlightDeckSlot* slot = &slots[i];
+
515  if (slot->state == QUEUED && slot->sequence > 1)
+
516  slot->sequence--;
+
517  }
+
518  }
+
519 }
+
520 
+
521 bool
+ +
523 {
+
524  FlightDeckSlot* slot = 0;
+
525  Sim* sim = Sim::GetSim();
+
526 
+
527  if (slot_ship) {
+
528  for (int i = 0; i < num_slots; i++) {
+
529  if (slots[i].ship == slot_ship)
+
530  slot = &(slots[i]);
+
531  }
+
532 
+
533  // only suggest a launch point if no flight plan has been filed...
+
534  if (slot_ship->GetElement()->FlightPlanLength() == 0) {
+
535  Point departure = end_point;
+
536  departure = departure.OtherHand();
+
537 
+
538  Instruction* launch_point = new(__FILE__,__LINE__)
+ +
540  launch_point->SetSpeed(350);
+
541 
+
542  slot_ship->SetLaunchPoint(launch_point);
+
543  }
+
544 
+
545  if (!slot_ship->IsAirborne()) {
+
546  Point cat;
+
547  if (fabs(azimuth) < 5*DEGREES) {
+
548  cat = carrier->Heading() * 300;
+
549  }
+
550  else {
+
551  Camera c;
+
552  c.Clone(carrier->Cam());
+
553  c.Yaw(azimuth);
+
554  cat = c.vpn() * 300;
+
555  }
+
556 
+
557  slot_ship->SetVelocity(carrier->Velocity() + cat);
+
558  slot_ship->SetFlightPhase(Ship::LAUNCH);
+
559  }
+
560  else {
+
561  slot_ship->SetFlightPhase(Ship::TAKEOFF);
+
562  }
+
563 
+
564  Director* dir = slot_ship->GetDirector();
+
565  if (dir && dir->Type() == ShipCtrl::DIR_TYPE) {
+
566  ShipCtrl* ctrl = (ShipCtrl*) dir;
+
567  ctrl->Launch();
+
568  }
+
569 
+ +
571  if (c) c->AddEvent(SimEvent::LAUNCH_SHIP, slot_ship->Name());
+
572 
+
573  ShipStats* stats = ShipStats::Find(slot_ship->Name());
+
574  if (stats) {
+
575  stats->SetRegion(carrier->GetRegion()->Name());
+
576  stats->SetType(slot_ship->Design()->name);
+
577 
+
578  if (slot_ship->GetElement()) {
+
579  Element* elem = slot_ship->GetElement();
+
580  stats->SetRole(Mission::RoleName(elem->Type()));
+
581  stats->SetCombatGroup(elem->GetCombatGroup());
+
582  stats->SetCombatUnit(elem->GetCombatUnit());
+
583  stats->SetElementIndex(slot_ship->GetElementIndex());
+
584  }
+
585 
+
586  stats->SetIFF(slot_ship->GetIFF());
+ +
588 
+
589  if (slot_ship == sim->GetPlayerShip())
+
590  stats->SetPlayer(true);
+
591  }
+
592 
+ +
594 
+
595  if (slot) {
+
596  slot->ship = 0;
+
597  slot->state = CLEAR;
+
598  slot->sequence = 0;
+
599  slot->time = 0;
+
600  }
+
601 
+
602  return true;
+
603  }
+
604 
+
605  return false;
+
606 }
+
607 
+
608 // +----------------------------------------------------------------------+
+
609 
+
610 void
+ +
612 {
+ +
614  light = new(__FILE__,__LINE__) Light((float) l);
+
615 }
+
616 
+
617 void
+ +
619 {
+
620  if (i >= 0 && i < NUM_APPROACH_PTS) {
+
621  approach_rel[i] = loc;
+
622 
+
623  if (i >= num_approach_pts)
+
624  num_approach_pts = i+1;
+
625  }
+
626 }
+
627 
+
628 void
+ +
630 {
+
631  if (i >= 0 && i < 2)
+
632  runway_rel[i] = loc;
+
633 }
+
634 
+
635 void
+ +
637 {
+
638  start_rel = loc;
+
639 }
+
640 
+
641 void
+ +
643 {
+
644  end_rel = loc;
+
645 }
+
646 
+
647 void
+ +
649 {
+
650  cam_rel = loc;
+
651 }
+
652 
+
653 // +----------------------------------------------------------------------+
+
654 
+
655 void
+
656 FlightDeck::AddSlot(const Point& spot, DWORD filter)
+
657 {
+
658  if (!slots)
+
659  slots = new(__FILE__,__LINE__) FlightDeckSlot[10];
+
660 
+
661  slots[num_slots].spot_rel = spot;
+
662  slots[num_slots].filter = filter;
+
663  num_slots++;
+
664 }
+
665 
+
666 // +----------------------------------------------------------------------+
+
667 
+
668 void
+ +
670 {
+
671  cycle_time = t;
+
672 }
+
673 
+
674 // +----------------------------------------------------------------------+
+
675 
+
676 void
+ +
678 {
+
679  System::Orient(rep);
+
680 
+
681  Matrix orientation = rep->Cam().Orientation();
+
682  Point loc = rep->Location();
+
683 
+
684  start_point = (start_rel * orientation) + loc;
+
685  end_point = (end_rel * orientation) + loc;
+
686  cam_loc = (cam_rel * orientation) + loc;
+
687 
+
688  for (int i = 0; i < num_approach_pts; i++)
+
689  approach_point[i] = (approach_rel[i] * orientation) + loc;
+
690 
+
691  for (int i = 0; i < num_slots; i++)
+
692  slots[i].spot_loc = (slots[i].spot_rel * orientation) + loc;
+
693 
+
694  if (IsRecoveryDeck()) {
+
695  if (carrier->IsAirborne()) {
+
696  runway_point[0] = (runway_rel[0] * orientation) + loc;
+
697  runway_point[1] = (runway_rel[1] * orientation) + loc;
+
698  }
+
699 
+
700  if (num_hoops < 1) {
+
701  num_hoops = 4;
+
702  hoops = new(__FILE__,__LINE__) Hoop[num_hoops];
+
703  }
+
704 
+
705  Point hoop_vec = start_point - end_point;
+
706  double hoop_d = hoop_vec.Normalize() / num_hoops;
+
707 
+
708  orientation.Yaw(azimuth);
+
709 
+
710  for (int i = 0; i < num_hoops; i++) {
+
711  hoops[i].MoveTo(end_point + hoop_vec * (i+1) * hoop_d);
+
712  hoops[i].SetOrientation(orientation);
+
713  }
+
714  }
+
715 
+
716  if (light)
+ +
718 }
+
719 
+
720 // +----------------------------------------------------------------------+
+
721 
+
722 int
+
723 FlightDeck::SpaceLeft(int type) const
+
724 {
+
725  int space_left = 0;
+
726 
+
727  for (int i = 0; i < num_slots; i++)
+
728  if (slots[i].ship == 0 && (slots[i].filter & type))
+
729  space_left++;
+
730 
+
731  return space_left;
+
732 }
+
733 
+
734 // +----------------------------------------------------------------------+
+
735 
+
736 bool
+
737 FlightDeck::Spot(Ship* s, int& index)
+
738 {
+
739  if (!s)
+
740  return false;
+
741 
+
742  if (index < 0) {
+
743  for (int i = 0; i < num_slots; i++) {
+
744  if (slots[i].ship == 0 && (slots[i].filter & s->Class())) {
+
745  index = i;
+
746  break;
+
747  }
+
748  }
+
749  }
+
750 
+
751  if (index >= 0 && index < num_slots && slots[index].ship == 0) {
+
752  slots[index].state = READY;
+
753  slots[index].ship = s;
+
754  slots[index].clearance = 0;
+
755 
+
756  if (s->GetGear())
+
757  slots[index].clearance = s->GetGear()->GetClearance();
+
758 
+
759  if (IsRecoveryDeck() && !s->IsAirborne()) {
+
760  s->SetVelocity(s->Velocity() * 0.01); // hit the brakes!
+
761  }
+
762 
+
763  if (!IsRecoveryDeck()) {
+
764  Camera work;
+
765  work.Clone(carrier->Cam());
+
766  work.Yaw(azimuth);
+
767 
+
768  s->CloneCam(work);
+
769  s->MoveTo(slots[index].spot_loc);
+
770 
+
771  LandingGear* g = s->GetGear();
+
772  if (g) {
+ +
774  g->ExecFrame(0);
+ +
776  }
+
777 
+ +
779  }
+
780 
+
781  s->SetCarrier(carrier, this);
+
782  Observe(s);
+
783 
+
784  return true;
+
785  }
+
786 
+
787  return false;
+
788 }
+
789 
+
790 bool
+ +
792 {
+
793  if (index >= 0 && index < num_slots && slots[index].ship != 0) {
+
794  Ship* s = slots[index].ship;
+
795 
+
796  slots[index].ship = 0;
+ +
798  slots[index].state = CLEAR;
+
799 
+ +
801  while (++iter) {
+
802  if (iter->GetShip() == s) {
+
803  delete iter.removeItem(); // ??? SHOULD DELETE HERE ???
+
804  break;
+
805  }
+
806  }
+
807 
+
808  return true;
+
809  }
+
810 
+
811  return false;
+
812 }
+
813 
+
814 // +----------------------------------------------------------------------+
+
815 
+
816 bool
+ +
818 {
+
819  if (subtype == FLIGHT_DECK_LAUNCH && index >= 0 && index < num_slots) {
+
820  FlightDeckSlot* slot = &slots[index];
+
821 
+
822  if (slot->ship && slot->state == READY) {
+
823  int last = 0;
+
824  FlightDeckSlot* last_slot = 0;
+
825  FlightDeckSlot* lock_slot = 0;
+
826 
+
827  for (int i = 0; i < num_slots; i++) {
+
828  FlightDeckSlot* s = &slots[i];
+
829 
+
830  if (s->state == QUEUED && s->sequence > last) {
+
831  last = s->sequence;
+
832  last_slot = s;
+
833  }
+
834 
+
835  else if (s->state == LOCKED) {
+
836  lock_slot = s;
+
837  }
+
838  }
+
839 
+
840  // queue the slot for launch:
+
841  slot->state = QUEUED;
+
842  slot->sequence = last + 1;
+
843  slot->time = 0;
+
844 
+
845  if (last_slot)
+
846  slot->time = last_slot->time + cycle_time;
+
847 
+
848  else if (lock_slot)
+
849  slot->time = lock_slot->time;
+
850 
+
851  return true;
+
852  }
+
853  }
+
854 
+
855  return false;
+
856 }
+
857 
+
858 // +----------------------------------------------------------------------+
+
859 
+
860 bool
+ +
862 {
+
863  if (s && subtype == FLIGHT_DECK_RECOVERY) {
+
864  if (OverThreshold(s)) {
+
865  if (s->GetFlightPhase() < Ship::RECOVERY) {
+ +
867  s->SetCarrier(carrier, this); // let ship know which flight deck it's in (needed for dock cam)
+
868  }
+
869 
+
870  // are we there yet?
+ +
872  if (slots[0].ship == 0) { // only need to ask this on approach
+
873  double dock_distance = (s->Location() - MountLocation()).length();
+
874 
+
875  if (s->IsAirborne()) {
+
876  double altitude = s->Location().y - MountLocation().y;
+
877  if (dock_distance < Radius()*3 && altitude < s->Radius())
+
878  Dock(s);
+
879  }
+
880  else {
+
881  if (dock_distance < s->Radius())
+
882  Dock(s);
+
883  }
+
884  }
+
885  }
+
886 
+
887  return true;
+
888  }
+
889  else {
+
890  if (s->GetFlightPhase() == Ship::RECOVERY)
+ +
892  }
+
893  }
+
894 
+
895  return false;
+
896 }
+
897 
+
898 bool
+ +
900 {
+
901  if (s && subtype == FLIGHT_DECK_RECOVERY && slots[0].time <= 0) {
+
902  int index = 0;
+
903  if (Spot(s, index)) {
+ +
905  s->SetCarrier(carrier, this);
+
906 
+
907  // hard landings?
+
908  if (Ship::GetLandingModel() == 0) {
+
909  double base_damage = s->Design()->integrity;
+
910 
+
911  // did player do something stupid?
+
912  if (s->GetGear() && !s->IsGearDown()) {
+
913  Print("FlightDeck::Dock(%s) Belly landing!\n", s->Name());
+
914  s->InflictDamage(0.5 * base_damage);
+
915  }
+
916 
+
917  double docking_deflection = fabs(carrier->Cam().vup().y - s->Cam().vup().y);
+
918 
+
919  if (docking_deflection > 0.35) {
+
920  Print("Landing upside down? y = %.3f\n", docking_deflection);
+
921  s->InflictDamage(0.8 * base_damage);
+
922  }
+
923 
+
924  // did incoming ship exceed safe landing parameters?
+
925  if (s->IsAirborne()) {
+
926  if (s->Velocity().y < -20) {
+
927  Print("FlightDeck::Dock(%s) Slammed it!\n", s->Name());
+
928  s->InflictDamage(0.1 * base_damage);
+
929  }
+
930  }
+
931 
+
932  // did incoming ship exceed safe docking speed?
+
933  else {
+
934  Point delta_v = s->Velocity() - carrier->Velocity();
+
935  double excess = (delta_v.length() - 100);
+
936 
+
937  if (excess > 0)
+
938  s->InflictDamage(excess);
+
939  }
+
940  }
+
941 
+
942  if (s->IsAirborne()) {
+
943  if (s == Sim::GetSim()->GetPlayerShip() && tire_sound) {
+
944  Sound* sound = tire_sound->Duplicate();
+
945  sound->Play();
+
946  }
+
947  }
+
948 
+
949  if (s->GetDrive())
+
950  s->GetDrive()->PowerOff();
+
951 
+ +
953  slots[index].time = 5;
+
954 
+
955  if (s->IsAirborne())
+
956  slots[index].time = 7.5;
+
957  return true;
+
958  }
+
959  }
+
960 
+
961  return false;
+
962 }
+
963 
+
964 int
+ +
966 {
+
967  if (s && s->GetShip()) {
+
968  Ship* inbound = s->GetShip();
+
969 
+
970  if (recovery_queue.contains(s)) {
+
971  InboundSlot* orig = s;
+
972  s = recovery_queue.find(s);
+
973  delete orig;
+
974  }
+
975  else {
+ +
977  Observe(s->GetShip());
+
978  }
+
979 
+
980  inbound->SetInbound(s);
+
981 
+
982  // find the best initial approach point for this ship:
+
983  double current_distance = 1e9;
+
984  for (int i = 0; i < num_approach_pts; i++) {
+
985  double distance = Point(inbound->Location() - approach_point[i]).length();
+
986  if (distance < current_distance) {
+
987  current_distance = distance;
+
988  s->SetApproach(i);
+
989  }
+
990  }
+
991 
+
992  Point offset(rand()-16000, rand()-16000, rand()-16000);
+
993  offset.Normalize();
+
994  offset *= 200;
+
995 
+
996  s->SetOffset(offset);
+
997 
+
998  // *** DEBUG ***
+
999  // PrintQueue();
+
1000 
+
1001  // if the new guy is first in line, and the deck is almost ready,
+
1002  // go ahead and clear him for approach now
+
1003  recovery_queue.sort();
+
1004  if (recovery_queue[0] == s && !s->Cleared() && slots[0].time <= 3)
+
1005  s->Clear();
+
1006 
+
1007  return recovery_queue.index(s) + 1;
+
1008  }
+
1009 
+
1010  return 0;
+
1011 }
+
1012 
+
1013 void
+ +
1015 {
+
1016  if (recovery_queue.size() > 0) {
+
1017  if (recovery_queue[0]->Cleared() && recovery_queue[0]->Distance() > 45e3) {
+
1018  recovery_queue[0]->Clear(false);
+
1019  }
+
1020 
+
1021  if (!recovery_queue[0]->Cleared()) {
+
1022  recovery_queue.sort();
+
1023 
+
1024  if (recovery_queue[0]->Distance() < 35e3) {
+
1025  recovery_queue[0]->Clear();
+
1026 
+
1027  Ship* dst = recovery_queue[0]->GetShip();
+
1028 
+
1029  RadioMessage* clearance = new(__FILE__,__LINE__) RadioMessage(dst, carrier, RadioMessage::CALL_CLEARANCE);
+
1030  clearance->SetInfo(Text("for final approach to ") + Name());
+
1031  RadioTraffic::Transmit(clearance);
+
1032  }
+
1033  }
+
1034  }
+
1035 }
+
1036 
+
1037 // +----------------------------------------------------------------------+
+
1038 
+
1039 void
+ +
1041 {
+
1042  Print("\nRecovery Queue for %s\n", Name());
+
1043  if (recovery_queue.size() < 1) {
+
1044  Print(" (empty)\n\n");
+
1045  return;
+
1046  }
+
1047 
+
1048  for (int i = 0; i < recovery_queue.size(); i++) {
+
1049  InboundSlot* s = recovery_queue.at(i);
+
1050 
+
1051  if (!s) {
+
1052  Print(" %2d. null\n", i);
+
1053  }
+
1054  else if (!s->GetShip()) {
+
1055  Print(" %2d. ship is null\n", i);
+
1056  }
+
1057  else {
+
1058  double d = Point(s->GetShip()->Location() - MountLocation()).length();
+
1059  Print(" %2d. %c %-20s %8d km\n", i, s->Cleared()?'*':' ', s->GetShip()->Name(), (int) (d/1000));
+
1060  }
+
1061  }
+
1062 
+
1063  Print("\n");
+
1064 }
+
1065 
+
1066 // +----------------------------------------------------------------------+
+
1067 
+
1068 Ship*
+
1069 FlightDeck::GetShip(int index) const
+
1070 {
+
1071  if (index >= 0 && index < num_slots)
+
1072  return slots[index].ship;
+
1073 
+
1074  return 0;
+
1075 }
+
1076 
+
1077 double
+ +
1079 {
+
1080  if (index >= 0 && index < num_slots)
+
1081  return slots[index].time;
+
1082 
+
1083  return 0;
+
1084 }
+
1085 
+
1086 
+
1087 int
+
1088 FlightDeck::State(int index) const
+
1089 {
+
1090  if (index >= 0 && index < num_slots)
+
1091  return slots[index].state;
+
1092 
+
1093  return 0;
+
1094 }
+
1095 
+
1096 int
+
1097 FlightDeck::Sequence(int index) const
+
1098 {
+
1099  if (index >= 0 && index < num_slots)
+
1100  return slots[index].sequence;
+
1101 
+
1102  return 0;
+
1103 }
+
1104 
+
1105 // +----------------------------------------------------------------------+
+
1106 
+
1107 bool
+ +
1109 {
+
1110  if (obj->Type() == SimObject::SIM_SHIP) {
+
1111  Ship* s = (Ship*) obj;
+
1112 
+ +
1114  while (++iter) {
+
1115  InboundSlot* recovery_slot = iter.value();
+
1116 
+
1117  if (recovery_slot->GetShip() == s || recovery_slot->GetShip() == 0) {
+
1118  delete iter.removeItem();
+
1119  }
+
1120  }
+
1121 
+
1122  for (int i = 0; i < num_slots; i++) {
+
1123  FlightDeckSlot* slot = &slots[i];
+
1124 
+
1125  if (slot->ship == s) {
+
1126  slot->ship = 0;
+
1127  slot->state = 0;
+
1128  slot->sequence = 0;
+
1129  slot->time = 0;
+
1130  break;
+
1131  }
+
1132  }
+
1133  }
+
1134 
+
1135  return SimObserver::Update(obj);
+
1136 }
+
1137 
+
1138 const char*
+ +
1140 {
+
1141  return Name();
+
1142 }
+
1143 
+
1144 // +----------------------------------------------------------------------+
+
1145 
+
1146 bool
+ +
1148 {
+
1149  if (carrier->IsAirborne()) {
+
1150  if (s->AltitudeAGL() > s->Radius() * 4)
+
1151  return false;
+
1152 
+
1153  const Point& sloc = s->Location();
+
1154 
+
1155  // is ship between the markers?
+
1156  double distance = 1e9;
+
1157 
+
1158  Point d0 = runway_point[0] - sloc;
+
1159  Point d1 = runway_point[1] - sloc;
+
1160  double d = d0 * d1;
+
1161  bool between = (d0 * d1) < 0;
+
1162 
+
1163  if (between) {
+
1164  // distance from point to line:
+
1165  Point src = runway_point[0];
+
1166  Point dir = runway_point[1] - src;
+
1167  Point w = (sloc - src).cross(dir);
+
1168 
+
1169  distance = w.length() / dir.length();
+
1170  }
+
1171 
+
1172  return distance < Radius();
+
1173  }
+
1174 
+
1175  else {
+
1176  return (s->Location() - MountLocation()).length() < (s->Radius() + Radius());
+
1177  }
+
1178 }
+
1179 
+
1180 // +----------------------------------------------------------------------+
+
1181 
+
1182 bool
+ +
1184 {
+
1185  return (p - MountLocation()).length() < Radius();
+
1186 }
+
+
+ + + + -- cgit v1.1