Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Shield.cpp
Go to the documentation of this file.
1 /* Project Starshatter 5.0
2  Destroyer Studios LLC
3  Copyright © 1997-2007. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: Shield.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Weapon class
13 */
14 
15 #include "MemDebug.h"
16 #include "Shield.h"
17 #include "Shot.h"
18 #include "WeaponDesign.h"
19 
20 #include "Game.h"
21 
22 // +----------------------------------------------------------------------+
23 
24 static char* shield_name[] = {
25  "sys.shield.none",
26  "sys.shield.deflector",
27  "sys.shield.grav",
28  "sys.shield.hyper"
29 };
30 
31 static int shield_value[] = {
32  0, 2, 2, 3
33 };
34 
35 // +----------------------------------------------------------------------+
36 
37 Shield::Shield(SUBTYPE shield_type)
38 : System(SHIELD, shield_type, "shield", shield_value[shield_type], 100, 0),
39 shield_cutoff(0.0f), shield_capacitor(false), shield_bubble(false),
40 deflection_cost(1.0f), shield_curve(0.05f)
41 {
42  name = Game::GetText(shield_name[shield_type]);
43  abrv = Game::GetText("sys.shield.abrv");
44 
46  energy = 0.0f;
47  power_level = 0.0f;
48  shield_level = 0.0f;
49 
50  switch (shield_type) {
51  default:
52  case DEFLECTOR:
53  capacity = sink_rate = 2.0e3f;
54  shield_factor = 0.05f;
55  break;
56 
57  case GRAV_SHIELD:
58  capacity = sink_rate = 7.0e3f;
59  shield_factor = 0.01f;
60  break;
61 
62  case HYPER_SHIELD:
63  capacity = sink_rate = 10.0e3f;
64  shield_factor = 0.003f;
65  break;
66  }
67 
68  emcon_power[0] = 0;
69  emcon_power[1] = 0;
70  emcon_power[2] = 100;
71 }
72 
73 // +----------------------------------------------------------------------+
74 
76 : System(s), shield_factor(s.shield_factor), requested_power_level(0.0f),
77 shield_cutoff(s.shield_cutoff), shield_capacitor(s.shield_capacitor),
78 shield_bubble(s.shield_bubble), deflection_cost(s.deflection_cost),
79 shield_curve(s.shield_curve)
80 {
82  energy = 0.0f;
83  power_level = 0.0f;
84  shield_level = 0.0f;
85 
86  Mount(s);
87 }
88 
89 // +--------------------------------------------------------------------+
90 
92 { }
93 
94 void
96 {
97  shield_capacitor = c;
98 
99  if (shield_capacitor) {
101  shield_curve = 0.05f;
102  }
103  else {
105  shield_curve = 0.25f;
106  }
107 }
108 
109 // +--------------------------------------------------------------------+
110 
111 void
112 Shield::ExecFrame(double seconds)
113 {
114  System::ExecFrame(seconds);
115 
117  power_level += (float) (seconds * 0.10); // ten seconds to charge up
118 
121  }
122  else if (power_level > requested_power_level) {
123  power_level -= (float) (seconds * 0.20); // five seconds to power down
124 
127  }
128 
129  if (power_level < 0.01 && !shield_capacitor) {
130  shield_level = 0.0f;
131  energy = 0.0f;
132  }
133 }
134 
135 // +----------------------------------------------------------------------+
136 
137 void
138 Shield::Distribute(double delivered_energy, double seconds)
139 {
140  System::Distribute(delivered_energy, seconds);
141 
142  if (shield_capacitor) {
143  if (shield_cutoff > 0 && shield_cutoff < 0.999) {
144  float cutoff = shield_cutoff * capacity;
145 
146  if (energy > cutoff)
147  shield_level = (energy-cutoff)/(capacity-cutoff);
148  else
149  shield_level = 0.0f;
150  }
151 
152  else {
154  }
155  }
156  else {
158  energy = 0.0f;
159  }
160 
161  if (shield_level < 0)
162  shield_level = 0;
163 }
164 
165 // +--------------------------------------------------------------------+
166 
167 double
168 Shield::DeflectDamage(Shot* shot, double damage)
169 {
170  double filter = 1;
171  double penetration = 5;
172  double leak = 0;
173 
174  if (shot)
175  penetration = shot->Design()->penetration;
176 
177  filter = 1 - shield_factor * penetration;
178 
179  if (filter < 0)
180  filter = 0;
181 
182  else if (filter > 1)
183  filter = 1;
184 
185  if (shield_capacitor) {
186  if (shield_cutoff > 0 && shield_level < 1e-6) {
187  leak = damage;
188  energy -= (float) (damage * deflection_cost);
189  }
190 
191  else {
192  leak = damage * (1 - pow(shield_level, shield_curve) * filter * availability);
193 
194  double deflected = damage - leak;
195  energy -= (float) deflected * deflection_cost;
196  }
197 
198  }
199  else {
200  leak = damage * (1 - pow(shield_level, shield_curve) * filter * availability);
201  }
202 
203  return leak;
204 }
205 
206 // +--------------------------------------------------------------------+
207 
208 void
210 {
211  if (level > 100)
212  level = 100;
213  else if (level < 0)
214  level = 0;
215 
216  level /= 100;
217 
218  if (requested_power_level != level) {
219  // if the system is on emergency override power,
220  // do not let the EMCON system use this method
221  // to drop it back to normal power:
222  if (power_level > 1 && level == 1) {
224  return;
225  }
226 
227  requested_power_level = (float) level;
228  }
229 }
230 
231 void
233 {
234  if (level > 100) level = 100;
235  else if (level < 0) level = 0;
236 
237  requested_power_level = (float) (level/100.0);
239 }
240 
241 void
242 Shield::DoEMCON(int index)
243 {
244  int e = GetEMCONPower(index);
245 
246  if (power_level * 100 > e || emcon != index) {
247  if (e == 0) {
248  PowerOff();
249  }
250  else if (emcon != index) {
251  PowerOn();
252 
253  if (power_level * 100 > e)
254  SetPowerLevel(e);
255  }
256  }
257 
258  emcon = index;
259 }