Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Debris.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: Debris.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Debris Sprite animation class
13 */
14 
15 #include "MemDebug.h"
16 #include "Debris.h"
17 #include "Shot.h"
18 #include "Explosion.h"
19 #include "Sim.h"
20 #include "StarSystem.h"
21 #include "Terrain.h"
22 
23 #include "Solid.h"
24 #include "Bitmap.h"
25 #include "DataLoader.h"
26 #include "Game.h"
27 #include "Random.h"
28 
29 // +--------------------------------------------------------------------+
30 
31 Debris::Debris(Model* model, const Vec3& pos, const Vec3& vel, double m)
32 : SimObject("Debris", SimObject::SIM_DEBRIS)
33 {
34  MoveTo(pos);
35 
36  velocity = vel;
37  mass = (float) m;
38  integrity = mass * 10.0f;
39  life = 300;
40 
41  Solid* solid = new(__FILE__,__LINE__) Solid;
42 
43  if (solid) {
44  solid->UseModel(model);
45  solid->MoveTo(pos);
46 
47  rep = solid;
48 
49  radius = solid->Radius();
50  }
51 
52  Point torque = RandomVector(Mass()/2);
53 
54  if (Mass() < 10)
55  torque *= (rand() / 3200);
56  else if (Mass() > 10e3)
57  torque *= 0.25;
58  else if (Mass() > 10e6)
59  torque *= 0.005;
60 
61  ApplyTorque(torque);
62 }
63 
64 // +--------------------------------------------------------------------+
65 
66 int
67 Debris::HitBy(Shot* shot, Point& impact)
68 {
69  if (!shot->IsArmed()) return 0;
70 
71  const int HIT_NOTHING = 0;
72  const int HIT_HULL = 1;
73 
74  Point hull_impact;
75  int hit_type = HIT_NOTHING;
76  bool hit_hull = true;
77  Point shot_loc = shot->Location();
78  Point delta = shot_loc - Location();
79  double dlen = delta.length();
80  double dscale = 1;
81  float scale = 1.0f;
82  Sim* sim = Sim::GetSim();
83 
84  // MISSILE PROCESSING ------------------------------------------------
85 
86  if (shot->IsMissile()) {
87  if (dlen < Radius()) {
88  hull_impact = impact = shot_loc;
89  sim->CreateExplosion(impact, Velocity(), Explosion::HULL_FLASH, 0.3f * scale, scale, region, this);
90  sim->CreateExplosion(impact, Point(), Explosion::SHOT_BLAST, 2.0f, scale, region);
91  hit_type = HIT_HULL;
92  }
93  }
94 
95  // ENERGY WEP PROCESSING ---------------------------------------------
96 
97  else {
98 
99  Solid* solid = (Solid*) rep;
100 
101  Point shot_loc = shot->Location();
102  Point shot_vpn = shot_loc - shot->Origin();
103  double shot_len = shot_vpn.Normalize();
104  if (shot_len == 0) shot_len = 1000;
105 
106  // impact:
107  if (solid) {
108  if (solid->CheckRayIntersection(shot->Origin(), shot_vpn, shot_len, impact)) {
109  // trim beam shots to impact point:
110  if (shot->IsBeam())
111  shot->SetBeamPoints(shot->Origin(), impact);
112 
113  hull_impact = impact;
114 
115  if (shot->IsBeam())
116  sim->CreateExplosion(impact, Velocity(), Explosion::BEAM_FLASH, 0.30f * scale, scale, region, this);
117  else
118  sim->CreateExplosion(impact, Velocity(), Explosion::HULL_FLASH, 0.30f * scale, scale, region, this);
119 
120  Point burst_vel = hull_impact - Location();
121  burst_vel.Normalize();
122  burst_vel *= Radius() * 0.5;
123  burst_vel += Velocity();
124 
125  sim->CreateExplosion(hull_impact, burst_vel, Explosion::HULL_BURST, 0.50f * scale, scale, region, this);
126 
127  hit_type = HIT_HULL;
128  hit_hull = true;
129  }
130  }
131 
132  else {
133  if (dlen < Radius()) {
134  hull_impact = impact = shot_loc;
135 
136  if (shot->IsBeam())
137  sim->CreateExplosion(impact, Velocity(), Explosion::BEAM_FLASH, 0.30f * scale, scale, region, this);
138  else
139  sim->CreateExplosion(impact, Velocity(), Explosion::HULL_FLASH, 0.30f * scale, scale, region, this);
140 
141  hit_type = HIT_HULL;
142  }
143  }
144  }
145 
146  // DAMAGE RESOLUTION -------------------------------------------------
147 
148  if (hit_type != HIT_NOTHING) {
149  double effective_damage = shot->Damage() * dscale;
150 
151  if (shot->IsBeam()) {
152  effective_damage *= Game::FrameTime();
153  }
154  else {
155  ApplyTorque(shot->Velocity() * (float) effective_damage * 1e-6f);
156  }
157 
158  if (effective_damage > 0)
159  Physical::InflictDamage(effective_damage);
160  }
161 
162  return hit_type;
163 }
164 
165 // +--------------------------------------------------------------------+
166 
167 void
168 Debris::ExecFrame(double seconds)
169 {
170  if (GetRegion()->Type() == SimRegion::AIR_SPACE) {
171  if (AltitudeAGL() < Radius()) {
172  velocity = Point();
174 
175  Terrain* terrain = region->GetTerrain();
176 
177  if (terrain) {
178  Point loc = Location();
179  MoveTo(Point(loc.x, terrain->Height(loc.x, loc.z), loc.z));
180  }
181  }
182  else {
183  if (mass > 100) {
184  Orbital* primary = GetRegion()->GetOrbitalRegion()->Primary();
185 
186  const double GRAV = 6.673e-11;
187  double m0 = primary->Mass();
188  double r = primary->Radius();
189 
190  SetDrag(0.001);
191  SetGravity(6 * GRAV * m0 / (r*r)); // accentuate gravity
192  SetBaseDensity(1.0f);
193  }
194 
195  AeroFrame(seconds);
196  }
197  }
198  else {
199  Physical::ExecFrame(seconds);
200  }
201 }
202 
203 // +--------------------------------------------------------------------+
204 
205 double
207 {
208  Point loc = Location();
209  double altitude_agl = loc.y;
210 
211  Terrain* terrain = region->GetTerrain();
212 
213  if (terrain)
214  altitude_agl -= terrain->Height(loc.x, loc.z);
215 
216  if (!_finite(altitude_agl))
217  altitude_agl = 0;
218 
219  return altitude_agl;
220 }