1 /* Weapon.h
2 Copyright (c) 2015 by Michael Zahniser
3
4 Endless Sky is free software: you can redistribute it and/or modify it under the
5 terms of the GNU General Public License as published by the Free Software
6 Foundation, either version 3 of the License, or (at your option) any later version.
7
8 Endless Sky is distributed in the hope that it will be useful, but WITHOUT ANY
9 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10 PARTICULAR PURPOSE. See the GNU General Public License for more details.
11 */
12
13 #ifndef WEAPON_H_
14 #define WEAPON_H_
15
16 #include "Body.h"
17 #include "Point.h"
18
19 #include <map>
20 #include <utility>
21
22 class DataNode;
23 class Effect;
24 class Outfit;
25 class Sound;
26 class Sprite;
27
28
29
30 // Class representing all the characteristics of a weapon, including sprites and
31 // effects, sounds, icons, ammo, submunitions, and other attributes. Storing
32 // these parameters in a separate class keeps each Projectile from needing a
33 // copy of them, and storing them as class variables instead of in a map of
34 // string to double significantly reduces access time.
35 class Weapon {
36 public:
37 // Load from a "weapon" node, either in an outfit, a ship (explosion), or a hazard.
38 void LoadWeapon(const DataNode &node);
39 bool IsWeapon() const;
40
41 // Get assets used by this weapon.
42 const Body &WeaponSprite() const;
43 const Body &HardpointSprite() const;
44 const Sound *WeaponSound() const;
45 const Outfit *Ammo() const;
46 const Sprite *Icon() const;
47
48 // Effects to be created at the start or end of the weapon's lifetime.
49 const std::map<const Effect *, int> &FireEffects() const;
50 const std::map<const Effect *, int> &LiveEffects() const;
51 const std::map<const Effect *, int> &HitEffects() const;
52 const std::map<const Effect *, int> &DieEffects() const;
53 const std::map<const Outfit *, int> &Submunitions() const;
54
55 // Accessor functions for various attributes.
56 int Lifetime() const;
57 int RandomLifetime() const;
58 double Reload() const;
59 double BurstReload() const;
60 int BurstCount() const;
61 int Homing() const;
62
63 int AmmoUsage() const;
64
65 int MissileStrength() const;
66 int AntiMissile() const;
67 // Weapons of the same type will alternate firing (streaming) rather than
68 // firing all at once (clustering) if the weapon is not an anti-missile and
69 // is not vulnerable to anti-missile, or has the "stream" attribute.
70 bool IsStreamed() const;
71 bool IsParallel() const;
72
73 double Velocity() const;
74 double RandomVelocity() const;
75 double WeightedVelocity() const;
76 double Acceleration() const;
77 double Drag() const;
78 const Point &HardpointOffset() const;
79
80 double Turn() const;
81 double Inaccuracy() const;
82 double TurretTurn() const;
83
84 double Tracking() const;
85 double OpticalTracking() const;
86 double InfraredTracking() const;
87 double RadarTracking() const;
88
89 // Normal damage sustained on firing ship when weapon fired.
90 double FiringEnergy() const;
91 double FiringForce() const;
92 double FiringFuel() const;
93 double FiringHeat() const;
94 double FiringHull() const;
95 double FiringShields() const;
96 double FiringIon() const;
97 double FiringSlowing() const;
98 double FiringDisruption() const;
99
100 // Relative damage sustained on firing ship when weapon fired.
101 double RelativeFiringEnergy() const;
102 double RelativeFiringHeat() const;
103 double RelativeFiringFuel() const;
104 double RelativeFiringHull() const;
105 double RelativeFiringShields() const;
106
107 double SplitRange() const;
108 double TriggerRadius() const;
109 double BlastRadius() const;
110 double HitForce() const;
111
112 // A "safe" weapon hits only hostile ships (even if it has a blast radius).
113 // A "phasing" weapon hits only its intended target; it passes through
114 // everything else, including asteroids.
115 bool IsSafe() const;
116 bool IsPhasing() const;
117 // Blast radius weapons will scale damage and hit force based on distance,
118 // unless the "no damage scaling" keyphrase is used in the weapon definition.
119 bool IsDamageScaled() const;
120 // Gravitational weapons deal the same amount of hit force to a ship regardless
121 // of its mass.
122 bool IsGravitational() const;
123
124 // These values include all submunitions:
125 // Normal damage types:
126 double ShieldDamage() const;
127 double HullDamage() const;
128 double FuelDamage() const;
129 double HeatDamage() const;
130 double EnergyDamage() const;
131 // Status effects:
132 double IonDamage() const;
133 double DisruptionDamage() const;
134 double SlowingDamage() const;
135 // Relative damage types:
136 double RelativeShieldDamage() const;
137 double RelativeHullDamage() const;
138 double RelativeFuelDamage() const;
139 double RelativeHeatDamage() const;
140 double RelativeEnergyDamage() const;
141 // Check if this weapon does damage. If not, attacking a ship with this
142 // weapon is not a provocation (even if you push or pull it).
143 bool DoesDamage() const;
144
145 double Piercing() const;
146
147 double TotalLifetime() const;
148 double Range() const;
149
150 // Check if this weapon has a damage dropoff range.
151 bool HasDamageDropoff() const;
152 // Calculate the percent damage that this weapon deals given the distance
153 // that the projectile traveled if it has a damage dropoff range.
154 double DamageDropoff(double distance) const;
155
156
157 protected:
158 // Legacy support: allow turret outfits with no turn rate to specify a
159 // default turnrate.
160 void SetTurretTurn(double rate);
161
162 // A pair representing the outfit that is consumed as ammo and the number
163 // of that outfit consumed upon fire.
164 std::pair<const Outfit*, int> ammo;
165
166
167 private:
168 double TotalDamage(int index) const;
169
170
171 private:
172 // Sprites and sounds.
173 Body sprite;
174 Body hardpointSprite;
175 const Sound *sound = nullptr;
176 const Sprite *icon = nullptr;
177
178 // Fire, die and hit effects.
179 std::map<const Effect *, int> fireEffects;
180 std::map<const Effect *, int> liveEffects;
181 std::map<const Effect *, int> hitEffects;
182 std::map<const Effect *, int> dieEffects;
183 std::map<const Outfit *, int> submunitions;
184
185 // This stores whether or not the weapon has been loaded.
186 bool isWeapon = false;
187 bool isStreamed = false;
188 bool isSafe = false;
189 bool isPhasing = false;
190 bool isDamageScaled = true;
191 bool isGravitational = false;
192 // Guns and missiles are by default aimed a converged point at the
193 // maximum weapons range in front of the ship. When either the installed
194 // weapon or the gun-port (or both) have the isParallel attribute set
195 // to true, then this convergence will not be used and the weapon will
196 // be aimed directly in the gunport angle/direction.
197 bool isParallel = false;
198
199 // Attributes.
200 int lifetime = 0;
201 int randomLifetime = 0;
202 double reload = 1.;
203 double burstReload = 1.;
204 int burstCount = 1;
205 int homing = 0;
206
207 int missileStrength = 0;
208 int antiMissile = 0;
209
210 double velocity = 0.;
211 double randomVelocity = 0.;
212 double acceleration = 0.;
213 double drag = 0.;
214 Point hardpointOffset = {0., 0.};
215
216 double turn = 0.;
217 double inaccuracy = 0.;
218 double turretTurn = 0.;
219
220 double tracking = 0.;
221 double opticalTracking = 0.;
222 double infraredTracking = 0.;
223 double radarTracking = 0.;
224
225 double firingEnergy = 0.;
226 double firingForce = 0.;
227 double firingFuel = 0.;
228 double firingHeat = 0.;
229 double firingHull = 0.;
230 double firingShields = 0.;
231 double firingIon = 0.;
232 double firingSlowing = 0.;
233 double firingDisruption = 0.;
234
235 double relativeFiringEnergy = 0.;
236 double relativeFiringHeat = 0.;
237 double relativeFiringFuel = 0.;
238 double relativeFiringHull = 0.;
239 double relativeFiringShields = 0.;
240
241 double splitRange = 0.;
242 double triggerRadius = 0.;
243 double blastRadius = 0.;
244
245 static const int DAMAGE_TYPES = 14;
246 static const int HIT_FORCE = 0;
247 // Normal damage types:
248 static const int SHIELD_DAMAGE = 1;
249 static const int HULL_DAMAGE = 2;
250 static const int FUEL_DAMAGE = 3;
251 static const int HEAT_DAMAGE = 4;
252 static const int ENERGY_DAMAGE = 5;
253 // Status effects:
254 static const int ION_DAMAGE = 6;
255 static const int DISRUPTION_DAMAGE = 7;
256 static const int SLOWING_DAMAGE = 8;
257 // Relative damage types:
258 static const int RELATIVE_SHIELD_DAMAGE = 9;
259 static const int RELATIVE_HULL_DAMAGE = 10;
260 static const int RELATIVE_FUEL_DAMAGE = 11;
261 static const int RELATIVE_HEAT_DAMAGE = 12;
262 static const int RELATIVE_ENERGY_DAMAGE = 13;
263 mutable double damage[DAMAGE_TYPES] = {};
264
265 double piercing = 0.;
266
267 double rangeOverride = 0.;
268 double velocityOverride = 0.;
269
270 bool hasDamageDropoff = false;
271 std::pair<double, double> damageDropoffRange;
272 double damageDropoffModifier;
273
274 // Cache the calculation of these values, for faster access.
275 mutable bool calculatedDamage = true;
276 mutable bool doesDamage = false;
277 mutable double totalLifetime = -1.;
278 };
279
280
281
282 // Inline the accessors because they get called so frequently.
Lifetime()283 inline int Weapon::Lifetime() const { return lifetime; }
RandomLifetime()284 inline int Weapon::RandomLifetime() const { return randomLifetime; }
Reload()285 inline double Weapon::Reload() const { return reload; }
BurstReload()286 inline double Weapon::BurstReload() const { return burstReload; }
BurstCount()287 inline int Weapon::BurstCount() const { return burstCount; }
Homing()288 inline int Weapon::Homing() const { return homing; }
289
MissileStrength()290 inline int Weapon::MissileStrength() const { return missileStrength; }
AntiMissile()291 inline int Weapon::AntiMissile() const { return antiMissile; }
IsStreamed()292 inline bool Weapon::IsStreamed() const { return isStreamed; }
293
Velocity()294 inline double Weapon::Velocity() const { return velocity; }
RandomVelocity()295 inline double Weapon::RandomVelocity() const { return randomVelocity; }
WeightedVelocity()296 inline double Weapon::WeightedVelocity() const { return (velocityOverride > 0.) ? velocityOverride : velocity; }
Acceleration()297 inline double Weapon::Acceleration() const { return acceleration; }
Drag()298 inline double Weapon::Drag() const { return drag; }
HardpointOffset()299 inline const Point &Weapon::HardpointOffset() const { return hardpointOffset; }
300
Turn()301 inline double Weapon::Turn() const { return turn; }
Inaccuracy()302 inline double Weapon::Inaccuracy() const { return inaccuracy; }
TurretTurn()303 inline double Weapon::TurretTurn() const { return turretTurn; }
304
Tracking()305 inline double Weapon::Tracking() const { return tracking; }
OpticalTracking()306 inline double Weapon::OpticalTracking() const { return opticalTracking; }
InfraredTracking()307 inline double Weapon::InfraredTracking() const { return infraredTracking; }
RadarTracking()308 inline double Weapon::RadarTracking() const { return radarTracking; }
309
FiringEnergy()310 inline double Weapon::FiringEnergy() const { return firingEnergy; }
FiringForce()311 inline double Weapon::FiringForce() const { return firingForce; }
FiringFuel()312 inline double Weapon::FiringFuel() const { return firingFuel; }
FiringHeat()313 inline double Weapon::FiringHeat() const { return firingHeat; }
FiringHull()314 inline double Weapon::FiringHull() const { return firingHull; }
FiringShields()315 inline double Weapon::FiringShields() const { return firingShields; }
FiringIon()316 inline double Weapon::FiringIon() const{ return firingIon; }
FiringSlowing()317 inline double Weapon::FiringSlowing() const{ return firingSlowing; }
FiringDisruption()318 inline double Weapon::FiringDisruption() const{ return firingDisruption; }
319
RelativeFiringEnergy()320 inline double Weapon::RelativeFiringEnergy() const{ return relativeFiringEnergy; }
RelativeFiringHeat()321 inline double Weapon::RelativeFiringHeat() const{ return relativeFiringHeat; }
RelativeFiringFuel()322 inline double Weapon::RelativeFiringFuel() const{ return relativeFiringFuel; }
RelativeFiringHull()323 inline double Weapon::RelativeFiringHull() const{ return relativeFiringHull; }
RelativeFiringShields()324 inline double Weapon::RelativeFiringShields() const{ return relativeFiringShields; }
325
Piercing()326 inline double Weapon::Piercing() const { return piercing; }
327
SplitRange()328 inline double Weapon::SplitRange() const { return splitRange; }
TriggerRadius()329 inline double Weapon::TriggerRadius() const { return triggerRadius; }
BlastRadius()330 inline double Weapon::BlastRadius() const { return blastRadius; }
HitForce()331 inline double Weapon::HitForce() const { return TotalDamage(HIT_FORCE); }
332
IsSafe()333 inline bool Weapon::IsSafe() const { return isSafe; }
IsPhasing()334 inline bool Weapon::IsPhasing() const { return isPhasing; }
IsDamageScaled()335 inline bool Weapon::IsDamageScaled() const { return isDamageScaled; }
IsGravitational()336 inline bool Weapon::IsGravitational() const { return isGravitational; }
337
ShieldDamage()338 inline double Weapon::ShieldDamage() const { return TotalDamage(SHIELD_DAMAGE); }
HullDamage()339 inline double Weapon::HullDamage() const { return TotalDamage(HULL_DAMAGE); }
FuelDamage()340 inline double Weapon::FuelDamage() const { return TotalDamage(FUEL_DAMAGE); }
HeatDamage()341 inline double Weapon::HeatDamage() const { return TotalDamage(HEAT_DAMAGE); }
EnergyDamage()342 inline double Weapon::EnergyDamage() const { return TotalDamage(ENERGY_DAMAGE); }
343
IonDamage()344 inline double Weapon::IonDamage() const { return TotalDamage(ION_DAMAGE); }
DisruptionDamage()345 inline double Weapon::DisruptionDamage() const { return TotalDamage(DISRUPTION_DAMAGE); }
SlowingDamage()346 inline double Weapon::SlowingDamage() const { return TotalDamage(SLOWING_DAMAGE); }
347
RelativeShieldDamage()348 inline double Weapon::RelativeShieldDamage() const { return TotalDamage(RELATIVE_SHIELD_DAMAGE); }
RelativeHullDamage()349 inline double Weapon::RelativeHullDamage() const { return TotalDamage(RELATIVE_HULL_DAMAGE); }
RelativeFuelDamage()350 inline double Weapon::RelativeFuelDamage() const { return TotalDamage(RELATIVE_FUEL_DAMAGE); }
RelativeHeatDamage()351 inline double Weapon::RelativeHeatDamage() const { return TotalDamage(RELATIVE_HEAT_DAMAGE); }
RelativeEnergyDamage()352 inline double Weapon::RelativeEnergyDamage() const { return TotalDamage(RELATIVE_ENERGY_DAMAGE); }
353
DoesDamage()354 inline bool Weapon::DoesDamage() const { if(!calculatedDamage) TotalDamage(0); return doesDamage; }
355
HasDamageDropoff()356 inline bool Weapon::HasDamageDropoff() const { return hasDamageDropoff; }
357
358
359
360 #endif
361