Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Contact.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: Contact.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Integrated (Passive and Active) Sensor Package class implementation
13 */
14 
15 #include "MemDebug.h"
16 #include "Contact.h"
17 #include "Drone.h"
18 #include "Sensor.h"
19 #include "Ship.h"
20 #include "Sim.h"
21 #include "WeaponDesign.h"
22 
23 #include "Game.h"
24 
25 // +----------------------------------------------------------------------+
26 
27 const int DEFAULT_TRACK_UPDATE = 500; // milliseconds
28 const int DEFAULT_TRACK_LENGTH = 20; // 10 seconds
29 const double DEFAULT_TRACK_AGE = 10; // 10 seconds
30 const double SENSOR_THRESHOLD = 0.25;
31 
32 // +----------------------------------------------------------------------+
33 
35 : ship(0), shot(0), d_pas(0.0f), d_act(0.0f),
36 track(0), ntrack(0), time(0), track_time(0), probe(false)
37 {
38  acquire_time = Game::GameTime();
39 }
40 
41 Contact::Contact(Ship* s, float p, float a)
42 : ship(s), shot(0), d_pas(p), d_act(a),
43 track(0), ntrack(0), time(0), track_time(0), probe(false)
44 {
45  acquire_time = Game::GameTime();
46  Observe(ship);
47 }
48 
49 Contact::Contact(Shot* s, float p, float a)
50 : ship(0), shot(s), d_pas(p), d_act(a),
51 track(0), ntrack(0), time(0), track_time(0), probe(false)
52 {
53  acquire_time = Game::GameTime();
54  Observe(shot);
55 }
56 
57 // +----------------------------------------------------------------------+
58 
60 {
61  delete [] track;
62 }
63 
64 // +----------------------------------------------------------------------+
65 
66 int
68 {
69  if (ship)
70  return ship == c.ship;
71 
72  else if (shot)
73  return shot == c.shot;
74 
75  return 0;
76 }
77 
78 // +----------------------------------------------------------------------+
79 
80 bool
82 {
83  if (obj == ship || obj == shot) {
84  ship = 0;
85  shot = 0;
86  d_act = 0;
87  d_pas = 0;
88 
89  ClearTrack();
90  }
91 
92  return SimObserver::Update(obj);
93 }
94 
95 const char*
97 {
98  static char name[128];
99 
100  if (ship)
101  sprintf_s(name, "Contact Ship='%s'", ship->Name());
102  else if (shot)
103  sprintf_s(name, "Contact Shot='%s' %s", shot->Name(), shot->DesignName());
104  else
105  sprintf_s(name, "Contact (unknown)");
106 
107  return name;
108 }
109 
110 // +----------------------------------------------------------------------+
111 
112 double
114 {
115  double age = 0;
116 
117  if (!ship && !shot)
118  return age;
119 
120  double seconds = (Game::GameTime() - time) / 1000.0;
121 
122  age = 1.0 - seconds/DEFAULT_TRACK_AGE;
123 
124  if (age < 0)
125  age = 0;
126 
127  return age;
128 }
129 
130 int
131 Contact::GetIFF(const Ship* observer) const
132 {
133  int i = 0;
134 
135  if (ship) {
136  i = ship->GetIFF();
137 
138  // if the contact is on our side or has locked us up,
139  // we know whose side he's on.
140 
141  // Otherwise:
142  if (i != observer->GetIFF() && !Threat(observer)) {
143  if (d_pas < 2*SENSOR_THRESHOLD && d_act < SENSOR_THRESHOLD && !Visible(observer))
144  i = -1000; // indeterminate iff reading
145  }
146  }
147 
148  else if (shot && shot->Owner()) {
149  i = shot->Owner()->GetIFF();
150  }
151 
152  return i;
153 }
154 
155 bool
157 {
158  return d_act >= SENSOR_THRESHOLD;
159 }
160 
161 bool
163 {
164  return d_pas >= SENSOR_THRESHOLD;
165 }
166 
167 // +----------------------------------------------------------------------+
168 
169 void
170 Contact::GetBearing(const Ship* observer, double& az, double& el, double& rng) const
171 {
172  // translate:
173  Point targ_pt = loc - observer->Location();
174 
175  // rotate:
176  const Camera* cam = &observer->Cam();
177  double tx = targ_pt * cam->vrt();
178  double ty = targ_pt * cam->vup();
179  double tz = targ_pt * cam->vpn();
180 
181  // convert to spherical coords:
182  rng = targ_pt.length();
183  az = asin(fabs(tx) / rng);
184  el = asin(fabs(ty) / rng);
185 
186  if (tx < 0) az = -az;
187  if (ty < 0) el = -el;
188 
189  // correct az/el for back hemisphere:
190  if (tz < 0) {
191  if (az < 0) az = -PI - az;
192  else az = PI - az;
193  }
194 }
195 
196 double
197 Contact::Range(const Ship* observer, double limit) const
198 {
199  double r = Point(loc - observer->Location()).length();
200 
201  // if passive only, return approximate range:
202  if (!ActLock()) {
203  const int chunk = 25000;
204 
205  if (!PasLock()) {
206  r = (int) limit;
207  }
208 
209  else if (r <= chunk) {
210  r = chunk;
211  }
212 
213  else {
214  int r1 = (int) (r + chunk/2) / chunk;
215  r = r1 * chunk;
216  }
217  }
218 
219  return r;
220 }
221 
222 // +----------------------------------------------------------------------+
223 
224 bool
225 Contact::InFront(const Ship* observer) const
226 {
227  // translate:
228  Point targ_pt = loc - observer->Location();
229 
230  // rotate:
231  const Camera* cam = &observer->Cam();
232  double tz = targ_pt * cam->vpn();
233 
234  if (tz > 1.0)
235  return true;
236 
237  return false;
238 }
239 
240 bool
241 Contact::Threat(const Ship* observer) const
242 {
243  bool threat = false;
244 
245  if (observer && observer->Life() != 0) {
246  if (ship && ship->Life() != 0) {
247  threat = (ship->GetIFF() &&
248  ship->GetIFF() != observer->GetIFF() &&
249  ship->GetEMCON() > 2 &&
250  ship->IsTracking((Ship*) observer) &&
251  ship->Weapons().size() > 0);
252 
253  if (threat && observer->GetIFF() == 0)
254  threat = ship->GetIFF() > 1;
255  }
256 
257  else if (shot) {
258  threat = shot->IsTracking((Ship*) observer);
259 
260  if (!threat && shot->Design()->probe && shot->GetIFF() != observer->GetIFF()) {
261  Point probe_pt = shot->Location() - observer->Location();
262  double prng = probe_pt.length();
263 
264  threat = (prng < shot->Design()->lethal_radius);
265  }
266  }
267  }
268 
269  return threat;
270 }
271 
272 bool
273 Contact::Visible(const Ship* observer) const
274 {
275  // translate:
276  Point targ_pt = loc - observer->Location();
277  double radius = 0;
278 
279  if (ship)
280  radius = ship->Radius();
281 
282  else if (shot)
283  radius = shot->Radius();
284 
285  // rotate:
286  const Camera* cam = &observer->Cam();
287  double rng = targ_pt.length();
288 
289  return radius/rng > 0.002;
290 }
291 
292 // +----------------------------------------------------------------------+
293 
294 void
296 {
297  if (Game::Paused()) return;
298 
299  float step_down = (float) (Game::FrameTime() / 10);
300 
301  if (d_pas > 0)
302  d_pas -= step_down;
303 
304  if (d_act > 0)
305  d_act -= step_down;
306 }
307 
308 void
310 {
311  if (c->GetShip() == ship && c->GetShot() == shot) {
312  if (c->d_pas > d_pas)
313  d_pas = c->d_pas;
314 
315  if (c->d_act > d_act)
316  d_act = c->d_act;
317  }
318 }
319 
320 void
322 {
323  delete [] track;
324  track = 0;
325  ntrack = 0;
326 }
327 
328 void
330 {
331  time = Game::GameTime();
332 
333  if (shot || (ship && ship->IsGroundUnit()))
334  return;
335 
336  if (!track) {
337  track = new(__FILE__,__LINE__) Point[DEFAULT_TRACK_LENGTH];
338  track[0] = loc;
339  ntrack = 1;
340  track_time = time;
341  }
342 
343  else if (time - track_time > DEFAULT_TRACK_UPDATE) {
344  if (loc != track[0]) {
345  for (int i = DEFAULT_TRACK_LENGTH-2; i >= 0; i--)
346  track[i+1] = track[i];
347 
348  track[0] = loc;
349  if (ntrack < DEFAULT_TRACK_LENGTH) ntrack++;
350  }
351 
352  track_time = time;
353  }
354 }
355 
356 // +----------------------------------------------------------------------+
357 
358 Point
360 {
361  if (track && i < ntrack)
362  return track[i];
363 
364  return Point();
365 }