1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00
vcmi/lib/StartInfo.h
Ivan Savenko 82c37573fa Removed save compatibility with 1.4
All save compatibility checks targeting 1.4 saves have now been removed.
Saves from 1.5 can still be loaded in 1.6

Implemeted few TODO's in serialization that were postponed to avoid
breaking save compatibility in MP for 1.5.X releases.

Fixed missed case for loading black market object from 1.5 saves
2024-08-29 18:51:53 +00:00

262 lines
6.3 KiB
C++

/*
* 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
std::string startTimeIso8601;
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 "Steadwick's Fall" scenario from "Dungeon and Devils" campaign
bool isSteadwickFallCampaignMission() 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;
}
h & startTimeIso8601;
h & fileURI;
h & simturnsInfo;
h & turnTimerInfo;
h & extraOptionsInfo;
h & mapname;
h & mapGenOptions;
h & campState;
}
StartInfo()
: mode(EStartMode::INVALID)
, difficulty(1)
, startTimeIso8601(vstd::getDateTimeISO8601Basic(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