Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
System.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: System.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Generic Ship Subsystem class
13 */
14 
15 #include "MemDebug.h"
16 #include "System.h"
17 #include "SystemDesign.h"
18 #include "Component.h"
19 #include "NetUtil.h"
20 
21 #include "Game.h"
22 
23 // +----------------------------------------------------------------------+
24 
25 System::System(System::CATEGORY t, int s, const char* n, int maxv,
26 double e, double c, double r)
27 : type(t), id(0), ship(0), subtype(s), status(NOMINAL), availability(1.0f),
28 safety(1.0f), stability(1.0f), crit_level(0.5f), net_avail(-1.0f),
29 mount_rel(0.0f, 0.0f, 0.0f), radius(0.0f), safety_overload(0.0f),
30 hull_factor(0.5f), energy((float) e), capacity((float) c), sink_rate((float) r),
31 power_level(1.0f), power_flags(0), source_index(0), power_on(true),
32 explosion_type(0), name(n), abrv(name), design(0), emcon(3)
33 {
34  if (maxv < 100)
35  max_value = maxv;
36  else
37  max_value = (int) (maxv/100.0);
38 
39  emcon_power[0] = 100;
40  emcon_power[1] = 100;
41  emcon_power[2] = 100;
42 }
43 
44 // +----------------------------------------------------------------------+
45 
47 : type(s.type), id(s.id), ship(0), subtype(s.subtype), status(s.status),
48 availability(s.availability), safety(s.safety), stability(s.stability),
49 crit_level(s.crit_level), net_avail(-1.0f),
50 mount_rel(s.mount_rel), radius(s.radius), safety_overload(0.0f),
51 hull_factor(s.hull_factor), energy(s.energy), capacity(s.capacity),
52 sink_rate(s.sink_rate), power_level(s.power_level), power_flags(s.power_flags),
53 source_index(s.source_index), power_on(s.power_on), max_value(s.max_value),
54 explosion_type(s.explosion_type), name(s.name), abrv(s.abrv), design(s.design),
55 emcon(s.emcon)
56 {
57  if (design) {
58  // cast-away const
60  while (++c) {
61  Component* comp = new(__FILE__,__LINE__) Component(*(c.value()));
62  comp->SetSystem(this);
63  components.append(comp);
64  }
65  }
66 
67  emcon_power[0] = s.emcon_power[0];
68  emcon_power[1] = s.emcon_power[1];
69  emcon_power[2] = s.emcon_power[2];
70 }
71 
72 // +--------------------------------------------------------------------+
73 
75 {
77 }
78 
79 // +--------------------------------------------------------------------+
80 
81 void
83 {
84  if (design) {
85  design = 0;
87  }
88 
89  if (d) {
90  design = d;
91 
93  while (++cd) {
94  Component* comp = new(__FILE__,__LINE__) Component(cd.value(), this);
95  components.append(comp);
96  }
97  }
98 }
99 
100 // +--------------------------------------------------------------------+
101 
102 void
104 {
105  if (level > 100)
106  level = 100;
107  else if (level < 0)
108  level = 0;
109 
110  level /= 100;
111 
112  if (power_level != level) {
113  // if the system is on emergency override power,
114  // do not let the EMCON system use this method
115  // to drop it back to normal power:
116  if (power_level > 1 && level == 1)
117  return;
118 
119  power_level = (float) level;
120 
122  }
123 }
124 
125 void
127 {
128  bool changed = false;
129 
130  if (over && power_level != 1.2f) {
131  power_level = 1.2f;
132  changed = true;
133  }
134 
135  else if (!over && power_level > 1) {
136  power_level = 1.0f;
137  changed = true;
138  }
139 
140  if (changed)
142 }
143 
144 void
145 System::SetEMCONPower(int index, int power_level)
146 {
147  if (index >= 1 && index <= 3) {
148  emcon_power[index-1] = (BYTE) power_level;
149  }
150 }
151 
152 int
154 {
155  if (index >= 1 && index <= 3) {
156  return emcon_power[index-1];
157  }
158 
159  return 100;
160 }
161 
162 void
163 System::DoEMCON(int index)
164 {
165  int e = GetEMCONPower(index);
166 
167  if (power_level * 100 > e || emcon != index) {
168  if (e == 0) {
169  PowerOff();
170  }
171  else {
172  if (emcon != index)
173  PowerOn();
174 
175  SetPowerLevel(e);
176  }
177  }
178 
179  emcon = index;
180 }
181 
182 // +--------------------------------------------------------------------+
183 
184 void
185 System::ExecFrame(double seconds)
186 {
187  if (seconds < 0.01)
188  seconds = 0.01;
189 
190  STATUS s = DESTROYED;
191 
192  if (availability > 0.99)
193  s = NOMINAL;
194  else if (availability > crit_level)
195  s = DEGRADED;
196  else
197  s = CRITICAL;
198 
199  bool repair = false;
200 
201  if (components.size() > 0) {
203  while (++comp) {
204  if (comp->Status() > Component::NOMINAL) {
205  repair = true;
206  break;
207  }
208  }
209  }
210 
211  if (repair) {
212  Repair();
213  }
214 
215  else {
216  if (status != s) {
217  status = s;
219  }
220 
221  // collateral damage due to unsafe operation:
222  if (power_on && power_level > safety) {
223  safety_overload += (float) seconds;
224 
225  // inflict some damage now:
226  if (safety_overload > 60) {
227  safety_overload -= (float) (rand() / (1000 * (power_level-safety)));
228  ApplyDamage(15);
229 
231  }
232  }
233 
234  else if (safety_overload > 0) {
235  safety_overload -= (float) seconds;
236  }
237  }
238 }
239 
240 void
242 {
243  if (status != MAINT) {
244  status = MAINT;
245  safety_overload = 0.0f;
246 
248  }
249 }
250 
251 // +--------------------------------------------------------------------+
252 
253 void
254 System::ExecMaintFrame(double seconds)
255 {
256  if (components.size() > 0) {
258  while (++comp) {
259  if (comp->Status() > Component::NOMINAL) {
260  comp->ExecMaintFrame(seconds);
261  }
262  }
263  }
264 }
265 
266 // +--------------------------------------------------------------------+
267 
268 void
269 System::ApplyDamage(double damage)
270 {
271  if (!power_on)
272  damage /= 10;
273 
274  if (components.size() > 0) {
275  int index = rand() % components.size();
276 
277  if (damage > 50) {
278  damage/=2;
279  components[index]->ApplyDamage(damage);
280 
281  index = rand() % components.size();
282  }
283 
284  components[index]->ApplyDamage(damage);
285 
286  if (safety < 0.5)
287  SetPowerLevel(50);
288 
289  else if (safety < 1.0)
290  SetPowerLevel(safety * 100);
291  }
292  else {
293  availability -= (float) (damage/100.0f);
294  if (availability < 0.01) availability = 0.0f;
295  }
296 }
297 
298 void
300 {
301  if (components.size() > 0) {
302  availability = 1.0f;
303  safety = 1.0f;
304  stability = 1.0f;
305 
307  while (++comp) {
308  if (comp->DamageEfficiency())
309  availability *= comp->Availability() / 100.0f;
310 
311  if (comp->DamageSafety())
312  safety *= comp->Availability() / 100.0f;
313 
314  if (comp->DamageStability())
315  stability *= comp->Availability() / 100.0f;
316 
317  if (comp->IsJerried()) {
318  safety *= 0.95f;
319  stability *= 0.95f;
320  }
321  }
322 
323  if (net_avail >= 0 && availability < net_avail)
325  }
326 }
327 
328 // +--------------------------------------------------------------------+
329 
330 void
331 System::Mount(Point loc, float rad, float hull)
332 {
333  mount_rel = loc;
334  radius = rad;
335  hull_factor = hull;
336 }
337 
338 void
339 System::Mount(const System& system)
340 {
341  mount_rel = system.mount_rel;
342  radius = system.radius;
343  hull_factor = system.hull_factor;
344 }
345 
346 // +--------------------------------------------------------------------+
347 
348 void
350 {
351  const Matrix& orientation = rep->Cam().Orientation();
352  Point loc = rep->Location();
353 
354  mount_loc = (mount_rel * orientation) + loc;
355 }
356 
357 // +----------------------------------------------------------------------+
358 
359 double
360 System::GetRequest(double seconds) const
361 {
362  if (!power_on || capacity == energy)
363  return 0;
364 
365  else
366  return power_level * sink_rate * seconds;
367 }
368 
369 // +----------------------------------------------------------------------+
370 
371 void
372 System::Distribute(double delivered_energy, double seconds)
373 {
374  if (UsesWatts()) {
375  if (seconds < 0.01)
376  seconds = 0.01;
377 
378  // convert Joules to Watts:
379  energy = (float) (delivered_energy/seconds);
380  }
381 
382  else if (!Game::Paused()) {
383  energy += (float) delivered_energy;
384 
385  if (energy > capacity)
386  energy = capacity;
387 
388  else if (energy < 0)
389  energy = 0.0f;
390  }
391 }
392 
393 // +----------------------------------------------------------------------+
394 
395 void
396 System::DrainPower(double to_level)
397 {
398  energy = 0.0f;
399 }