Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ShipKiller.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
6  FILE: ShipKiller.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  ShipKiller class implementation
13 */
14 
15 #include "MemDebug.h"
16 #include "ShipKiller.h"
17 #include "Sim.h"
18 #include "Ship.h"
19 #include "ShipDesign.h"
20 #include "System.h"
21 #include "Weapon.h"
22 #include "Shot.h"
23 #include "Explosion.h"
24 #include "Debris.h"
25 #include "HUDSounds.h"
26 
27 #include "Solid.h"
28 #include "Random.h"
29 
30 // +----------------------------------------------------------------------+
31 
33 : ship(s), DEATH_CAM_LINGER(5.0f), time(0.0f), exp_time(0.0f), exp_index(0)
34 {
35 }
36 
38 {
39 }
40 
41 // +----------------------------------------------------------------------+
42 
43 inline int random_index()
44 {
45  return (int) (rand()/3277);
46 }
47 
48 // +----------------------------------------------------------------------+
49 
50 void
52 {
53  if (!ship) return;
54 
55  // shut down all ship systems:
56  ListIter<System> iter = ship->Systems();
57  while (++iter) {
58  iter->PowerOff();
59  iter->SetPowerLevel(0);
60 
61  if (iter->Type() == System::WEAPON) {
62  Weapon* gun = (Weapon*) iter.value();
63 
64  for (int i = 0; i < Weapon::MAX_BARRELS; i++) {
65  Shot* beam = gun->GetBeam(i);
66  if (beam)
67  beam->Destroy();
68  }
69  }
70  }
71 
72  if (ship->GetShieldRep())
73  ship->GetShieldRep()->Hide();
74 
75  Sim* sim = Sim::GetSim();
76  const ShipDesign* design = ship->Design();
77 
78  float time_to_go = design->death_spiral_time;
79  time = DEATH_CAM_LINGER + time_to_go;
80  loc = ship->Location() + ship->Velocity() * (time_to_go-1.0f);
81 
82  if (rand() < 16000)
83  loc += ship->BeamLine() * -3 * ship->Radius();
84  else
85  loc += ship->BeamLine() * 3 * ship->Radius();
86 
87  if (rand() < 8000)
88  loc += ship->LiftLine() * -1 * ship->Radius();
89  else
90  loc += ship->LiftLine() * 2 * ship->Radius();
91 
92  // stop on crash:
93  if (ship->IsGroundUnit() || (ship->IsAirborne() && ship->AltitudeAGL() < ship->Radius()*2)) {
95  loc = ship->Location() + Point(6*ship->Radius(), 7*ship->Radius(), 8*ship->Radius());
96  ship->SetVelocity(Point(0,0,0));
97  }
98  // else, slow tumble:
99  else {
100  Point torque = RandomVector(ship->Mass()/7);
101  ship->ApplyTorque(torque);
102 
103  for (int i = 0; i < 5; i++) {
105  if (design->explosion[exp_index].type > 0 && !design->explosion[exp_index].final)
106  break;
107  }
108 
109  float exp_scale = design->explosion_scale;
110  if (exp_scale <= 0)
111  exp_scale = design->scale;
112 
113  exp_time = design->explosion[exp_index].time;
114 
115  if (design->explosion[exp_index].type > 0) {
116  Point exp_loc = ship->Location() + (design->explosion[exp_index].loc * ship->Cam().Orientation());
117  sim->CreateExplosion(exp_loc,
118  ship->Velocity(),
119  design->explosion[exp_index].type,
120  (float) ship->Radius(),
121  exp_scale,
122  ship->GetRegion(),
123  ship);
124  }
125  }
126 
127  ship->SetControls(0);
128  ship->SetupAgility();
129 }
130 
131 // +----------------------------------------------------------------------+
132 
133 void
134 ShipKiller::ExecFrame(double seconds)
135 {
136  Sim* sim = Sim::GetSim();
137  const ShipDesign* design = ship->Design();
138 
139  time -= (float) seconds;
140  exp_time -= (float) seconds;
141 
142  float exp_scale = design->explosion_scale;
143  if (exp_scale <= 0)
144  exp_scale = design->scale;
145 
146  if (exp_time < 0) {
147  exp_index++;
149  exp_index = 0;
150 
151  exp_time = design->explosion[exp_index].time;
152 
153  if (design->explosion[exp_index].type > 0) {
154  Point exp_loc = ship->Location() + (design->explosion[exp_index].loc * ship->Cam().Orientation());
155  sim->CreateExplosion(exp_loc,
156  ship->Velocity(),
157  design->explosion[exp_index].type,
158  (float) ship->Radius(),
159  exp_scale,
160  ship->GetRegion(),
161  ship);
162  }
163  }
164 
165  if (time < DEATH_CAM_LINGER) {
166  for (int i = 0; i < ShipDesign::MAX_EXPLOSIONS; i++) {
167  if (design->explosion[i].final) {
168  Point exp_loc = ship->Location() + (design->explosion[i].loc * ship->Cam().Orientation());
169  sim->CreateExplosion(exp_loc,
170  ship->Velocity(),
171  design->explosion[i].type,
172  (float) ship->Radius(),
173  exp_scale,
174  ship->GetRegion());
175  }
176  }
177 
178  for (int i = 0; i < ShipDesign::MAX_DEBRIS; i++) {
179  if (design->debris[i].model) {
180  Point debris_loc = ship->Location() + (design->debris[i].loc * ship->Cam().Orientation());
181  Point debris_vel = debris_loc - ship->Location();
182  debris_vel.Normalize();
183 
184  if (design->debris[i].speed > 0)
185  debris_vel *= design->debris[i].speed;
186  else
187  debris_vel *= 200;
188 
189  if (ship->IsGroundUnit()) {
190  debris_vel *= 2;
191 
192  if (debris_vel.y < 0)
193  debris_vel.y *= -1;
194  }
195 
196  for (int n = 0; n < design->debris[i].count; n++) {
197  Debris* debris = sim->CreateDebris(debris_loc,
198  debris_vel + ship->Velocity(),
199  design->debris[i].model,
200  design->debris[i].mass,
201  ship->GetRegion());
202 
203  debris->SetLife(design->debris[i].life);
204  debris->SetDrag(design->debris[i].drag);
205 
206  if (n == 0) {
207  debris->CloneCam(ship->Cam());
208  debris->MoveTo(debris_loc);
209  }
210 
211  for (int fire = 0; fire < 5; fire++) {
212  if (design->debris[i].fire_loc[fire] == Vec3(0,0,0))
213  continue;
214 
215  Point fire_loc = debris->Location() + (design->debris[i].fire_loc[fire] * debris->Cam().Orientation());
216 
217  if (design->debris[i].fire_type > 0) {
218  sim->CreateExplosion(fire_loc,
219  ship->Velocity(),
220  design->debris[i].fire_type,
221  exp_scale,
222  exp_scale,
223  ship->GetRegion(),
224  debris);
225  }
226  else {
227  sim->CreateExplosion(fire_loc,
228  ship->Velocity(),
230  exp_scale,
231  exp_scale,
232  ship->GetRegion(),
233  debris);
234 
235  sim->CreateExplosion(fire_loc,
236  ship->Velocity(),
238  exp_scale * 0.25f,
239  exp_scale * 0.25f,
240  ship->GetRegion(),
241  debris);
242  }
243  }
244 
245  if (n+1 < design->debris[i].count) {
246  debris_vel = RandomVector(1);
247 
248  if (design->debris[i].speed > 0)
249  debris_vel *= design->debris[i].speed * Random(0.8, 1.2);
250  else
251  debris_vel *= 300 + rand()/50;
252  }
253  }
254  }
255  }
256 
257  if (ship == sim->GetPlayerShip())
259 
260  sim->CreateSplashDamage(ship);
261  ship->Destroy(); // CAREFUL!!! This will also delete this object!
262  }
263 }