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