1 // Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details 2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt 3 4 #ifndef _SHIP_H 5 #define _SHIP_H 6 7 #include <unordered_map> 8 9 #include "DynamicBody.h" 10 #include "ShipType.h" 11 #include "galaxy/SystemPath.h" 12 #include "lua/LuaRef.h" 13 #include "scenegraph/ModelSkin.h" 14 #include "sound/Sound.h" 15 16 #include "FixedGuns.h" 17 #include "ship/Propulsion.h" 18 19 class AICommand; 20 class Camera; 21 class CargoBody; 22 class SpaceStation; 23 class HyperspaceCloud; 24 class Missile; 25 class NavLights; 26 class Planet; 27 class Sensors; 28 class ShipController; 29 class Space; 30 31 struct CollisionContact; 32 struct HeatGradientParameters_t; 33 34 namespace Graphics { 35 class Renderer; 36 } 37 38 struct shipstats_t { 39 int used_capacity; 40 int used_cargo; 41 int free_capacity; 42 int static_mass; // cargo, equipment + hull 43 float hull_mass_left; // effectively hitpoints 44 float hyperspace_range; 45 float hyperspace_range_max; 46 float shield_mass; 47 float shield_mass_left; 48 float fuel_tank_mass_left; 49 50 // cached equipment information to avoid costly Lua lookups 51 int atmo_shield_cap; 52 int radar_cap; 53 int fuel_scoop_cap; 54 int cargo_bay_life_support_cap; 55 int hull_autorepair_cap; 56 }; 57 58 struct HyperdriveSoundsTable { 59 std::string jump_sound; 60 std::string warmup_sound; 61 std::string abort_sound; 62 }; 63 64 class Ship : public DynamicBody { 65 friend class ShipController; //only controllers need access to AITimeStep 66 friend class PlayerShipController; 67 68 public: 69 OBJDEF(Ship, DynamicBody, SHIP); 70 Ship() = delete; 71 Ship(const Json &jsonObj, Space *space); 72 Ship(const ShipType::Id &shipId); 73 virtual ~Ship(); 74 75 virtual void SetFrame(FrameId fId) override; 76 77 void SetController(ShipController *c); //deletes existing GetController()78 ShipController *GetController() const { return m_controller; } 79 80 virtual void SetDockedWith(SpaceStation *, int port); 81 /** Use GetDockedWith() to determine if docked */ GetDockedWith()82 SpaceStation *GetDockedWith() const { return m_dockedWith; } GetDockingPort()83 int GetDockingPort() const { return m_dockedWithPort; } IsDocked()84 bool IsDocked() const { return GetFlightState() == Ship::DOCKED; } IsLanded()85 bool IsLanded() const { return GetFlightState() == Ship::LANDED; } 86 87 virtual void SetLandedOn(Planet *p, float latitude, float longitude); 88 89 virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) override; 90 ClearThrusterState()91 inline void ClearThrusterState() 92 { 93 ClearAngThrusterState(); 94 if (m_launchLockTimeout <= 0.0f) ClearLinThrusterState(); 95 } 96 void UpdateLuaStats(); 97 void UpdateEquipStats(); 98 void UpdateFuelStats(); 99 void UpdateGunsStats(); GetStats()100 const shipstats_t &GetStats() const { return m_stats; } 101 102 void Explode(); 103 virtual bool DoDamage(float kgDamage); // can be overloaded in Player to add audio 104 void SetGunState(int idx, int state); GetGunTemperature(int idx)105 float GetGunTemperature(int idx) const { return GetFixedGuns()->GetGunTemperature(idx); } 106 void UpdateMass(); 107 virtual bool SetWheelState(bool down); // returns success of state change, NOT state itself 108 void Blastoff(); 109 bool Undock(); 110 virtual void TimeStepUpdate(const float timeStep) override; 111 virtual void StaticUpdate(const float timeStep) override; 112 113 void TimeAccelAdjust(const float timeStep); 114 IsDecelerating()115 bool IsDecelerating() const { return m_decelerating; } 116 117 virtual void NotifyRemoved(const Body *const removedBody) override; 118 virtual bool OnCollision(Body *o, Uint32 flags, double relVel) override; 119 virtual bool OnDamage(Body *attacker, float kgDamage, const CollisionContact &contactData) override; 120 121 enum FlightState { // <enum scope='Ship' name=ShipFlightState public> 122 FLYING, // open flight (includes autopilot) 123 DOCKING, // in docking animation 124 UNDOCKING, // in docking animation 125 DOCKED, // docked with station 126 LANDED, // rough landed (not docked) 127 JUMPING, // between space and hyperspace ;) 128 HYPERSPACE, // in hyperspace 129 }; 130 131 // vector3d CalcAtmoPassiveControl() const; 132 vector3d CalcAtmoTorque() const; 133 GetFlightState()134 FlightState GetFlightState() const { return m_flightState; } 135 void SetFlightState(FlightState s); GetWheelState()136 float GetWheelState() const { return m_wheelState; } GetWheelTransition()137 int GetWheelTransition() const { return m_wheelTransition; } 138 bool SpawnCargo(CargoBody *c_body) const; 139 GetEquipSet()140 LuaRef GetEquipSet() const { return m_equipSet; } 141 IsInSpace()142 virtual bool IsInSpace() const override { return (m_flightState != HYPERSPACE); } 143 SetHyperspaceDest(const SystemPath & dest)144 void SetHyperspaceDest(const SystemPath &dest) { m_hyperspace.dest = dest; } GetHyperspaceDest()145 const SystemPath &GetHyperspaceDest() const { return m_hyperspace.dest; } GetHyperspaceDuration()146 double GetHyperspaceDuration() const { return m_hyperspace.duration; } GetECMRechargeRemain()147 double GetECMRechargeRemain() const { return m_ecmRecharge; } 148 149 enum HyperjumpStatus { // <enum scope='Ship' name=ShipJumpStatus prefix=HYPERJUMP_ public> 150 HYPERJUMP_OK, 151 HYPERJUMP_CURRENT_SYSTEM, 152 HYPERJUMP_NO_DRIVE, 153 HYPERJUMP_INITIATED, 154 HYPERJUMP_DRIVE_ACTIVE, 155 HYPERJUMP_OUT_OF_RANGE, 156 HYPERJUMP_INSUFFICIENT_FUEL, 157 HYPERJUMP_SAFETY_LOCKOUT 158 }; 159 160 Ship::HyperjumpStatus CheckHyperjumpCapability() const; 161 virtual Ship::HyperjumpStatus InitiateHyperjumpTo(const SystemPath &dest, int warmup_time, double duration, const HyperdriveSoundsTable &sounds, LuaRef checks); 162 virtual void AbortHyperjump(); GetHyperspaceCountdown()163 float GetHyperspaceCountdown() const { return m_hyperspace.countdown; } IsHyperspaceActive()164 bool IsHyperspaceActive() const { return (m_hyperspace.countdown > 0.0); } 165 166 // 0 to 1.0 is alive, > 1.0 = death 167 double GetHullTemperature() const; 168 169 enum ECMResult { 170 ECM_NOT_INSTALLED, 171 ECM_ACTIVATED, 172 ECM_RECHARGING, 173 }; 174 175 ECMResult UseECM(); 176 177 virtual Missile *SpawnMissile(ShipType::Id missile_type, int power = -1); 178 179 enum AlertState { // <enum scope='Ship' name=ShipAlertStatus prefix=ALERT_ public> 180 ALERT_NONE, 181 ALERT_SHIP_NEARBY, 182 ALERT_SHIP_FIRING, 183 ALERT_MISSILE_DETECTED, 184 }; GetAlertState()185 AlertState GetAlertState() { return m_alertState; } 186 187 void AIClearInstructions(); // Note: defined in Ship-AI.cpp AIIsActive()188 bool AIIsActive() { return m_curAICmd ? true : false; } 189 void AIGetStatusText(char *str); // Note: defined in Ship-AI.cpp 190 191 void AIKamikaze(Body *target); // Note: defined in Ship-AI.cpp 192 void AIKill(Ship *target); // Note: defined in Ship-AI.cpp 193 //void AIJourney(SystemBodyPath &dest); 194 void AIDock(SpaceStation *target); // Note: defined in Ship-AI.cpp 195 void AIFlyTo(Body *target); // Note: defined in Ship-AI.cpp 196 void AIOrbit(Body *target, double alt); // Note: defined in Ship-AI.cpp 197 void AIHoldPosition(); // Note: defined in Ship-AI.cpp 198 AIBodyDeleted(const Body * const body)199 void AIBodyDeleted(const Body *const body){}; // Note: defined in Ship-AI.cpp // todo: signals 200 GetAICommand()201 const AICommand *GetAICommand() const { return m_curAICmd; } 202 203 virtual void PostLoadFixup(Space *space) override; 204 GetShipType()205 const ShipType *GetShipType() const { return m_type; } 206 virtual void SetShipType(const ShipType::Id &shipId); 207 GetSkin()208 const SceneGraph::ModelSkin &GetSkin() const { return m_skin; } 209 void SetSkin(const SceneGraph::ModelSkin &skin); 210 211 void SetPattern(unsigned int num); 212 213 void SetLabel(const std::string &label) override; 214 void SetShipName(const std::string &shipName); 215 216 float GetAtmosphericPressureLimit() const; 217 float GetPercentShields() const; 218 float GetPercentHull() const; 219 void SetPercentHull(float); 220 221 void EnterSystem(); 222 GetHyperspaceCloud()223 HyperspaceCloud *GetHyperspaceCloud() const { return m_hyperspaceCloud; } 224 225 sigc::signal<void> onDock; // JJ: check what these are for 226 sigc::signal<void> onUndock; 227 sigc::signal<void> onLanded; 228 229 // mutable because asking to know when state changes is not the same as 230 // actually changing state 231 mutable sigc::signal<void> onFlavourChanged; 232 IsInvulnerable()233 bool IsInvulnerable() const { return m_invulnerable; } SetInvulnerable(bool b)234 void SetInvulnerable(bool b) { m_invulnerable = b; } 235 GetSensors()236 Sensors *GetSensors() const { return m_sensors.get(); } 237 238 Uint8 GetRelations(Body *other) const; //0=hostile, 50=neutral, 100=ally 239 void SetRelations(Body *other, Uint8 percent); 240 GetLandingPosOffset()241 double GetLandingPosOffset() const { return m_landingMinOffset; } 242 243 protected: 244 vector3d CalcAtmosphericForce() const override; 245 246 virtual void SaveToJson(Json &jsonObj, Space *space) override; 247 248 bool AITimeStep(float timeStep); // Called by controller. Returns true if complete 249 250 virtual void SetAlertState(AlertState as); 251 252 virtual void OnEnterHyperspace(); 253 virtual void OnEnterSystem(); 254 255 SpaceStation *m_dockedWith; 256 int m_dockedWithPort; 257 258 float m_ecmRecharge; 259 260 ShipController *m_controller; 261 262 struct HyperspacingOut { 263 SystemPath dest; 264 // > 0 means active 265 float countdown; 266 bool now; 267 double duration; 268 LuaRef checks; // A Lua function to check all the conditions before the jump 269 HyperdriveSoundsTable sounds; 270 } m_hyperspace; 271 272 LuaRef m_equipSet; 273 274 private: 275 float GetECMRechargeTime(); 276 void DoThrusterSounds() const; 277 void Init(); 278 void TestLanded(); 279 void UpdateAlertState(); 280 void UpdateFuel(float timeStep); 281 void SetShipId(const ShipType::Id &shipId); 282 void EnterHyperspace(); 283 void InitMaterials(); 284 void InitEquipSet(); 285 286 bool m_invulnerable; 287 288 static const double DEFAULT_LIFT_TO_DRAG_RATIO; 289 290 static const float DEFAULT_SHIELD_COOLDOWN_TIME; 291 float m_shieldCooldown; 292 shipstats_t m_stats; 293 const ShipType *m_type; 294 SceneGraph::ModelSkin m_skin; 295 296 Sound::Event m_beamLaser[2]; 297 298 FlightState m_flightState; 299 bool m_testLanded; 300 bool m_forceWheelUpdate; 301 float m_launchLockTimeout; 302 float m_wheelState; 303 int m_wheelTransition; 304 305 AlertState m_alertState; 306 double m_lastAlertUpdate; 307 double m_lastFiringAlert; 308 bool m_shipNear; 309 bool m_shipFiring; 310 bool m_missileDetected; 311 312 HyperspaceCloud *m_hyperspaceCloud; 313 314 AICommand *m_curAICmd; 315 316 double m_landingMinOffset; // offset from the centre of the ship used during docking 317 318 int m_dockedWithIndex; // deserialisation 319 320 SceneGraph::Animation *m_landingGearAnimation; 321 std::unique_ptr<NavLights> m_navLights; 322 323 static HeatGradientParameters_t s_heatGradientParams; 324 325 std::unique_ptr<Sensors> m_sensors; 326 std::unordered_map<Body *, Uint8> m_relationsMap; 327 328 std::string m_shipName; 329 330 public: ClearAngThrusterState()331 void ClearAngThrusterState() { GetPropulsion()->ClearAngThrusterState(); } ClearLinThrusterState()332 void ClearLinThrusterState() { GetPropulsion()->ClearLinThrusterState(); } GetAccelFwd()333 double GetAccelFwd() { return GetPropulsion()->GetAccelFwd(); } SetAngThrusterState(const vector3d & levels)334 void SetAngThrusterState(const vector3d &levels) { GetPropulsion()->SetAngThrusterState(levels); } GetFuel()335 double GetFuel() const { return GetPropulsion()->GetFuel(); } GetAccel(Thruster thruster)336 double GetAccel(Thruster thruster) const { return GetPropulsion()->GetAccel(thruster); } SetFuel(const double f)337 void SetFuel(const double f) { GetPropulsion()->SetFuel(f); } SetFuelReserve(const double f)338 void SetFuelReserve(const double f) { GetPropulsion()->SetFuelReserve(f); } 339 AIMatchVel(const vector3d & vel)340 bool AIMatchVel(const vector3d &vel) { return GetPropulsion()->AIMatchVel(vel); } 341 double AIFaceDirection(const vector3d &dir, double av = 0) { return GetPropulsion()->AIFaceDirection(dir, av); } AIMatchAngVelObjSpace(const vector3d & angvel)342 void AIMatchAngVelObjSpace(const vector3d &angvel) { return GetPropulsion()->AIMatchAngVelObjSpace(angvel); } SetThrusterState(int axis,double level)343 void SetThrusterState(int axis, double level) { return GetPropulsion()->SetLinThrusterState(axis, level); } AIModelCoordsMatchAngVel(const vector3d & desiredAngVel,double softness)344 void AIModelCoordsMatchAngVel(const vector3d &desiredAngVel, double softness) { return GetPropulsion()->AIModelCoordsMatchAngVel(desiredAngVel, softness); } 345 }; 346 347 #endif /* _SHIP_H */ 348