Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
GroundAI.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: GroundAI.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Low-Level Artificial Intelligence class for Ground Units
13 */
14 
15 #include "MemDebug.h"
16 #include "GroundAI.h"
17 #include "SteerAI.h"
18 #include "System.h"
19 #include "Ship.h"
20 #include "ShipDesign.h"
21 #include "Shield.h"
22 #include "Sim.h"
23 #include "Player.h"
24 #include "CarrierAI.h"
25 #include "Contact.h"
26 #include "Weapon.h"
27 #include "WeaponGroup.h"
28 
29 #include "Game.h"
30 #include "Physical.h"
31 
32 // +----------------------------------------------------------------------+
33 
35 : ship((Ship*) s), target(0), subtarget(0), exec_time(0), carrier_ai(0)
36 {
37  Sim* sim = Sim::GetSim();
38  Ship* pship = sim->GetPlayerShip();
39  int player_team = 1;
40  int ai_level = 1;
41 
42  if (pship)
43  player_team = pship->GetIFF();
44 
45  Player* player = Player::GetCurrentPlayer();
46  if (player) {
47  if (ship && ship->GetIFF() && ship->GetIFF() != player_team) {
48  ai_level = player->AILevel();
49  }
50  else if (player->AILevel() == 0) {
51  ai_level = 1;
52  }
53  }
54 
55  // evil alien ships are *always* smart:
56  if (ship && ship->GetIFF() > 1 && ship->Design()->auto_roll > 1) {
57  ai_level = 2;
58  }
59 
60  if (ship && ship->GetHangar() && ship->GetCommandAILevel() > 0)
61  carrier_ai = new(__FILE__,__LINE__) CarrierAI(ship, ai_level);
62 }
63 
64 
65 // +--------------------------------------------------------------------+
66 
68 {
69  delete carrier_ai;
70 }
71 
72 // +--------------------------------------------------------------------+
73 
74 void
76 {
77  if (target != targ) {
78  target = targ;
79 
80  if (target)
81  Observe(target);
82  }
83 
84  subtarget = sub;
85 }
86 
87 // +--------------------------------------------------------------------+
88 
89 bool
91 {
92  if (obj == target) {
93  target = 0;
94  subtarget = 0;
95  }
96 
97  return SimObserver::Update(obj);
98 }
99 
100 const char*
102 {
103  static char name[64];
104  sprintf_s(name, "GroundAI(%s)", ship->Name());
105  return name;
106 }
107 
108 // +--------------------------------------------------------------------+
109 
110 void
112 {
113  SimObject* potential_target = 0;
114 
115  // pick the closest combatant ship with a different IFF code:
116  double target_dist = 1.0e15;
117 
118  Ship* current_ship_target = 0;
119 
120  ListIter<Contact> c_iter = ship->ContactList();
121  while (++c_iter) {
122  Contact* contact = c_iter.value();
123  int c_iff = contact->GetIFF(ship);
124  Ship* c_ship = contact->GetShip();
125  Shot* c_shot = contact->GetShot();
126  bool rogue = false;
127 
128  if (c_ship)
129  rogue = c_ship->IsRogue();
130 
131  if (rogue || c_iff > 0 && c_iff != ship->GetIFF() && c_iff < 1000) {
132  if (c_ship && !c_ship->InTransition()) {
133  // found an enemy, check distance:
134  double dist = (ship->Location() - c_ship->Location()).length();
135 
136  if (!current_ship_target || (c_ship->Class() <= current_ship_target->Class() &&
137  dist < target_dist)) {
138  current_ship_target = c_ship;
139  target_dist = dist;
140  }
141  }
142  }
143 
144  potential_target = current_ship_target;
145  }
146 
147  SetTarget(potential_target);
148 }
149 
150 // +--------------------------------------------------------------------+
151 
152 int
154 {
155  return SteerAI::GROUND;
156 }
157 
158 // +--------------------------------------------------------------------+
159 
160 void
162 {
163  const int exec_period = 1000;
164 
165  if ((int) Game::GameTime() - exec_time > exec_period) {
166  exec_time = (int) Game::GameTime();
167  SelectTarget();
168  }
169 
170  if (ship) {
171  Shield* shield = ship->GetShield();
172 
173  if (shield)
174  shield->SetPowerLevel(100);
175 
177  while (++iter) {
178  WeaponGroup* group = (WeaponGroup*) iter.value();
179 
180  if (group->NumWeapons() > 1 && group->CanTarget(Ship::DROPSHIPS))
182  else
184 
185  group->SetTarget((Ship*) target, 0);
186  }
187 
188  if (carrier_ai)
189  carrier_ai->ExecFrame(secs);
190  }
191 }