1 /* PlayerInfo.h 2 Copyright (c) 2014 by Michael Zahniser 3 4 Endless Sky is free software: you can redistribute it and/or modify it under the 5 terms of the GNU General Public License as published by the Free Software 6 Foundation, either version 3 of the License, or (at your option) any later version. 7 8 Endless Sky is distributed in the hope that it will be useful, but WITHOUT ANY 9 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 10 PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 */ 12 13 #ifndef PLAYER_INFO_H_ 14 #define PLAYER_INFO_H_ 15 16 #include "Account.h" 17 #include "CargoHold.h" 18 #include "CoreStartData.h" 19 #include "DataNode.h" 20 #include "Date.h" 21 #include "Depreciation.h" 22 #include "GameEvent.h" 23 #include "Mission.h" 24 25 #include <chrono> 26 #include <list> 27 #include <map> 28 #include <memory> 29 #include <set> 30 #include <string> 31 #include <utility> 32 #include <vector> 33 34 class Government; 35 class Outfit; 36 class Planet; 37 class Rectangle; 38 class Ship; 39 class ShipEvent; 40 class StartConditions; 41 class StellarObject; 42 class System; 43 class UI; 44 45 46 47 // Class holding information about a "player" - their name, their finances, what 48 // ship(s) they own and with what outfits, what systems they have visited, etc. 49 // This class also handles saving the player's info to disk so it can be read 50 // back in exactly the same state later. This includes what changes the player 51 // has made to the universe, what jobs are being offered to them right now, 52 // and what their current travel plan is, if any. 53 class PlayerInfo { 54 public: 55 PlayerInfo() = default; 56 // Don't allow copying this class. 57 PlayerInfo(const PlayerInfo &) = delete; 58 PlayerInfo &operator=(const PlayerInfo &) = delete; 59 PlayerInfo(PlayerInfo &&) = default; 60 PlayerInfo &operator=(PlayerInfo &&) = default; 61 ~PlayerInfo() noexcept = default; 62 63 // Reset the player to an "empty" state, i.e. no player is loaded. 64 void Clear(); 65 66 // Check if any player's information is loaded. 67 bool IsLoaded() const; 68 // Make a new player. 69 void New(const StartConditions &start); 70 // Load an existing player. 71 void Load(const std::string &path); 72 // Load the most recently saved player. If no save could be loaded, returns false. 73 bool LoadRecent(); 74 // Save this player (using the Identifier() as the file name). 75 void Save() const; 76 77 // Get the root filename used for this player's saved game files. (If there 78 // are multiple pilots with the same name it may have a digit appended.) 79 std::string Identifier() const; 80 81 // Apply the given changes and store them in the player's saved game file. 82 void AddChanges(std::list<DataNode> &changes); 83 // Add an event that will happen at the given date. 84 void AddEvent(const GameEvent &event, const Date &date); 85 86 // Mark the player as dead, or check if they have died. 87 void Die(int response = 0, const std::shared_ptr<Ship> &capturer = nullptr); 88 bool IsDead() const; 89 90 // Get or set the player's name. 91 const std::string &FirstName() const; 92 const std::string &LastName() const; 93 void SetName(const std::string &first, const std::string &last); 94 95 // Get or change the current date. 96 const Date &GetDate() const; 97 void IncrementDate(); 98 99 // Get basic data about the player's starting scenario. 100 const CoreStartData &StartData() const noexcept; 101 102 // Set the system the player is in. This must be stored here so that even if 103 // the player sells all their ships, we still know where the player is. 104 // This also marks the given system as visited. 105 void SetSystem(const System &system); 106 const System *GetSystem() const; 107 // Set what planet the player is on (or nullptr, if taking off). 108 void SetPlanet(const Planet *planet); 109 const Planet *GetPlanet() const; 110 // If the player is landed, return the stellar object they are on. 111 const StellarObject *GetStellarObject() const; 112 // Check whether a mission conversation has raised a flag that the player 113 // must leave the planet immediately (without time to do anything else). 114 bool ShouldLaunch() const; 115 116 // Access the player's accounting information. 117 const Account &Accounts() const; 118 Account &Accounts(); 119 // Calculate the daily salaries for crew, not counting crew on "parked" ships. 120 int64_t Salaries() const; 121 // Calculate the daily maintenance cost for all ships and in cargo outfits. 122 int64_t Maintenance() const; 123 124 // Access the flagship (the first ship in the list). This returns null if 125 // the player does not have any ships that can be a flagship. 126 const Ship *Flagship() const; 127 Ship *Flagship(); 128 const std::shared_ptr<Ship> &FlagshipPtr(); 129 // Get the full list of ships the player owns. 130 const std::vector<std::shared_ptr<Ship>> &Ships() const; 131 // Inspect the flightworthiness of the player's active fleet as a whole to 132 // determine which ships cannot travel with the group. 133 std::map<const std::shared_ptr<Ship>, std::vector<std::string>> FlightCheck() const; 134 // Add a captured ship to your fleet. 135 void AddShip(const std::shared_ptr<Ship> &ship); 136 // Buy or sell a ship. 137 void BuyShip(const Ship *model, const std::string &name, bool isGift = false); 138 void SellShip(const Ship *selected); 139 void DisownShip(const Ship *selected); 140 void ParkShip(const Ship *selected, bool isParked); 141 void RenameShip(const Ship *selected, const std::string &name); 142 // Change the order of the given ship in the list. 143 void ReorderShip(int fromIndex, int toIndex); 144 int ReorderShips(const std::set<int> &fromIndices, int toIndex); 145 // Get the attraction factors of the player's fleet to raid fleets. 146 std::pair<double, double> RaidFleetFactors() const; 147 148 // Get cargo information. 149 CargoHold &Cargo(); 150 const CargoHold &Cargo() const; 151 // Get items stored on the player's current planet. 152 CargoHold *Storage(bool forceCreate = false); 153 // Get items stored on all planets (for map display). 154 const std::map<const Planet *, CargoHold> &PlanetaryStorage() const; 155 // Get cost basis for commodities. 156 void AdjustBasis(const std::string &commodity, int64_t adjustment); 157 int64_t GetBasis(const std::string &commodity, int tons = 1) const; 158 // Call this when leaving the outfitter, shipyard, or hiring panel. 159 void UpdateCargoCapacities(); 160 // Switch cargo from being stored in ships to being stored here. 161 void Land(UI *ui); 162 // Load the cargo back into your ships. This may require selling excess. 163 bool TakeOff(UI *ui); 164 165 // Get or add to pilot's playtime. 166 double GetPlayTime() const noexcept; 167 void AddPlayTime(std::chrono::nanoseconds timeVal); 168 169 // Get the player's logbook. 170 const std::multimap<Date, std::string> &Logbook() const; 171 void AddLogEntry(const std::string &text); 172 const std::map<std::string, std::map<std::string, std::string>> &SpecialLogs() const; 173 void AddSpecialLog(const std::string &type, const std::string &name, const std::string &text); 174 bool HasLogs() const; 175 176 // Get mission information. 177 const std::list<Mission> &Missions() const; 178 const std::list<Mission> &AvailableJobs() const; 179 const Mission *ActiveBoardingMission() const; 180 void UpdateMissionNPCs(); 181 void AcceptJob(const Mission &mission, UI *ui); 182 // Check to see if there is any mission to offer right now. 183 Mission *MissionToOffer(Mission::Location location); 184 Mission *BoardingMission(const std::shared_ptr<Ship> &ship); 185 void ClearActiveBoardingMission(); 186 // If one of your missions cannot be offered because you do not have enough 187 // space for it, and it specifies a message to be shown in that situation, 188 // show that message. 189 void HandleBlockedMissions(Mission::Location location, UI *ui); 190 // Callback for accepting or declining whatever mission has been offered. 191 void MissionCallback(int response); 192 // Basic callback for handling forced departure from a planet. 193 void BasicCallback(int response); 194 // Complete or fail a mission. 195 void RemoveMission(Mission::Trigger trigger, const Mission &mission, UI *ui); 196 // Mark a mission as failed, but do not remove it from the mission list yet. 197 void FailMission(const Mission &mission); 198 // Update mission status based on an event. 199 void HandleEvent(const ShipEvent &event, UI *ui); 200 201 // Access the "condition" flags for this player. 202 int64_t GetCondition(const std::string &name) const; 203 std::map<std::string, int64_t> &Conditions(); 204 const std::map<std::string, int64_t> &Conditions() const; 205 // Set and check the reputation conditions, which missions and events 206 // can use to modify the player's reputation with other governments. 207 void SetReputationConditions(); 208 void CheckReputationConditions(); 209 210 // Check what the player knows about the given system or planet. 211 bool HasSeen(const System &system) const; 212 bool HasVisited(const System &system) const; 213 bool HasVisited(const Planet &planet) const; 214 bool KnowsName(const System &system) const; 215 // Marking a system as visited also "sees" its neighbors. 216 void Visit(const System &system); 217 void Visit(const Planet &planet); 218 // Mark a system and its planets as unvisited, even if visited previously. 219 void Unvisit(const System &system); 220 void Unvisit(const Planet &planet); 221 222 // Access the player's travel plan. 223 bool HasTravelPlan() const; 224 const std::vector<const System *> &TravelPlan() const; 225 std::vector<const System *> &TravelPlan(); 226 // Remove the first or last system from the travel plan. 227 void PopTravel(); 228 // Get or set the planet to land on at the end of the travel path. 229 const Planet *TravelDestination() const; 230 void SetTravelDestination(const Planet *planet); 231 232 // Toggle which secondary weapon the player has selected. 233 const Outfit *SelectedWeapon() const; 234 void SelectNext(); 235 236 // Escorts currently selected for giving orders. 237 const std::vector<std::weak_ptr<Ship>> &SelectedShips() const; 238 // Select any player ships in the given box or list. Return true if any were 239 // selected. 240 bool SelectShips(const Rectangle &box, bool hasShift); 241 bool SelectShips(const std::vector<const Ship *> &stack, bool hasShift); 242 void SelectShip(const Ship *ship, bool hasShift); 243 void SelectGroup(int group, bool hasShift); 244 void SetGroup(int group, const std::set<Ship *> *newShips = nullptr); 245 std::set<Ship *> GetGroup(int group); 246 247 // Keep track of any outfits that you have sold since landing. These will be 248 // available to buy back until you take off. 249 int Stock(const Outfit *outfit) const; 250 void AddStock(const Outfit *outfit, int count); 251 // Get depreciation information. 252 const Depreciation &FleetDepreciation() const; 253 const Depreciation &StockDepreciation() const; 254 255 // Keep track of what materials you have mined in each system. 256 void Harvest(const Outfit *type); 257 const std::set<std::pair<const System *, const Outfit *>> &Harvested() const; 258 259 // Get or set the travel destination for selected escorts via the map. 260 const std::pair<const System *, Point> &GetEscortDestination() const; 261 void SetEscortDestination(const System *system = nullptr, Point pos = Point()); 262 bool HasEscortDestination() const; 263 264 // Get or set what coloring is currently selected in the map. 265 int MapColoring() const; 266 void SetMapColoring(int index); 267 // Get or set the map zoom level. 268 int MapZoom() const; 269 void SetMapZoom(int level); 270 // Get the set of collapsed categories for the named panel. 271 std::set<std::string> &Collapsed(const std::string &name); 272 273 274 private: 275 // Apply any "changes" saved in this player info to the global game state. 276 void ApplyChanges(); 277 // After loading & applying changes, make sure the player & ship locations are sensible. 278 void ValidateLoad(); 279 280 // New missions are generated each time you land on a planet. 281 void UpdateAutoConditions(bool isBoarding = false); 282 void CreateMissions(); 283 void StepMissions(UI *ui); 284 void Autosave() const; 285 void Save(const std::string &path) const; 286 287 // Check for and apply any punitive actions from planetary security. 288 void Fine(UI *ui); 289 290 // Helper function to update the ship selection. 291 void SelectShip(const std::shared_ptr<Ship> &ship, bool *first); 292 293 // Check that this player's current state can be saved. 294 bool CanBeSaved() const; 295 296 297 private: 298 std::string firstName; 299 std::string lastName; 300 std::string filePath; 301 302 Date date; 303 const System *system = nullptr; 304 const Planet *planet = nullptr; 305 bool shouldLaunch = false; 306 bool isDead = false; 307 308 // The amount of in-game time played, in seconds. 309 double playTime = 0.; 310 311 Account accounts; 312 313 std::shared_ptr<Ship> flagship; 314 std::vector<std::shared_ptr<Ship>> ships; 315 std::vector<std::weak_ptr<Ship>> selectedShips; 316 std::map<const Ship *, int> groups; 317 CargoHold cargo; 318 std::map<const Planet *, CargoHold> planetaryStorage; 319 std::map<std::string, int64_t> costBasis; 320 321 std::multimap<Date, std::string> logbook; 322 std::map<std::string, std::map<std::string, std::string>> specialLogs; 323 324 // A list of the player's active, accepted missions. 325 std::list<Mission> missions; 326 // These lists are populated when you land on a planet, and saved so that 327 // they will not change if you reload the game. 328 std::list<Mission> availableJobs; 329 std::list<Mission> availableMissions; 330 // If any mission component is not fully defined, the mission is deactivated 331 // until its components are fully evaluable (i.e. needed plugins are reinstalled). 332 std::list<Mission> inactiveMissions; 333 // Missions that are failed or aborted, but not yet deleted, and any 334 // missions offered while in-flight are not saved. 335 std::list<Mission> doneMissions; 336 std::list<Mission> boardingMissions; 337 // This pointer to the most recently accepted boarding mission enables 338 // its NPCs to be placed before the player lands, and is then cleared. 339 Mission *activeBoardingMission = nullptr; 340 341 std::map<std::string, int64_t> conditions; 342 343 std::set<const System *> seen; 344 std::set<const System *> visitedSystems; 345 std::set<const Planet *> visitedPlanets; 346 std::vector<const System *> travelPlan; 347 const Planet *travelDestination = nullptr; 348 349 const Outfit *selectedWeapon = nullptr; 350 351 std::map<const Outfit *, int> stock; 352 Depreciation depreciation; 353 Depreciation stockDepreciation; 354 std::set<std::pair<const System *, const Outfit *>> harvested; 355 356 // Changes that this PlayerInfo wants to make to the global galaxy state: 357 std::vector<std::pair<const Government *, double>> reputationChanges; 358 std::list<DataNode> dataChanges; 359 DataNode economy; 360 // Persons that have been killed in this player's universe: 361 std::vector<std::string> destroyedPersons; 362 // Events that are going to happen some time in the future: 363 std::list<GameEvent> gameEvents; 364 365 // The system and position therein to which the "orbits" system UI issued a move order. 366 std::pair<const System *, Point> interstellarEscortDestination; 367 // Currently selected coloring, in the map panel (defaults to reputation): 368 int mapColoring = -6; 369 int mapZoom = 0; 370 371 // Currently collapsed categories for various panels. 372 std::map<std::string, std::set<std::string>> collapsed; 373 374 bool freshlyLoaded = true; 375 int desiredCrew = 0; 376 377 // Basic information about the player's starting scenario. 378 CoreStartData startData; 379 }; 380 381 382 383 #endif 384