pioneer/src/Ship.h

348 lines
11 KiB
C++

// Copyright © 2008-2021 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 <unordered_map>
#include "DynamicBody.h"
#include "ShipType.h"
#include "galaxy/SystemPath.h"
#include "lua/LuaRef.h"
#include "scenegraph/ModelSkin.h"
#include "sound/Sound.h"
#include "FixedGuns.h"
#include "ship/Propulsion.h"
class AICommand;
class Camera;
class CargoBody;
class SpaceStation;
class HyperspaceCloud;
class Missile;
class NavLights;
class Planet;
class Sensors;
class ShipController;
class Space;
struct CollisionContact;
struct HeatGradientParameters_t;
namespace Graphics {
class Renderer;
}
struct shipstats_t {
int used_capacity;
int used_cargo;
int free_capacity;
int static_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_left;
// cached equipment information to avoid costly Lua lookups
int atmo_shield_cap;
int radar_cap;
int fuel_scoop_cap;
int cargo_bay_life_support_cap;
int hull_autorepair_cap;
};
struct HyperdriveSoundsTable {
std::string jump_sound;
std::string warmup_sound;
std::string abort_sound;
};
class Ship : public DynamicBody {
friend class ShipController; //only controllers need access to AITimeStep
friend class PlayerShipController;
public:
OBJDEF(Ship, DynamicBody, SHIP);
Ship() = delete;
Ship(const Json &jsonObj, Space *space);
Ship(const ShipType::Id &shipId);
virtual ~Ship();
virtual void SetFrame(FrameId fId) override;
void SetController(ShipController *c); //deletes existing
ShipController *GetController() const { return m_controller; }
virtual void SetDockedWith(SpaceStation *, int port);
/** Use GetDockedWith() to determine if docked */
SpaceStation *GetDockedWith() const { return m_dockedWith; }
int GetDockingPort() const { return m_dockedWithPort; }
bool IsDocked() const { return GetFlightState() == Ship::DOCKED; }
bool IsLanded() const { return GetFlightState() == Ship::LANDED; }
virtual void SetLandedOn(Planet *p, float latitude, float longitude);
virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) override;
inline void ClearThrusterState()
{
ClearAngThrusterState();
if (m_launchLockTimeout <= 0.0f) ClearLinThrusterState();
}
void UpdateLuaStats();
void UpdateEquipStats();
void UpdateFuelStats();
void UpdateGunsStats();
const shipstats_t &GetStats() const { return m_stats; }
void Explode();
virtual bool DoDamage(float kgDamage); // can be overloaded in Player to add audio
void SetGunState(int idx, int state);
float GetGunTemperature(int idx) const { return GetFixedGuns()->GetGunTemperature(idx); }
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) override;
virtual void StaticUpdate(const float timeStep) override;
void TimeAccelAdjust(const float timeStep);
bool IsDecelerating() const { return m_decelerating; }
virtual void NotifyRemoved(const Body *const removedBody) override;
virtual bool OnCollision(Body *o, Uint32 flags, double relVel) override;
virtual bool OnDamage(Body *attacker, float kgDamage, const CollisionContact &contactData) override;
enum FlightState { // <enum scope='Ship' name=ShipFlightState public>
FLYING, // open flight (includes autopilot)
DOCKING, // in docking animation
UNDOCKING, // in docking animation
DOCKED, // docked with station
LANDED, // rough landed (not docked)
JUMPING, // between space and hyperspace ;)
HYPERSPACE, // in hyperspace
};
// vector3d CalcAtmoPassiveControl() const;
vector3d CalcAtmoTorque() const;
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;
LuaRef GetEquipSet() const { return m_equipSet; }
virtual bool IsInSpace() const override { 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; }
double GetECMRechargeRemain() const { return m_ecmRecharge; }
enum HyperjumpStatus { // <enum scope='Ship' name=ShipJumpStatus prefix=HYPERJUMP_ public>
HYPERJUMP_OK,
HYPERJUMP_CURRENT_SYSTEM,
HYPERJUMP_NO_DRIVE,
HYPERJUMP_INITIATED,
HYPERJUMP_DRIVE_ACTIVE,
HYPERJUMP_OUT_OF_RANGE,
HYPERJUMP_INSUFFICIENT_FUEL,
HYPERJUMP_SAFETY_LOCKOUT
};
Ship::HyperjumpStatus CheckHyperjumpCapability() const;
virtual Ship::HyperjumpStatus InitiateHyperjumpTo(const SystemPath &dest, int warmup_time, double duration, const HyperdriveSoundsTable &sounds, LuaRef checks);
virtual void AbortHyperjump();
float GetHyperspaceCountdown() const { return m_hyperspace.countdown; }
bool IsHyperspaceActive() const { return (m_hyperspace.countdown > 0.0); }
// 0 to 1.0 is alive, > 1.0 = death
double GetHullTemperature() const;
enum ECMResult {
ECM_NOT_INSTALLED,
ECM_ACTIVATED,
ECM_RECHARGING,
};
ECMResult 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,
ALERT_MISSILE_DETECTED,
};
AlertState GetAlertState() { return m_alertState; }
void AIClearInstructions(); // Note: defined in Ship-AI.cpp
bool AIIsActive() { return m_curAICmd ? true : false; }
void AIGetStatusText(char *str); // Note: defined in Ship-AI.cpp
void AIKamikaze(Body *target); // Note: defined in Ship-AI.cpp
void AIKill(Ship *target); // Note: defined in Ship-AI.cpp
//void AIJourney(SystemBodyPath &dest);
void AIDock(SpaceStation *target); // Note: defined in Ship-AI.cpp
void AIFlyTo(Body *target); // Note: defined in Ship-AI.cpp
void AIOrbit(Body *target, double alt); // Note: defined in Ship-AI.cpp
void AIHoldPosition(); // Note: defined in Ship-AI.cpp
void AIBodyDeleted(const Body *const body){}; // Note: defined in Ship-AI.cpp // todo: signals
const AICommand *GetAICommand() const { return m_curAICmd; }
virtual void PostLoadFixup(Space *space) override;
const ShipType *GetShipType() const { return m_type; }
virtual void SetShipType(const ShipType::Id &shipId);
const SceneGraph::ModelSkin &GetSkin() const { return m_skin; }
void SetSkin(const SceneGraph::ModelSkin &skin);
void SetPattern(unsigned int num);
void SetLabel(const std::string &label) override;
void SetShipName(const std::string &shipName);
float GetAtmosphericPressureLimit() const;
float GetPercentShields() const;
float GetPercentHull() const;
void SetPercentHull(float);
void EnterSystem();
HyperspaceCloud *GetHyperspaceCloud() const { return m_hyperspaceCloud; }
sigc::signal<void> onDock; // JJ: check what these are for
sigc::signal<void> onUndock;
sigc::signal<void> onLanded;
// mutable because asking to know when state changes is not the same as
// actually changing state
mutable sigc::signal<void> onFlavourChanged;
bool IsInvulnerable() const { return m_invulnerable; }
void SetInvulnerable(bool b) { m_invulnerable = b; }
Sensors *GetSensors() const { return m_sensors.get(); }
Uint8 GetRelations(Body *other) const; //0=hostile, 50=neutral, 100=ally
void SetRelations(Body *other, Uint8 percent);
double GetLandingPosOffset() const { return m_landingMinOffset; }
protected:
vector3d CalcAtmosphericForce() const override;
virtual void SaveToJson(Json &jsonObj, Space *space) override;
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;
float m_ecmRecharge;
ShipController *m_controller;
struct HyperspacingOut {
SystemPath dest;
// > 0 means active
float countdown;
bool now;
double duration;
LuaRef checks; // A Lua function to check all the conditions before the jump
HyperdriveSoundsTable sounds;
} m_hyperspace;
LuaRef m_equipSet;
private:
float GetECMRechargeTime();
void DoThrusterSounds() const;
void Init();
void TestLanded();
void UpdateAlertState();
void UpdateFuel(float timeStep);
void SetShipId(const ShipType::Id &shipId);
void EnterHyperspace();
void InitMaterials();
void InitEquipSet();
bool m_invulnerable;
static const double DEFAULT_LIFT_TO_DRAG_RATIO;
static const float DEFAULT_SHIELD_COOLDOWN_TIME;
float m_shieldCooldown;
shipstats_t m_stats;
const ShipType *m_type;
SceneGraph::ModelSkin m_skin;
Sound::Event m_beamLaser[2];
FlightState m_flightState;
bool m_testLanded;
bool m_forceWheelUpdate;
float m_launchLockTimeout;
float m_wheelState;
int m_wheelTransition;
AlertState m_alertState;
double m_lastAlertUpdate;
double m_lastFiringAlert;
bool m_shipNear;
bool m_shipFiring;
bool m_missileDetected;
HyperspaceCloud *m_hyperspaceCloud;
AICommand *m_curAICmd;
double m_landingMinOffset; // offset from the centre of the ship used during docking
int m_dockedWithIndex; // deserialisation
SceneGraph::Animation *m_landingGearAnimation;
std::unique_ptr<NavLights> m_navLights;
static HeatGradientParameters_t s_heatGradientParams;
std::unique_ptr<Sensors> m_sensors;
std::unordered_map<Body *, Uint8> m_relationsMap;
std::string m_shipName;
public:
void ClearAngThrusterState() { GetPropulsion()->ClearAngThrusterState(); }
void ClearLinThrusterState() { GetPropulsion()->ClearLinThrusterState(); }
double GetAccelFwd() { return GetPropulsion()->GetAccelFwd(); }
void SetAngThrusterState(const vector3d &levels) { GetPropulsion()->SetAngThrusterState(levels); }
double GetFuel() const { return GetPropulsion()->GetFuel(); }
double GetAccel(Thruster thruster) const { return GetPropulsion()->GetAccel(thruster); }
void SetFuel(const double f) { GetPropulsion()->SetFuel(f); }
void SetFuelReserve(const double f) { GetPropulsion()->SetFuelReserve(f); }
bool AIMatchVel(const vector3d &vel) { return GetPropulsion()->AIMatchVel(vel); }
double AIFaceDirection(const vector3d &dir, double av = 0) { return GetPropulsion()->AIFaceDirection(dir, av); }
void AIMatchAngVelObjSpace(const vector3d &angvel) { return GetPropulsion()->AIMatchAngVelObjSpace(angvel); }
void SetThrusterState(int axis, double level) { return GetPropulsion()->SetLinThrusterState(axis, level); }
void AIModelCoordsMatchAngVel(const vector3d &desiredAngVel, double softness) { return GetPropulsion()->AIModelCoordsMatchAngVel(desiredAngVel, softness); }
};
#endif /* _SHIP_H */