forked from pioneerspacesim/pioneer
/
Ship.h
338 lines (271 loc) · 10.9 KB
/
Ship.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
// Copyright © 2008-2013 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
#ifndef _SHIP_H
#define _SHIP_H
#include "libs.h"
#include "Camera.h"
#include "DynamicBody.h"
#include "EquipSet.h"
#include "galaxy/SystemPath.h"
#include "NavLights.h"
#include "Planet.h"
#include "Serializer.h"
#include "ShipType.h"
#include "scenegraph/SceneGraph.h"
#include "scenegraph/ModelSkin.h"
#include <list>
class SpaceStation;
class HyperspaceCloud;
class AICommand;
class ShipController;
class CargoBody;
class Missile;
namespace Graphics { class Renderer; }
struct shipstats_t {
int max_capacity;
int used_capacity;
int used_cargo;
int free_capacity;
int total_mass; // cargo, equipment + hull
float hull_mass_left; // effectively hitpoints
float hyperspace_range;
float hyperspace_range_max;
float shield_mass;
float shield_mass_left;
float fuel_tank_mass; //thruster, not hyperspace fuel
float fuel_tank_mass_left;
float fuel_use; // percentage (ie, 0--100) of tank used per second at full thrust
};
class SerializableEquipSet: public EquipSet {
public:
void Save(Serializer::Writer &wr);
void Load(Serializer::Reader &rd);
};
class Ship: public DynamicBody {
friend class ShipController; //only controllers need access to AITimeStep
friend class PlayerShipController;
public:
OBJDEF(Ship, DynamicBody, SHIP);
Ship(ShipType::Id shipId);
Ship() {} //default constructor used before Load
virtual ~Ship();
void SetController(ShipController *c); //deletes existing
ShipController *GetController() const { return m_controller; }
virtual bool IsPlayerShip() const { return false; } //XXX to be replaced with an owner check
virtual void SetDockedWith(SpaceStation *, int port);
/** Use GetDockedWith() to determine if docked */
SpaceStation *GetDockedWith() const { return m_dockedWith; }
int GetDockingPort() const { return m_dockedWithPort; }
virtual void SetLandedOn(Planet *p, float latitude, float longitude);
virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform);
void SetThrusterState(int axis, double level) {
if (m_thrusterFuel <= 0.f) level = 0.0;
m_thrusters[axis] = Clamp(level, -1.0, 1.0);
}
void SetThrusterState(const vector3d &levels);
vector3d GetThrusterState() const { return m_thrusters; }
void SetAngThrusterState(int axis, double level) { m_angThrusters[axis] = Clamp(level, -1.0, 1.0); }
void SetAngThrusterState(const vector3d &levels);
vector3d GetAngThrusterState() const { return m_angThrusters; }
void ClearThrusterState();
vector3d GetMaxThrust(const vector3d &dir) const;
double GetAccelFwd() const { return -m_type->linThrust[ShipType::THRUSTER_FORWARD] / GetMass(); }
double GetAccelRev() const { return m_type->linThrust[ShipType::THRUSTER_REVERSE] / GetMass(); }
double GetAccelUp() const { return m_type->linThrust[ShipType::THRUSTER_UP] / GetMass(); }
double GetAccelMin() const;
void UpdateEquipStats();
void UpdateFuelStats();
void UpdateStats();
const shipstats_t &GetStats() const { return m_stats; }
void Explode();
void SetGunState(int idx, int state);
void UpdateMass();
virtual bool SetWheelState(bool down); // returns success of state change, NOT state itself
void Blastoff();
bool Undock();
virtual void TimeStepUpdate(const float timeStep);
virtual void StaticUpdate(const float timeStep);
void TimeAccelAdjust(const float timeStep);
void SetDecelerating(bool decel) { m_decelerating = decel; }
bool IsDecelerating() const { return m_decelerating; }
virtual void NotifyRemoved(const Body* const removedBody);
virtual bool OnCollision(Object *o, Uint32 flags, double relVel);
virtual bool OnDamage(Object *attacker, float kgDamage);
enum FlightState { // <enum scope='Ship' name=ShipFlightState public>
FLYING, // open flight (includes autopilot)
DOCKING, // in docking animation
DOCKED, // docked with station
LANDED, // rough landed (not docked)
HYPERSPACE, // in hyperspace
};
FlightState GetFlightState() const { return m_flightState; }
void SetFlightState(FlightState s);
float GetWheelState() const { return m_wheelState; }
int GetWheelTransition() const { return m_wheelTransition; }
bool SpawnCargo(CargoBody * c_body) const;
virtual bool IsInSpace() const { return (m_flightState != HYPERSPACE); }
void SetHyperspaceDest(const SystemPath &dest) { m_hyperspace.dest = dest; }
const SystemPath &GetHyperspaceDest() const { return m_hyperspace.dest; }
double GetHyperspaceDuration() const { return m_hyperspace.duration; }
enum HyperjumpStatus { // <enum scope='Ship' name=ShipJumpStatus prefix=HYPERJUMP_ public>
HYPERJUMP_OK,
HYPERJUMP_CURRENT_SYSTEM,
HYPERJUMP_NO_DRIVE,
HYPERJUMP_DRIVE_ACTIVE,
HYPERJUMP_OUT_OF_RANGE,
HYPERJUMP_INSUFFICIENT_FUEL,
HYPERJUMP_SAFETY_LOCKOUT
};
HyperjumpStatus GetHyperspaceDetails(const SystemPath &dest, int &outFuelRequired, double &outDurationSecs);
HyperjumpStatus CheckHyperspaceTo(const SystemPath &dest, int &outFuelRequired, double &outDurationSecs);
HyperjumpStatus CheckHyperspaceTo(const SystemPath &dest) {
int unusedFuel;
double unusedDuration;
return CheckHyperspaceTo(dest, unusedFuel, unusedDuration);
}
bool CanHyperspaceTo(const SystemPath &dest, HyperjumpStatus &status) {
status = CheckHyperspaceTo(dest);
return (status == HYPERJUMP_OK);
}
bool CanHyperspaceTo(const SystemPath &dest) { return (CheckHyperspaceTo(dest) == HYPERJUMP_OK); }
virtual Ship::HyperjumpStatus StartHyperspaceCountdown(const SystemPath &dest);
float GetHyperspaceCountdown() const { return m_hyperspace.countdown; }
bool IsHyperspaceActive() const { return (m_hyperspace.countdown > 0.0); }
virtual void ResetHyperspaceCountdown();
Equip::Type GetHyperdriveFuelType() const;
// 0 to 1.0 is alive, > 1.0 = death
double GetHullTemperature() const;
void UseECM();
virtual Missile * SpawnMissile(ShipType::Id missile_type, int power=-1);
enum AlertState { // <enum scope='Ship' name=ShipAlertStatus prefix=ALERT_ public>
ALERT_NONE,
ALERT_SHIP_NEARBY,
ALERT_SHIP_FIRING,
};
AlertState GetAlertState() { return m_alertState; }
bool AIMatchVel(const vector3d &vel);
bool AIChangeVelBy(const vector3d &diffvel); // acts in obj space
vector3d AIChangeVelDir(const vector3d &diffvel); // world space, maintain direction
void AIMatchAngVelObjSpace(const vector3d &angvel);
double AIFaceUpdir(const vector3d &updir, double av=0);
double AIFaceDirection(const vector3d &dir, double av=0);
vector3d AIGetLeadDir(const Body *target, const vector3d& targaccel, int gunindex=0);
double AITravelTime(const vector3d &reldir, double targdist, const vector3d &relvel, double endspeed, double maxdecel);
// old stuff, deprecated
void AIAccelToModelRelativeVelocity(const vector3d v);
void AIModelCoordsMatchAngVel(vector3d desiredAngVel, double softness);
void AIModelCoordsMatchSpeedRelTo(const vector3d v, const Ship *);
void AIClearInstructions();
bool AIIsActive() { return m_curAICmd ? true : false; }
void AIGetStatusText(char *str);
enum AIError { // <enum scope='Ship' name=ShipAIError prefix=AIERROR_ public>
AIERROR_NONE=0,
AIERROR_GRAV_TOO_HIGH,
AIERROR_REFUSED_PERM,
AIERROR_ORBIT_IMPOSSIBLE
};
AIError AIMessage(AIError msg=AIERROR_NONE) { AIError tmp = m_aiMessage; m_aiMessage = msg; return tmp; }
void AIKamikaze(Body *target);
void AIKill(Ship *target);
//void AIJourney(SystemBodyPath &dest);
void AIDock(SpaceStation *target);
void AIFlyTo(Body *target);
void AIOrbit(Body *target, double alt);
void AIHoldPosition();
void AIBodyDeleted(const Body* const body) {}; // todo: signals
SerializableEquipSet m_equipment; // shouldn't be public?...
virtual void PostLoadFixup(Space *space);
const ShipType *GetShipType() const { return m_type; }
void SetShipType(const ShipType::Id &shipId);
const SceneGraph::ModelSkin &GetSkin() const { return m_skin; }
void SetSkin(const SceneGraph::ModelSkin &skin);
void SetLabel(const std::string &label);
static std::string MakeRandomLabel(); // XXX doesn't really belong here
float GetPercentShields() const;
float GetPercentHull() const;
void SetPercentHull(float);
float GetGunTemperature(int idx) const { return m_gun[idx].temperature; }
enum FuelState { // <enum scope='Ship' name=ShipFuelStatus prefix=FUEL_ public>
FUEL_OK,
FUEL_WARNING,
FUEL_EMPTY,
};
FuelState GetFuelState() { return m_thrusterFuel > 0.05f ? FUEL_OK : m_thrusterFuel > 0.0f ? FUEL_WARNING : FUEL_EMPTY; }
// fuel left, 0.0-1.0
double GetFuel() const { return m_thrusterFuel; }
void SetFuel(const double f);
double GetFuelReserve() const { return m_reserveFuel; }
void SetFuelReserve(const double f) { m_reserveFuel = Clamp(f, 0.0, 1.0); }
// percentage (ie, 0--100) of tank used per second at full thrust
double GetFuelUseRate() const;
double GetSpeedReachedWithFuel() const;
void EnterSystem();
HyperspaceCloud *GetHyperspaceCloud() const { return m_hyperspaceCloud; }
sigc::signal<void> onDock; // JJ: check what these are for
sigc::signal<void> onUndock;
// mutable because asking to know when state changes is not the same as
// actually changing state
mutable sigc::signal<void> onFlavourChanged;
protected:
virtual void Save(Serializer::Writer &wr, Space *space);
virtual void Load(Serializer::Reader &rd, Space *space);
void RenderLaserfire();
bool AITimeStep(float timeStep); // Called by controller. Returns true if complete
virtual void SetAlertState(AlertState as);
virtual void OnEnterHyperspace();
virtual void OnEnterSystem();
SpaceStation *m_dockedWith;
int m_dockedWithPort;
struct Gun {
vector3f pos;
vector3f dir;
Uint32 state;
float recharge;
float temperature;
};
Gun m_gun[ShipType::GUNMOUNT_MAX];
float m_ecmRecharge;
ShipController *m_controller;
private:
float GetECMRechargeTime();
void DoThrusterSounds() const;
void FireWeapon(int num);
void Init();
bool IsFiringLasers();
void TestLanded();
void UpdateAlertState();
void UpdateFuel(float timeStep, const vector3d &thrust);
void SetShipId(const ShipType::Id &shipId);
void OnEquipmentChange(Equip::Type e);
void EnterHyperspace();
void InitGun(const char *tag, int num);
shipstats_t m_stats;
const ShipType *m_type;
SceneGraph::ModelSkin m_skin;
FlightState m_flightState;
bool m_testLanded;
float m_launchLockTimeout;
float m_wheelState;
int m_wheelTransition;
vector3d m_thrusters;
vector3d m_angThrusters;
AlertState m_alertState;
double m_lastFiringAlert;
struct HyperspacingOut {
SystemPath dest;
// > 0 means active
float countdown;
bool now;
double duration;
} m_hyperspace;
HyperspaceCloud *m_hyperspaceCloud;
AICommand *m_curAICmd;
AIError m_aiMessage;
bool m_decelerating;
double m_thrusterFuel; // remaining fuel 0.0-1.0
double m_reserveFuel; // 0-1, fuel not to touch for the current AI program
int m_dockedWithIndex; // deserialisation
SceneGraph::Animation *m_landingGearAnimation;
ScopedPtr<NavLights> m_navLights;
};
#endif /* _SHIP_H */