File: StartInfo.h

package info (click to toggle)
vcmi 1.6.5%2Bdfsg-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 32,060 kB
  • sloc: cpp: 238,971; python: 265; sh: 224; xml: 157; ansic: 78; objc: 61; makefile: 49
file content (271 lines) | stat: -rw-r--r-- 6,686 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/*
 * StartInfo.h, part of VCMI engine
 *
 * Authors: listed in file AUTHORS in main folder
 *
 * License: GNU General Public License v2.0 or later
 * Full text of license available in license.txt file, in main folder
 *
 */
#pragma once

#include "vstd/DateUtils.h"

#include "GameConstants.h"
#include "TurnTimerInfo.h"
#include "ExtraOptionsInfo.h"
#include "campaign/CampaignConstants.h"
#include "serializer/Serializeable.h"
#include "ResourceSet.h"

VCMI_LIB_NAMESPACE_BEGIN

class CMapGenOptions;
class CampaignState;
class CMapInfo;
struct PlayerInfo;
class PlayerColor;

struct DLL_LINKAGE SimturnsInfo
{
	/// Minimal number of turns that must be played simultaneously even if contact has been detected
	int requiredTurns = 0;
	/// Maximum number of turns that might be played simultaneously unless contact is detected
	int optionalTurns = 0;
	/// If set to true, human and 1 AI can act at the same time
	bool allowHumanWithAI = false;
	/// If set to true, allied players can play simultaneously even after contacting each other
	bool ignoreAlliedContacts = true;

	bool operator == (const SimturnsInfo & other) const
	{
		return requiredTurns == other.requiredTurns &&
				optionalTurns == other.optionalTurns &&
				ignoreAlliedContacts == other.ignoreAlliedContacts &&
				allowHumanWithAI == other.allowHumanWithAI;
	}

	template <typename Handler>
	void serialize(Handler &h)
	{
		h & requiredTurns;
		h & optionalTurns;
		h & allowHumanWithAI;

		if (h.version >= Handler::Version::SAVE_COMPATIBILITY_FIXES)
			h & ignoreAlliedContacts;
		else
			ignoreAlliedContacts = true;
	}
};

enum class PlayerStartingBonus : int8_t
{
	RANDOM   = -1,
	ARTIFACT =  0,
	GOLD     =  1,
	RESOURCE =  2
};

struct DLL_LINKAGE Handicap {
	TResources startBonus = TResources();
	int percentIncome = 100;
	int percentGrowth = 100;

	template <typename Handler>
	void serialize(Handler &h)
	{
		h & startBonus;
		h & percentIncome;
		h & percentGrowth;
	}
};

/// Struct which describes the name, the color, the starting bonus of a player
struct DLL_LINKAGE PlayerSettings
{
	enum { PLAYER_AI = 0 }; // for use in playerID

	PlayerStartingBonus bonus;
	FactionID castle;
	HeroTypeID hero;
	HeroTypeID heroPortrait; //-1 if default, else ID

	std::string heroNameTextId;
	PlayerColor color; //from 0 -

	Handicap handicap;

	std::string name;
	std::set<ui8> connectedPlayerIDs; //Empty - AI, or connectrd player ids
	bool compOnly; //true if this player is a computer only player; required for RMG
	template <typename Handler>
	void serialize(Handler &h)
	{
		h & castle;
		h & hero;
		h & heroPortrait;
		h & heroNameTextId;
		h & bonus;
		h & color;
		if (h.version >= Handler::Version::PLAYER_HANDICAP)
			h & handicap;
		else
		{
			enum EHandicap {NO_HANDICAP, MILD, SEVERE};
			EHandicap handicapLegacy = NO_HANDICAP;
			h & handicapLegacy;
		}
		h & name;
		h & connectedPlayerIDs;
		h & compOnly;
	}

	PlayerSettings();
	bool isControlledByAI() const;
	bool isControlledByHuman() const;

	FactionID getCastleValidated() const;
	HeroTypeID getHeroValidated() const;
};

enum class EStartMode : int32_t
{
	NEW_GAME,
	LOAD_GAME,
	CAMPAIGN,
	INVALID = 255
};

/// Struct which describes the difficulty, the turn time,.. of a heroes match.
struct DLL_LINKAGE StartInfo : public Serializeable
{
	EStartMode mode;
	ui8 difficulty; //0=easy; 4=impossible

	using TPlayerInfos = std::map<PlayerColor, PlayerSettings>;
	TPlayerInfos playerInfos; //color indexed

	time_t startTime;
	std::string fileURI;
	SimturnsInfo simturnsInfo;
	TurnTimerInfo turnTimerInfo;
	ExtraOptionsInfo extraOptionsInfo;
	std::string mapname; // empty for random map, otherwise name of the map or savegame
	bool createRandomMap() const { return mapGenOptions != nullptr; }
	std::shared_ptr<CMapGenOptions> mapGenOptions;

	std::shared_ptr<CampaignState> campState;

	PlayerSettings & getIthPlayersSettings(const PlayerColor & no);
	const PlayerSettings & getIthPlayersSettings(const PlayerColor & no) const;
	PlayerSettings * getPlayersSettings(const ui8 connectedPlayerId);

	// TODO: Must be client-side
	std::string getCampaignName() const;

	/// Controls hardcoded check for handling of garrisons by AI in Restoration of Erathia campaigns to match H3 behavior
	bool isRestorationOfErathiaCampaign() const;

	template <typename Handler>
	void serialize(Handler &h)
	{
		h & mode;
		h & difficulty;
		h & playerInfos;
		if (h.version < Handler::Version::REMOVE_LIB_RNG)
		{
			uint32_t oldSeeds = 0;
			h & oldSeeds;
			h & oldSeeds;
			h & oldSeeds;
		}
		if (h.version < Handler::Version::FOLDER_NAME_REWORK)
		{
			std::string startTimeLegacy;
			h & startTimeLegacy;
			struct std::tm tm;
			std::istringstream ss(startTimeLegacy);
			ss >> std::get_time(&tm, "%Y%m%dT%H%M%S");
			startTime = mktime(&tm);
		}
		else
			h & startTime;
		h & fileURI;
		h & simturnsInfo;
		h & turnTimerInfo;
		h & extraOptionsInfo;
		h & mapname;
		h & mapGenOptions;
		h & campState;
	}

	StartInfo()
		: mode(EStartMode::INVALID)
		, difficulty(1)
		, startTime(std::time(nullptr))
	{

	}
};

struct ClientPlayer
{
	int connection;
	std::string name;

	template <typename Handler> void serialize(Handler &h)
	{
		h & connection;
		h & name;
	}
};

struct DLL_LINKAGE LobbyState
{
	std::shared_ptr<StartInfo> si;
	std::shared_ptr<CMapInfo> mi;
	std::map<ui8, ClientPlayer> playerNames; // id of player <-> player name; 0 is reserved as ID of AI "players"
	int hostClientId;
	// TODO: Campaign-only and we don't really need either of them.
	// Before start both go into CCampaignState that is part of StartInfo
	CampaignScenarioID campaignMap;
	int campaignBonus;

	LobbyState() : si(new StartInfo()), hostClientId(-1), campaignMap(CampaignScenarioID::NONE), campaignBonus(-1) {}

	template <typename Handler> void serialize(Handler &h)
	{
		h & si;
		h & mi;
		h & playerNames;
		h & hostClientId;
		h & campaignMap;
		h & campaignBonus;
	}
};

struct DLL_LINKAGE LobbyInfo : public LobbyState
{
	std::string uuid;

	LobbyInfo() {}

	void verifyStateBeforeStart(bool ignoreNoHuman = false) const;

	bool isClientHost(int clientId) const;
	bool isPlayerHost(const PlayerColor & color) const;
	std::set<PlayerColor> getAllClientPlayers(int clientId) const;
	std::vector<ui8> getConnectedPlayerIdsForClient(int clientId) const;

	// Helpers for lobby state access
	std::set<PlayerColor> clientHumanColors(int clientId);
	PlayerColor clientFirstColor(int clientId) const;
	bool isClientColor(int clientId, const PlayerColor & color) const;
	ui8 clientFirstId(int clientId) const; // Used by chat only!
	PlayerInfo & getPlayerInfo(PlayerColor color);
	TeamID getPlayerTeamId(const PlayerColor & color);
};


VCMI_LIB_NAMESPACE_END