From b829170121d3657369904ec62d8065606777a9ce Mon Sep 17 00:00:00 2001 From: Aki Date: Fri, 1 Oct 2021 18:54:04 +0200 Subject: Removed doxygen generated docs They can be rebuild anytime and are considered a build artifact/binary. --- Doc/doxygen/html/_tactical_a_i_8cpp_source.html | 1076 ----------------------- 1 file changed, 1076 deletions(-) delete mode 100644 Doc/doxygen/html/_tactical_a_i_8cpp_source.html (limited to 'Doc/doxygen/html/_tactical_a_i_8cpp_source.html') diff --git a/Doc/doxygen/html/_tactical_a_i_8cpp_source.html b/Doc/doxygen/html/_tactical_a_i_8cpp_source.html deleted file mode 100644 index 2defd52..0000000 --- a/Doc/doxygen/html/_tactical_a_i_8cpp_source.html +++ /dev/null @@ -1,1076 +0,0 @@ - - - - - -Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/TacticalAI.cpp Source File - - - - - - - - - - - - - -
-
- - - - - - -
-
Starshatter_Open -
-
Open source Starshatter engine
-
-
- - - - - -
-
- -
-
-
- -
- - - - -
- -
- -
-
-
TacticalAI.cpp
-
-
-Go to the documentation of this file.
1 /* Project Starshatter 4.5
-
2  Destroyer Studios LLC
-
3  Copyright (C) 1997-2004. All Rights Reserved.
-
4 
-
5  SUBSYSTEM: Stars.exe
-
6  FILE: TacticalAI.cpp
-
7  AUTHOR: John DiCamillo
-
8 
-
9 
-
10  OVERVIEW
-
11  ========
-
12  Generic Ship Tactical Level AI class
-
13 */
-
14 
-
15 #include "MemDebug.h"
-
16 #include "TacticalAI.h"
-
17 #include "ShipAI.h"
-
18 #include "CarrierAI.h"
-
19 #include "Ship.h"
-
20 #include "ShipDesign.h"
-
21 #include "Element.h"
-
22 #include "Instruction.h"
-
23 #include "RadioMessage.h"
-
24 #include "RadioTraffic.h"
-
25 #include "Contact.h"
-
26 #include "WeaponGroup.h"
-
27 #include "Drive.h"
-
28 #include "Hangar.h"
-
29 #include "Sim.h"
-
30 #include "Shot.h"
-
31 #include "Drone.h"
-
32 #include "StarSystem.h"
-
33 
-
34 #include "Game.h"
-
35 #include "Random.h"
-
36 
-
37 // +----------------------------------------------------------------------+
-
38 
-
39 static int exec_time_seed = 0;
-
40 
-
41 // +----------------------------------------------------------------------+
-
42 
- -
44 : ship(0), ship_ai(0), carrier_ai(0), navpt(0), orders(0),
-
45 action(0), threat_level(0), support_level(1),
-
46 directed_tgtid(0)
-
47 {
-
48  if (ai) {
-
49  ship_ai = ai;
-
50  ship = ai->GetShip();
-
51 
-
52  Sim* sim = Sim::GetSim();
-
53 
-
54  if (ship && ship->GetHangar() && ship->GetCommandAILevel() > 0 &&
-
55  ship != sim->GetPlayerShip())
-
56  carrier_ai = new(__FILE__,__LINE__) CarrierAI(ship, ship_ai->GetAILevel());
-
57  }
-
58 
-
59  agression = 0;
-
60  roe = FLEXIBLE;
-
61  element_index = 1;
-
62  exec_time = exec_time_seed;
-
63  exec_time_seed += 17;
-
64 }
-
65 
- -
67 {
-
68  delete carrier_ai;
-
69 }
-
70 
-
71 // +--------------------------------------------------------------------+
-
72 
-
73 void
- -
75 {
-
76  const int exec_period = 1000;
-
77 
-
78  if (!ship || !ship_ai)
-
79  return;
-
80 
- - -
83 
-
84  if ((int) Game::GameTime() - exec_time > exec_period) {
- -
86 
-
87  CheckOrders();
-
88  SelectTarget();
-
89  FindThreat();
-
90  FindSupport();
-
91 
-
92  if (element_index > 1) {
-
93  int formation = 0;
-
94 
-
95  if (orders && orders->Formation() >= 0)
-
96  formation = orders->Formation();
-
97 
-
98  else if (navpt)
-
99  formation = navpt->Formation();
-
100 
-
101  FindFormationSlot(formation);
-
102  }
-
103 
- -
105 
-
106  if (carrier_ai)
-
107  carrier_ai->ExecFrame(secs);
-
108 
-
109  exec_time += exec_period;
-
110  }
-
111 }
-
112 
-
113 // +--------------------------------------------------------------------+
-
114 
-
115 void
- -
117 {
-
118  directed_tgtid = 0;
-
119 
-
120  if (CheckShipOrders())
-
121  return;
-
122 
-
123  if (CheckFlightPlan())
-
124  return;
-
125 
-
126  if (CheckObjectives())
-
127  return;
-
128 }
-
129 
-
130 // +--------------------------------------------------------------------+
-
131 
-
132 bool
- -
134 {
-
135  return ProcessOrders();
-
136 }
-
137 
-
138 // +--------------------------------------------------------------------+
-
139 
-
140 bool
- -
142 {
-
143  bool processed = false;
-
144  Ship* ward = 0;
-
145  Element* elem = ship->GetElement();
-
146 
-
147  if (elem) {
-
148  Instruction* obj = elem->GetTargetObjective();
-
149 
-
150  if (obj) {
-
151  ship_ai->ClearPatrol();
-
152 
-
153  if (obj->Action()) {
-
154  switch (obj->Action()) {
- -
156  case Instruction::STRIKE:
- -
158  {
-
159  SimObject* tgt = obj->GetTarget();
-
160  if (tgt && tgt->Type() == SimObject::SIM_SHIP) {
-
161  roe = DIRECTED;
-
162  SelectTargetDirected((Ship*) tgt);
-
163  }
-
164  }
-
165  break;
-
166 
-
167  case Instruction::DEFEND:
-
168  case Instruction::ESCORT:
-
169  {
-
170  SimObject* tgt = obj->GetTarget();
-
171  if (tgt && tgt->Type() == SimObject::SIM_SHIP) {
-
172  roe = DEFENSIVE;
-
173  ward = (Ship*) tgt;
-
174  }
-
175  }
-
176  break;
-
177 
-
178  default:
-
179  break;
-
180  }
-
181  }
-
182 
-
183  orders = obj;
-
184  processed = true;
-
185  }
-
186  }
-
187 
-
188  ship_ai->SetWard(ward);
-
189  return processed;
-
190 }
-
191 
-
192 // +--------------------------------------------------------------------+
-
193 
-
194 bool
- -
196 {
-
197  if (ship_ai)
-
198  ship_ai->ClearPatrol();
-
199 
-
200  if (orders && orders->EMCON() > 0) {
-
201  int desired_emcon = orders->EMCON();
-
202 
- -
204  desired_emcon = 3;
-
205 
-
206  if (ship->GetEMCON() != desired_emcon)
-
207  ship->SetEMCON(desired_emcon);
-
208  }
-
209 
-
210  if (orders && orders->Action()) {
-
211  switch (orders->Action()) {
- - - -
215  {
-
216  bool tgt_ok = false;
-
217  SimObject* tgt = orders->GetTarget();
-
218 
-
219  if (tgt && tgt->Type() == SimObject::SIM_SHIP) {
-
220  Ship* tgt_ship = (Ship*) tgt;
-
221 
-
222  if (CanTarget(tgt_ship)) {
-
223  roe = DIRECTED;
-
224  SelectTargetDirected((Ship*) tgt);
-
225 
- - -
228  ship_ai->SetNavPoint(0);
-
229 
-
230  tgt_ok = true;
-
231  }
-
232  }
-
233 
-
234  if (!tgt_ok)
- -
236  }
-
237  break;
-
238 
- - -
241  {
-
242  SimObject* tgt = orders->GetTarget();
-
243  if (tgt && tgt->Type() == SimObject::SIM_SHIP) {
-
244  roe = DEFENSIVE;
-
245  ship_ai->SetWard((Ship*) tgt);
-
246  ship_ai->SetNavPoint(0);
-
247  }
-
248  else {
- -
250  }
-
251  }
-
252  break;
-
253 
- -
255  roe = AGRESSIVE;
-
256  ship_ai->DropTarget(0.1);
-
257  break;
-
258 
- - -
261  roe = NONE;
-
262  ship_ai->DropTarget(5);
-
263  break;
-
264 
- - - -
268  ship_ai->SetNavPoint(0);
-
269  ship_ai->DropTarget(Random(5, 10));
-
270  break;
-
271 
-
272  case RadioMessage::RTB:
- -
274  roe = NONE;
-
275 
-
276  ship_ai->DropTarget(10);
-
277 
-
278  if (!ship->GetInbound()) {
-
279  RadioMessage* msg = 0;
-
280  Ship* controller = ship->GetController();
-
281 
- -
283  controller = (Ship*) orders->GetTarget();
-
284  }
-
285 
-
286  if (!controller) {
-
287  Element* elem = ship->GetElement();
-
288  if (elem && elem->GetCommander()) {
-
289  Element* cmdr = elem->GetCommander();
-
290  controller = cmdr->GetShip(1);
-
291  }
-
292  }
-
293 
-
294  if (controller && controller->GetHangar() &&
-
295  controller->GetHangar()->CanStow(ship)) {
-
296  SimRegion* self_rgn = ship->GetRegion();
-
297  SimRegion* rtb_rgn = controller->GetRegion();
-
298 
-
299  if (self_rgn == rtb_rgn) {
-
300  double range = Point(controller->Location() - ship->Location()).length();
-
301 
-
302  if (range < 50e3) {
-
303  msg = new(__FILE__,__LINE__) RadioMessage(controller, ship, RadioMessage::CALL_INBOUND);
- -
305  }
-
306  }
-
307  }
-
308  else {
- -
310  }
-
311 
-
312  ship_ai->SetNavPoint(0);
-
313  }
-
314  break;
-
315 
- - -
318  roe = NONE;
-
319  ship_ai->DropTarget(10);
-
320  break;
-
321 
-
322  }
-
323 
-
324  action = orders->Action();
-
325  return true;
-
326  }
-
327 
-
328  // if we had an action before, this must be a "cancel orders"
-
329  else if (action) {
- -
331  }
-
332 
-
333  return false;
-
334 }
-
335 
-
336 void
- -
338 {
-
339  action = 0;
-
340  roe = FLEXIBLE;
-
341 
-
342  if (ship_ai)
-
343  ship_ai->DropTarget(0.1);
-
344 
-
345  if (ship)
- -
347 
-
348 }
-
349 
-
350 // +--------------------------------------------------------------------+
-
351 
-
352 bool
- -
354 {
-
355  Ship* ward = 0;
-
356 
-
357  // Find next Instruction:
- -
359 
-
360  roe = FLEXIBLE;
-
361 
-
362  if (navpt) {
-
363  switch (navpt->Action()) {
-
364  case Instruction::LAUNCH:
-
365  case Instruction::DOCK:
-
366  case Instruction::RTB: roe = NONE;
-
367  break;
-
368 
- -
370  break;
-
371 
-
372  case Instruction::DEFEND:
- -
374  break;
-
375 
- -
377  roe = DIRECTED;
-
378  break;
-
379 
-
380  case Instruction::RECON:
-
381  case Instruction::STRIKE:
- -
383  break;
-
384 
-
385  case Instruction::PATROL:
- -
387  break;
-
388 
-
389  default: break;
-
390  }
-
391 
-
392  if (roe == DEFENSIVE) {
-
393  SimObject* tgt = navpt->GetTarget();
-
394 
-
395  if (tgt && tgt->Type() == SimObject::SIM_SHIP)
-
396  ward = (Ship*) tgt;
-
397  }
-
398 
-
399 
-
400  if (navpt->EMCON() > 0) {
-
401  int desired_emcon = navpt->EMCON();
-
402 
- -
404  desired_emcon = 3;
-
405 
-
406  if (ship->GetEMCON() != desired_emcon)
-
407  ship->SetEMCON(desired_emcon);
-
408  }
-
409  }
-
410 
-
411  if (ship_ai)
-
412  ship_ai->SetWard(ward);
-
413 
-
414  return (navpt != 0);
-
415 }
-
416 
-
417 // +--------------------------------------------------------------------+
-
418 
-
419 void
- -
421 {
-
422  if (!ship) {
-
423  roe = NONE;
-
424  return;
-
425  }
-
426 
-
427  // unarmed vessels should never engage an enemy:
-
428  if (ship->Weapons().size() < 1)
-
429  roe = NONE;
-
430 
-
431  SimObject* target = ship_ai->GetTarget();
-
432  SimObject* ward = ship_ai->GetWard();
-
433 
-
434  // if not allowed to engage, drop and return:
-
435  if (roe == NONE) {
-
436  if (target)
-
437  ship_ai->DropTarget();
-
438  return;
-
439  }
-
440 
-
441  // if we have abandoned our ward, drop and return:
-
442  if (ward && roe != AGRESSIVE) {
-
443  double d = (ward->Location() - ship->Location()).length();
-
444  double safe_zone = 50e3;
-
445 
-
446  if (target) {
-
447  if (ship->IsStarship())
-
448  safe_zone = 100e3;
-
449 
-
450  if (d > safe_zone) {
-
451  ship_ai->DropTarget();
-
452  return;
-
453  }
-
454  }
-
455  else {
-
456  if (d > safe_zone) {
-
457  return;
-
458  }
-
459  }
-
460  }
-
461 
-
462  // already have a target, keep it:
-
463  if (target) {
-
464  if (target->Life()) {
-
465  CheckTarget();
-
466 
-
467  // frigates need to be ready to abandon ship-type targets
-
468  // in favor of drone-type targets, others should just go
-
469  // with what they have:
-
470  if (ship->Class() != Ship::CORVETTE && ship->Class() != Ship::FRIGATE)
-
471  return;
-
472 
-
473  // in case the check decided to drop the target:
-
474  target = ship_ai->GetTarget();
-
475  }
-
476 
-
477  // if the old target is dead, forget it:
-
478  else {
-
479  ship_ai->DropTarget();
-
480  target = 0;
-
481  }
-
482  }
-
483 
-
484  // if not allowed to acquire, forget it:
-
485  if (ship_ai->DropTime() > 0)
-
486  return;
-
487 
-
488  if (roe == DIRECTED) {
-
489  if (target && target->Type() == SimObject::SIM_SHIP)
-
490  SelectTargetDirected((Ship*) target);
-
491  else if (navpt && navpt->GetTarget() && navpt->GetTarget()->Type() == SimObject::SIM_SHIP)
- -
493  else
- -
495  }
-
496 
-
497  else {
- -
499 
-
500  // don't switch one ship target for another...
-
501  if (ship->Class() == Ship::CORVETTE || ship->Class() == Ship::FRIGATE) {
-
502  SimObject* potential_target = ship_ai->GetTarget();
-
503  if (target && potential_target && target != potential_target) {
-
504  if (target->Type() == SimObject::SIM_SHIP &&
-
505  potential_target->Type() == SimObject::SIM_SHIP) {
-
506 
-
507  ship_ai->SetTarget(target);
-
508  }
-
509  }
-
510  }
-
511  }
-
512 }
-
513 
-
514 // +--------------------------------------------------------------------+
-
515 
-
516 void
- -
518 {
-
519  Ship* potential_target = tgt;
-
520 
-
521  // try to target one of the element's objectives
-
522  // (if it shows up in the contact list)
-
523 
-
524  if (!tgt) {
-
525  Element* elem = ship->GetElement();
-
526 
-
527  if (elem) {
-
528  Instruction* objective = elem->GetTargetObjective();
-
529 
-
530  if (objective) {
-
531  SimObject* obj_sim_obj = objective->GetTarget();
-
532  Ship* obj_tgt = 0;
-
533 
-
534  if (obj_sim_obj && obj_sim_obj->Type() == SimObject::SIM_SHIP)
-
535  obj_tgt = (Ship*) obj_sim_obj;
-
536 
-
537  if (obj_tgt) {
-
538  ListIter<Contact> contact = ship->ContactList();
-
539  while (++contact && !potential_target) {
-
540  Ship* test = contact->GetShip();
-
541 
-
542  if (obj_tgt == test) {
-
543  potential_target = test;
-
544  }
-
545  }
-
546  }
-
547  }
-
548  }
-
549  }
-
550 
-
551  if (!CanTarget(potential_target))
-
552  potential_target = 0;
-
553 
-
554  ship_ai->SetTarget(potential_target);
-
555 
-
556  if (tgt && tgt == ship_ai->GetTarget())
-
557  directed_tgtid = tgt->Identity();
-
558  else
-
559  directed_tgtid = 0;
-
560 }
-
561 
-
562 // +--------------------------------------------------------------------+
-
563 
-
564 bool
- -
566 {
-
567  bool result = false;
-
568 
-
569  if (tgt && !tgt->InTransition()) {
-
570  if (tgt->IsRogue() || tgt->GetIFF() != ship->GetIFF())
-
571  result = true;
-
572  }
-
573 
-
574  return result;
-
575 }
-
576 
-
577 // +--------------------------------------------------------------------+
-
578 
-
579 void
- -
581 {
-
582  // NON-COMBATANTS do not pick targets of opportunity:
-
583  if (ship->GetIFF() == 0)
-
584  return;
-
585 
-
586  SimObject* potential_target = 0;
-
587 
-
588  // pick the closest combatant ship with a different IFF code:
-
589  double target_dist = ship->Design()->commit_range;
-
590 
-
591  SimObject* ward = ship_ai->GetWard();
-
592 
-
593  // FRIGATES are primarily anti-air platforms, but may
-
594  // also attack smaller starships:
-
595 
-
596  if (ship->Class() == Ship::CORVETTE || ship->Class() == Ship::FRIGATE) {
-
597  Ship* current_ship_target = 0;
-
598  Shot* current_shot_target = 0;
-
599 
-
600  // if we are escorting a larger warship, it is good to attack
-
601  // the same target as our ward:
-
602 
-
603  if (ward) {
-
604  Ship* s = (Ship*) ward;
-
605 
-
606  if (s->Class() > ship->Class()) {
-
607  SimObject* obj = s->GetTarget();
-
608 
-
609  if (obj && obj->Type() == SimObject::SIM_SHIP) {
-
610  current_ship_target = (Ship*) obj;
-
611  target_dist = (ship->Location() - obj->Location()).length();
-
612  }
-
613  }
-
614  }
-
615 
-
616  ListIter<Contact> contact = ship->ContactList();
-
617  while (++contact) {
-
618  Ship* c_ship = contact->GetShip();
-
619  Shot* c_shot = contact->GetShot();
-
620 
-
621  if (!c_ship && !c_shot)
-
622  continue;
-
623 
-
624  int c_iff = contact->GetIFF(ship);
-
625  bool rogue = c_ship && c_ship->IsRogue();
-
626  bool tgt_ok = c_iff > 0 &&
-
627  c_iff != ship->GetIFF() &&
-
628  c_iff < 1000;
-
629 
-
630  if (rogue || tgt_ok) {
-
631  if (c_ship && c_ship != ship && !c_ship->InTransition()) {
-
632  if (c_ship->Class() < Ship::DESTROYER ||
-
633  (c_ship->Class() >= Ship::MINE && c_ship->Class() <= Ship::SWACS)) {
-
634  // found an enemy, check distance:
-
635  double dist = (ship->Location() - c_ship->Location()).length();
-
636 
-
637  if (dist < 0.75 * target_dist &&
-
638  (!current_ship_target || c_ship->Class() <= current_ship_target->Class())) {
-
639  current_ship_target = c_ship;
-
640  target_dist = dist;
-
641  }
-
642  }
-
643  }
-
644 
-
645  else if (c_shot) {
-
646  // found an enemy shot, is there enough time to engage?
-
647  if (c_shot->GetEta() < 3)
-
648  continue;
-
649 
-
650  // found an enemy shot, check distance:
-
651  double dist = (ship->Location() - c_shot->Location()).length();
-
652 
-
653  if (!current_shot_target) {
-
654  current_shot_target = c_shot;
-
655  target_dist = dist;
-
656  }
-
657 
-
658  // is this shot a better target than the one we've found?
-
659  else {
-
660  Ship* ward = ship_ai->GetWard();
-
661 
-
662  if ((c_shot->IsTracking(ward) || c_shot->IsTracking(ship)) &&
-
663  (!current_shot_target->IsTracking(ward) ||
-
664  !current_shot_target->IsTracking(ship))) {
-
665  current_shot_target = c_shot;
-
666  target_dist = dist;
-
667  }
-
668  else if (dist < target_dist) {
-
669  current_shot_target = c_shot;
-
670  target_dist = dist;
-
671  }
-
672  }
-
673  }
-
674  }
-
675  }
-
676 
-
677  if (current_shot_target)
-
678  potential_target = current_shot_target;
-
679  else
-
680  potential_target = current_ship_target;
-
681  }
-
682 
-
683  // ALL OTHER SHIP CLASSES ignore fighters and only engage
-
684  // other starships:
-
685 
-
686  else {
-
687  List<Ship> ward_threats;
-
688 
-
689  ListIter<Contact> contact = ship->ContactList();
-
690  while (++contact) {
-
691  Ship* c_ship = contact->GetShip();
-
692 
-
693  if (!c_ship)
-
694  continue;
-
695 
-
696  int c_iff = contact->GetIFF(ship);
-
697  bool rogue = c_ship->IsRogue();
-
698  bool tgt_ok = c_ship != ship &&
-
699  c_iff > 0 &&
-
700  c_iff != ship->GetIFF() &&
-
701  !c_ship->InTransition();
-
702 
-
703  if (rogue || tgt_ok) {
-
704  if (c_ship->IsStarship() || c_ship->IsStatic()) {
-
705  // found an enemy, check distance:
-
706  double dist = (ship->Location() - c_ship->Location()).length();
-
707 
-
708  if (dist < 0.75 * target_dist) {
-
709  potential_target = c_ship;
-
710  target_dist = dist;
-
711  }
-
712 
-
713  if (ward && c_ship->IsTracking(ward)) {
-
714  ward_threats.append(c_ship);
-
715  }
-
716  }
-
717  }
-
718  }
-
719 
-
720  // if this ship is protecting a ward,
-
721  // prefer targets that are threatening that ward:
-
722  if (potential_target && ward_threats.size() && !ward_threats.contains((Ship*)potential_target)) {
-
723  target_dist *= 2;
-
724 
-
725  ListIter<Ship> iter = ward_threats;
-
726  while (++iter) {
-
727  Ship* threat = iter.value();
-
728 
-
729  double dist = (ward->Location() - threat->Location()).length();
-
730 
-
731  if (dist < target_dist) {
-
732  potential_target = threat;
-
733  target_dist = dist;
-
734  }
-
735  }
-
736  }
-
737  }
-
738 
-
739  if (ship->Class() != Ship::CARRIER)
-
740  ship_ai->SetTarget(potential_target);
-
741 }
-
742 
-
743 // +--------------------------------------------------------------------+
-
744 
-
745 void
- -
747 {
-
748  SimObject* tgt = ship_ai->GetTarget();
-
749 
-
750  if (!tgt) return;
-
751 
-
752  if (tgt->GetRegion() != ship->GetRegion()) {
-
753  ship_ai->DropTarget();
-
754  return;
-
755  }
-
756 
-
757  if (tgt->Type() == SimObject::SIM_SHIP) {
-
758  Ship* target = (Ship*) tgt;
-
759 
-
760  // has the target joined our side?
-
761  if (target->GetIFF() == ship->GetIFF() && !target->IsRogue()) {
-
762  ship_ai->DropTarget();
-
763  return;
-
764  }
-
765 
-
766  // is the target already jumping/breaking/dying?
-
767  if (target->InTransition()) {
-
768  ship_ai->DropTarget();
-
769  return;
-
770  }
-
771 
-
772  // have we been ordered to pursue the target?
-
773  if (directed_tgtid) {
-
774  if (directed_tgtid != target->Identity()) {
-
775  ship_ai->DropTarget();
-
776  }
-
777 
-
778  return;
-
779  }
-
780 
-
781  // can we catch the target?
-
782  if (target->Design()->vlimit <= ship->Design()->vlimit ||
-
783  ship->Velocity().length() <= ship->Design()->vlimit)
-
784  return;
-
785 
-
786  // is the target now out of range?
-
787  WeaponDesign* wep_dsn = ship->GetPrimaryDesign();
-
788  if (!wep_dsn)
-
789  return;
-
790 
-
791  // compute the "give up" range:
-
792  double drop_range = 3 * wep_dsn->max_range;
-
793  if (drop_range > 0.75 * ship->Design()->commit_range)
-
794  drop_range = 0.75 * ship->Design()->commit_range;
-
795 
-
796  double range = Point(target->Location() - ship->Location()).length();
-
797  if (range < drop_range)
-
798  return;
-
799 
-
800  // is the target closing or separating?
-
801  Point delta = (target->Location() + target->Velocity()) -
-
802  (ship->Location() + ship->Velocity());
-
803 
-
804  if (delta.length() < range)
-
805  return;
-
806 
-
807  ship_ai->DropTarget();
-
808  }
-
809 
-
810  else if (tgt->Type() == SimObject::SIM_DRONE) {
-
811  Drone* drone = (Drone*) tgt;
-
812 
-
813  // is the target still a threat?
-
814  if (drone->GetEta() < 1 || drone->GetTarget() == 0)
-
815  ship_ai->DropTarget();
-
816  }
-
817 }
-
818 
-
819 // +--------------------------------------------------------------------+
-
820 
-
821 void
- -
823 {
-
824  // pick the closest contact on Threat Warning System:
-
825  Ship* threat = 0;
-
826  Shot* threat_missile = 0;
-
827  Ship* rumor = 0;
-
828  double threat_dist = 1e9;
-
829  const DWORD THREAT_REACTION_TIME = 1000; // 1 second
-
830 
- -
832 
-
833  while (++iter) {
-
834  Contact* contact = iter.value();
-
835 
-
836  if (contact->Threat(ship) &&
-
837  (Game::GameTime() - contact->AcquisitionTime()) > THREAT_REACTION_TIME) {
-
838 
-
839  if (contact->GetShot()) {
-
840  threat_missile = contact->GetShot();
-
841  rumor = (Ship*) threat_missile->Owner();
-
842  }
-
843  else {
-
844  double rng = contact->Range(ship);
-
845 
-
846  Ship* c_ship = contact->GetShip();
-
847  if (c_ship && !c_ship->InTransition() &&
-
848  c_ship->Class() != Ship::FREIGHTER &&
-
849  c_ship->Class() != Ship::FARCASTER) {
-
850 
-
851  if (c_ship->GetTarget() == ship) {
-
852  if (!threat || c_ship->Class() > threat->Class()) {
-
853  threat = c_ship;
-
854  threat_dist = 0;
-
855  }
-
856  }
-
857  else if (rng < threat_dist) {
-
858  threat = c_ship;
-
859  threat_dist = rng;
-
860  }
-
861  }
-
862  }
-
863  }
-
864  }
-
865 
-
866  if (rumor && !rumor->InTransition()) {
-
867  iter.reset();
-
868 
-
869  while (++iter) {
-
870  if (iter->GetShip() == rumor) {
-
871  rumor = 0;
-
872  ship_ai->ClearRumor();
-
873  break;
-
874  }
-
875  }
-
876  }
-
877  else {
-
878  rumor = 0;
-
879  ship_ai->ClearRumor();
-
880  }
-
881 
-
882  ship_ai->SetRumor(rumor);
-
883  ship_ai->SetThreat(threat);
-
884  ship_ai->SetThreatMissile(threat_missile);
-
885 }
-
886 
-
887 // +--------------------------------------------------------------------+
-
888 
-
889 void
- -
891 {
-
892  if (!ship_ai->GetThreat()) {
-
893  ship_ai->SetSupport(0);
-
894  return;
-
895  }
-
896 
-
897  // pick the biggest friendly contact in the sector:
-
898  Ship* support = 0;
-
899  double support_dist = 1e9;
-
900 
-
901  ListIter<Contact> contact = ship->ContactList();
-
902 
-
903  while (++contact) {
-
904  if (contact->GetShip() && contact->GetIFF(ship) == ship->GetIFF()) {
-
905  Ship* c_ship = contact->GetShip();
-
906 
-
907  if (c_ship != ship && c_ship->Class() >= ship->Class() && !c_ship->InTransition()) {
-
908  if (!support || c_ship->Class() > support->Class())
-
909  support = c_ship;
-
910  }
-
911  }
-
912  }
-
913 
-
914  ship_ai->SetSupport(support);
-
915 }
-
916 
-
917 // +--------------------------------------------------------------------+
-
918 
-
919 void
- -
921 {
-
922  // find the formation delta:
-
923  int s = element_index - 1;
-
924  Point delta(10*s, 0, 10*s);
-
925 
-
926  // diamond:
-
927  if (formation == Instruction::DIAMOND) {
-
928  switch (element_index) {
-
929  case 2: delta = Point( 10, 0, -12); break;
-
930  case 3: delta = Point(-10, 0, -12); break;
-
931  case 4: delta = Point( 0, 0, -24); break;
-
932  }
-
933  }
-
934 
-
935  // spread:
-
936  if (formation == Instruction::SPREAD) {
-
937  switch (element_index) {
-
938  case 2: delta = Point( 15, 0, 0); break;
-
939  case 3: delta = Point(-15, 0, 0); break;
-
940  case 4: delta = Point(-30, 0, 0); break;
-
941  }
-
942  }
-
943 
-
944  // box:
-
945  if (formation == Instruction::BOX) {
-
946  switch (element_index) {
-
947  case 2: delta = Point(15, 0, 0); break;
-
948  case 3: delta = Point( 0, -1, -15); break;
-
949  case 4: delta = Point(15, -1, -15); break;
-
950  }
-
951  }
-
952 
-
953  // trail:
-
954  if (formation == Instruction::TRAIL) {
-
955  delta = Point(0, 0, -15*s);
-
956  }
-
957 
-
958  ship_ai->SetFormationDelta(delta * ship->Radius() * 2);
-
959 }
-
-
- - - - -- cgit v1.1