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