1 #ifndef PLAYER_SPACESHIP_H
2 #define PLAYER_SPACESHIP_H
3 
4 #include "spaceship.h"
5 #include "scanProbe.h"
6 #include "commsScriptInterface.h"
7 #include "playerInfo.h"
8 #include <iostream>
9 
10 class ScanProbe;
11 
12 enum ECommsState
13 {
14     CS_Inactive,          // No active comms
15     CS_OpeningChannel,    // Opening a comms channel
16     CS_BeingHailed,       // Receiving a hail from an object
17     CS_BeingHailedByGM,   //                   ... the GM
18     CS_ChannelOpen,       // Comms open to an object
19     CS_ChannelOpenPlayer, //           ... another player
20     CS_ChannelOpenGM,     //           ... the GM
21     CS_ChannelFailed,     // Comms failed to connect
22     CS_ChannelBroken,     // Comms broken by other side
23     CS_ChannelClosed      // Comms manually closed
24 };
25 
26 enum EAlertLevel
27 {
28     AL_Normal,      // No alert state
29     AL_YellowAlert, // Yellow
30     AL_RedAlert,    // Red
31     AL_MAX          // ?
32 };
33 
34 class PlayerSpaceship : public SpaceShip
35 {
36 public:
37     // Power consumption and generation base rates
38     constexpr static float default_energy_shield_use_per_second = 1.5f;
39     constexpr static float default_energy_warp_per_second = 1.0f;
40     // Total coolant
41     constexpr static float max_coolant_per_system = 10.0f;
42     float max_coolant;
43     // Overheat subsystem damage rate
44     constexpr static float damage_per_second_on_overheat = 0.08f;
45     // Base time it takes to perform an action
46     constexpr static float shield_calibration_time = 25.0f;
47     constexpr static float comms_channel_open_time = 2.0;
48     constexpr static float scan_probe_charge_time = 10.0f;
49     constexpr static float max_scanning_delay = 6.0;
50     // Maximum number of self-destruction confirmation codes
51     constexpr static int max_self_destruct_codes = 3;
52 
53     constexpr static int16_t CMD_PLAY_CLIENT_SOUND = 0x0001;
54 
55     // Content of a line in the ship's log
56     class ShipLogEntry
57     {
58     public:
59         string prefix;
60         string text;
61         sf::Color color;
62 
ShipLogEntry()63         ShipLogEntry() {}
ShipLogEntry(string prefix,string text,sf::Color color)64         ShipLogEntry(string prefix, string text, sf::Color color)
65         : prefix(prefix), text(text), color(color) {}
66 
67         bool operator!=(const ShipLogEntry& e) { return prefix != e.prefix || text != e.text || color != e.color; }
68     };
69 
70     class CustomShipFunction
71     {
72     public:
73         enum class Type
74         {
75             Info,
76             Button,
77             Message
78         };
79         Type type;
80         string name;
81         string caption;
82         ECrewPosition crew_position;
83         ScriptSimpleCallback callback;
84 
85         bool operator!=(const CustomShipFunction& csf) { return type != csf.type || name != csf.name || caption != csf.caption || crew_position != csf.crew_position; }
86     };
87 
88     // Visual indicators of hull damage and in-progress jumps
89     float hull_damage_indicator;
90     float jump_indicator;
91     // Time in seconds it takes to recalibrate shields
92     float shield_calibration_delay;
93     // Ship automation features, mostly for single-person ships like fighters
94     bool auto_repair_enabled;
95     bool auto_coolant_enabled;
96     // Whether shields are up (true) or down
97     bool shields_active;
98     // Password to join a ship. Default is empty.
99     string control_code;
100 
101 private:
102     bool on_new_player_ship_called=false;
103     // Comms variables
104     ECommsState comms_state;
105     float comms_open_delay;
106     string comms_target_name;
107     string comms_incomming_message;
108     P<SpaceObject> comms_target; // Server only
109     std::vector<int> comms_reply_id;
110     std::vector<string> comms_reply_message;
111     CommsScriptInterface comms_script_interface; // Server only
112     // Ship's log container
113     std::vector<ShipLogEntry> ships_log;
114     float energy_shield_use_per_second = default_energy_shield_use_per_second;
115     float energy_warp_per_second = default_energy_warp_per_second;
116 public:
117     std::vector<CustomShipFunction> custom_functions;
118 
119     std::vector<sf::Vector2f> waypoints;
120 
121     // Ship functionality
122     // Capable of scanning a target
123     bool can_scan = true;
124     // Target of a scan. Server-only value
125     P<SpaceObject> scanning_target;
126     // Time in seconds to scan an object if scanning_complexity is 0 (none)
127     float scanning_delay = 0.0;
128     // Number of sliders during a scan
129     int scanning_complexity = 0;
130     // Number of times an object must be scanned to achieve a fully scanned
131     // state
132     int scanning_depth = 0;
133 
134     // Capable of hacking a target
135     bool can_hack = true;
136     // Capable of docking with a target
137     bool can_dock = true;
138     // Capable of combat maneuvers
139     bool can_combat_maneuver = true;
140 
141     // Capable of self-destruction
142     bool can_self_destruct = true;
143     bool activate_self_destruct = false;
144     uint32_t self_destruct_code[max_self_destruct_codes];
145     bool self_destruct_code_confirmed[max_self_destruct_codes];
146     ECrewPosition self_destruct_code_entry_position[max_self_destruct_codes];
147     ECrewPosition self_destruct_code_show_position[max_self_destruct_codes];
148     float self_destruct_countdown = 0.0;
149     float self_destruct_damage = 150.0;
150     float self_destruct_size = 1500.0;
151 
152     // Capable of probe launches
153     bool can_launch_probe = true;
154     int max_scan_probes = 8;
155     int scan_probe_stock;
156     float scan_probe_recharge = 0.0;
157     ScriptSimpleCallback on_probe_launch;
158     ScriptSimpleCallback on_probe_link;
159     ScriptSimpleCallback on_probe_unlink;
160 
161     // Main screen content
162     EMainScreenSetting main_screen_setting;
163     // Content overlaid on the main screen, such as comms
164     EMainScreenOverlay main_screen_overlay;
165 
166     EAlertLevel alert_level;
167 
168     int32_t linked_science_probe_id = -1;
169 
170     PlayerSpaceship();
171     virtual ~PlayerSpaceship();
172 
173     // Comms functions
isCommsInactive()174     bool isCommsInactive() { return comms_state == CS_Inactive; }
isCommsOpening()175     bool isCommsOpening() { return comms_state == CS_OpeningChannel; }
isCommsBeingHailed()176     bool isCommsBeingHailed() { return comms_state == CS_BeingHailed || comms_state == CS_BeingHailedByGM; }
isCommsBeingHailedByGM()177     bool isCommsBeingHailedByGM() { return comms_state == CS_BeingHailedByGM; }
isCommsFailed()178     bool isCommsFailed() { return comms_state == CS_ChannelFailed; }
isCommsBroken()179     bool isCommsBroken() { return comms_state == CS_ChannelBroken; }
isCommsClosed()180     bool isCommsClosed() { return comms_state == CS_ChannelClosed; }
isCommsChatOpen()181     bool isCommsChatOpen() { return comms_state == CS_ChannelOpenPlayer || comms_state == CS_ChannelOpenGM; }
isCommsChatOpenToGM()182     bool isCommsChatOpenToGM() { return comms_state == CS_ChannelOpenGM; }
isCommsChatOpenToPlayer()183     bool isCommsChatOpenToPlayer() { return comms_state == CS_ChannelOpenPlayer; }
isCommsScriptOpen()184     bool isCommsScriptOpen() { return comms_state == CS_ChannelOpen; }
getCommsState()185     ECommsState getCommsState() { return comms_state; }
getCommsOpeningDelay()186     float getCommsOpeningDelay() { return comms_open_delay; }
getCommsReplyOptions()187     const std::vector<string>& getCommsReplyOptions() const { return comms_reply_message; }
getCommsTarget()188     P<SpaceObject> getCommsTarget() { return comms_target; }
getCommsTargetName()189     const string& getCommsTargetName() { return comms_target_name; }
getCommsIncommingMessage()190     const string& getCommsIncommingMessage() { return comms_incomming_message; }
191     bool hailCommsByGM(string target_name);
192     bool hailByObject(P<SpaceObject> object, string opening_message);
193     void setCommsMessage(string message);
194     void addCommsIncommingMessage(string message);
195     void addCommsOutgoingMessage(string message);
196     void addCommsReply(int32_t id, string message);
197     void switchCommsToGM();
198     void closeComms();
199 
setEnergyLevel(float amount)200     void setEnergyLevel(float amount) { energy_level = std::max(0.0f, std::min(max_energy_level, amount)); }
setEnergyLevelMax(float amount)201     void setEnergyLevelMax(float amount) { max_energy_level = std::max(0.0f, amount); energy_level = std::min(energy_level, max_energy_level); }
getEnergyLevel()202     float getEnergyLevel() { return energy_level; }
getEnergyLevelMax()203     float getEnergyLevelMax() { return max_energy_level; }
204 
setCanScan(bool enabled)205     void setCanScan(bool enabled) { can_scan = enabled; }
getCanScan()206     bool getCanScan() { return can_scan; }
setCanHack(bool enabled)207     void setCanHack(bool enabled) { can_hack = enabled; }
getCanHack()208     bool getCanHack() { return can_hack; }
setCanDock(bool enabled)209     void setCanDock(bool enabled) { can_dock = enabled; }
getCanDock()210     bool getCanDock() { return can_dock; }
setCanCombatManeuver(bool enabled)211     void setCanCombatManeuver(bool enabled) { can_combat_maneuver = enabled; }
getCanCombatManeuver()212     bool getCanCombatManeuver() { return can_combat_maneuver; }
setCanSelfDestruct(bool enabled)213     void setCanSelfDestruct(bool enabled) { can_self_destruct = enabled; }
getCanSelfDestruct()214     bool getCanSelfDestruct() { return can_self_destruct && self_destruct_size > 0 && self_destruct_damage > 0; }
setCanLaunchProbe(bool enabled)215     void setCanLaunchProbe(bool enabled) { can_launch_probe = enabled; }
getCanLaunchProbe()216     bool getCanLaunchProbe() { return can_launch_probe; }
217 
setSelfDestructDamage(float amount)218     void setSelfDestructDamage(float amount) { self_destruct_damage = std::max(0.0f, amount); }
getSelfDestructDamage()219     float getSelfDestructDamage() { return self_destruct_damage; }
setSelfDestructSize(float size)220     void setSelfDestructSize(float size) { self_destruct_size = std::max(0.0f, size); }
getSelfDestructSize()221     float getSelfDestructSize() { return self_destruct_size; }
222 
setScanProbeCount(int amount)223     void setScanProbeCount(int amount) { scan_probe_stock = std::max(0, std::min(amount, max_scan_probes)); }
getScanProbeCount()224     int getScanProbeCount() { return scan_probe_stock; }
setMaxScanProbeCount(int amount)225     void setMaxScanProbeCount(int amount) { max_scan_probes = std::max(0, amount); scan_probe_stock = std::min(scan_probe_stock, max_scan_probes); }
getMaxScanProbeCount()226     int getMaxScanProbeCount() { return max_scan_probes; }
227 
228     void onProbeLaunch(ScriptSimpleCallback callback);
229     void onProbeLink(ScriptSimpleCallback callback);
230     void onProbeUnlink(ScriptSimpleCallback callback);
231 
232     void addCustomButton(ECrewPosition position, string name, string caption, ScriptSimpleCallback callback);
233     void addCustomInfo(ECrewPosition position, string name, string caption);
234     void addCustomMessage(ECrewPosition position, string name, string caption);
235     void addCustomMessageWithCallback(ECrewPosition position, string name, string caption, ScriptSimpleCallback callback);
236     void removeCustom(string name);
237 
getBeamSystemTarget()238     ESystem getBeamSystemTarget(){ return beam_system_target; }
getBeamSystemTargetName()239     string getBeamSystemTargetName(){ return getSystemName(beam_system_target); }
240     // Client command functions
241     virtual void onReceiveClientCommand(int32_t client_id, sf::Packet& packet) override;
242     void commandTargetRotation(float target);
243     void commandTurnSpeed(float turnSpeed);
244     void commandImpulse(float target);
245     void commandWarp(int8_t target);
246     void commandJump(float distance);
247     void commandSetTarget(P<SpaceObject> target);
248     void commandSetScienceLink(P<ScanProbe> probe);
249     void commandClearScienceLink();
250     void commandLoadTube(int8_t tubeNumber, EMissileWeapons missileType);
251     void commandUnloadTube(int8_t tubeNumber);
252     void commandFireTube(int8_t tubeNumber, float missile_target_angle);
253     void commandFireTubeAtTarget(int8_t tubeNumber, P<SpaceObject> target);
254     void commandSetShields(bool enabled);
255     void commandMainScreenSetting(EMainScreenSetting mainScreen);
256     void commandMainScreenOverlay(EMainScreenOverlay mainScreen);
257     void commandScan(P<SpaceObject> object);
258     void commandSetSystemPowerRequest(ESystem system, float power_level);
259     void commandSetSystemCoolantRequest(ESystem system, float coolant_level);
260     void commandDock(P<SpaceObject> station);
261     void commandUndock();
262     void commandAbortDock();
263     void commandOpenTextComm(P<SpaceObject> obj);
264     void commandCloseTextComm();
265     void commandAnswerCommHail(bool awnser);
266     void commandSendComm(uint8_t index);
267     void commandSendCommPlayer(string message);
268     void commandSetAutoRepair(bool enabled);
269     void commandSetBeamFrequency(int32_t frequency);
270     void commandSetBeamSystemTarget(ESystem system);
271     void commandSetShieldFrequency(int32_t frequency);
272     void commandAddWaypoint(sf::Vector2f position);
273     void commandRemoveWaypoint(int32_t index);
274     void commandMoveWaypoint(int32_t index, sf::Vector2f position);
275     void commandActivateSelfDestruct();
276     void commandCancelSelfDestruct();
277     void commandConfirmDestructCode(int8_t index, uint32_t code);
278     void commandCombatManeuverBoost(float amount);
279     void commandCombatManeuverStrafe(float strafe);
280     void commandLaunchProbe(sf::Vector2f target_position);
281     void commandScanDone();
282     void commandScanCancel();
283     void commandSetAlertLevel(EAlertLevel level);
284     void commandHackingFinished(P<SpaceObject> target, string target_system);
285     void commandCustomFunction(string name);
286 
287     virtual void onReceiveServerCommand(sf::Packet& packet) override;
288 
289     // Template function
290     virtual void applyTemplateValues() override;
291 
292     // Ship status functions
293     virtual void executeJump(float distance) override;
294     virtual void takeHullDamage(float damage_amount, DamageInfo& info) override;
295     void setSystemCoolantRequest(ESystem system, float request);
296     void setMaxCoolant(float coolant);
getMaxCoolant()297     float getMaxCoolant() { return max_coolant; }
setAutoCoolant(bool active)298     void setAutoCoolant(bool active) { auto_coolant_enabled = active; }
299     int getRepairCrewCount();
300     void setRepairCrewCount(int amount);
getAlertLevel()301     EAlertLevel getAlertLevel() { return alert_level; }
302 
303     // Flow rate controls.
getEnergyShieldUsePerSecond()304     float getEnergyShieldUsePerSecond() const { return energy_shield_use_per_second; }
setEnergyShieldUsePerSecond(float rate)305     void setEnergyShieldUsePerSecond(float rate) { energy_shield_use_per_second = rate; }
getEnergyWarpPerSecond()306     float getEnergyWarpPerSecond() const { return energy_warp_per_second; }
setEnergyWarpPerSecond(float rate)307     void setEnergyWarpPerSecond(float rate) { energy_warp_per_second = rate; }
308 
309     // Ship update functions
310     virtual void update(float delta) override;
311     virtual bool useEnergy(float amount) override;
312     virtual void addHeat(ESystem system, float amount) override;
313 
314     // Call on the server to play a sound on the main screen.
315     void playSoundOnMainScreen(string sound_name);
316 
317     float getNetSystemEnergyUsage();
318 
319     // Ship's log functions
320     void addToShipLog(string message, sf::Color color);
321     void addToShipLogBy(string message, P<SpaceObject> target);
322     const std::vector<ShipLogEntry>& getShipsLog() const;
323 
324     // Ship's crew functions
325     void transferPlayersToShip(P<PlayerSpaceship> other_ship);
326     void transferPlayersAtPositionToShip(ECrewPosition position, P<PlayerSpaceship> other_ship);
327     bool hasPlayerAtPosition(ECrewPosition position);
328 
329     // Ship shields functions
getShieldsActive()330     virtual bool getShieldsActive() override { return shields_active; }
setShieldsActive(bool active)331     void setShieldsActive(bool active) { shields_active = active; }
332 
333     // Waypoint functions
getWaypointCount()334     int getWaypointCount() { return waypoints.size(); }
getWaypoint(int index)335     sf::Vector2f getWaypoint(int index) { if (index > 0 && index <= int(waypoints.size())) return waypoints[index - 1]; return sf::Vector2f(0, 0); }
336 
337     // Ship control code/password setter
setControlCode(string code)338     void setControlCode(string code) { control_code = code.upper(); }
339 
340     // Radar function
341     virtual void drawOnGMRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range) override;
342 
343     // Script export function
344     virtual string getExportLine() override;
345 };
346 REGISTER_MULTIPLAYER_ENUM(ECommsState);
347 template<> int convert<EAlertLevel>::returnType(lua_State* L, EAlertLevel l);
348 template<> void convert<EAlertLevel>::param(lua_State* L, int& idx, EAlertLevel& al);
349 REGISTER_MULTIPLAYER_ENUM(EAlertLevel);
350 
351 static inline sf::Packet& operator << (sf::Packet& packet, const PlayerSpaceship::CustomShipFunction& csf) { return packet << uint8_t(csf.type) << uint8_t(csf.crew_position) << csf.name << csf.caption; } \
352 static inline sf::Packet& operator >> (sf::Packet& packet, PlayerSpaceship::CustomShipFunction& csf) { int8_t tmp; packet >> tmp; csf.type = PlayerSpaceship::CustomShipFunction::Type(tmp); packet >> tmp; csf.crew_position = ECrewPosition(tmp); packet >> csf.name >> csf.caption; return packet; }
353 
354 string alertLevelToString(EAlertLevel level);
355 string alertLevelToLocaleString(EAlertLevel level);
356 #endif//PLAYER_SPACESHIP_H
357