2023-10-19 16:19:09 +02:00
|
|
|
/*
|
|
|
|
* 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"
|
2023-12-28 21:48:19 +02:00
|
|
|
#include "ExtraOptionsInfo.h"
|
2023-10-19 16:19:09 +02:00
|
|
|
#include "campaign/CampaignConstants.h"
|
2024-05-07 21:17:05 +02:00
|
|
|
#include "serializer/Serializeable.h"
|
2023-10-19 16:19:09 +02:00
|
|
|
|
|
|
|
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
|
2023-11-13 19:50:53 +02:00
|
|
|
bool allowHumanWithAI = false;
|
2024-05-19 22:13:42 +02:00
|
|
|
/// If set to true, allied players can play simultaneously even after contacting each other
|
|
|
|
bool ignoreAlliedContacts = true;
|
2023-10-19 16:19:09 +02:00
|
|
|
|
2023-12-07 16:36:44 +02:00
|
|
|
bool operator == (const SimturnsInfo & other) const
|
|
|
|
{
|
|
|
|
return requiredTurns == other.requiredTurns &&
|
|
|
|
optionalTurns == other.optionalTurns &&
|
2024-05-19 22:13:42 +02:00
|
|
|
ignoreAlliedContacts == other.ignoreAlliedContacts &&
|
2023-12-07 16:36:44 +02:00
|
|
|
allowHumanWithAI == other.allowHumanWithAI;
|
|
|
|
}
|
|
|
|
|
2023-10-19 16:19:09 +02:00
|
|
|
template <typename Handler>
|
2024-01-20 20:34:51 +02:00
|
|
|
void serialize(Handler &h)
|
2023-10-19 16:19:09 +02:00
|
|
|
{
|
|
|
|
h & requiredTurns;
|
|
|
|
h & optionalTurns;
|
|
|
|
h & allowHumanWithAI;
|
2024-05-19 22:13:42 +02:00
|
|
|
|
|
|
|
static_assert(Handler::Version::RELEASE_143 < Handler::Version::CURRENT, "Please add ignoreAlliedContacts to serialization for 1.6");
|
|
|
|
// disabled to allow multiplayer compatibility between 1.5.2 and 1.5.1
|
|
|
|
// h & ignoreAlliedContacts
|
2023-10-19 16:19:09 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class PlayerStartingBonus : int8_t
|
|
|
|
{
|
|
|
|
RANDOM = -1,
|
|
|
|
ARTIFACT = 0,
|
|
|
|
GOLD = 1,
|
|
|
|
RESOURCE = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
/// 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 -
|
|
|
|
enum EHandicap {NO_HANDICAP, MILD, SEVERE};
|
|
|
|
EHandicap handicap;//0-no, 1-mild, 2-severe
|
|
|
|
|
|
|
|
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>
|
2024-01-20 20:34:51 +02:00
|
|
|
void serialize(Handler &h)
|
2023-10-19 16:19:09 +02:00
|
|
|
{
|
|
|
|
h & castle;
|
|
|
|
h & hero;
|
|
|
|
h & heroPortrait;
|
|
|
|
h & heroNameTextId;
|
|
|
|
h & bonus;
|
|
|
|
h & color;
|
|
|
|
h & handicap;
|
|
|
|
h & name;
|
|
|
|
h & connectedPlayerIDs;
|
|
|
|
h & compOnly;
|
|
|
|
}
|
|
|
|
|
|
|
|
PlayerSettings();
|
|
|
|
bool isControlledByAI() const;
|
|
|
|
bool isControlledByHuman() const;
|
|
|
|
|
|
|
|
FactionID getCastleValidated() const;
|
|
|
|
HeroTypeID getHeroValidated() const;
|
|
|
|
};
|
|
|
|
|
2024-01-21 16:48:36 +02:00
|
|
|
enum class EStartMode : int32_t
|
|
|
|
{
|
|
|
|
NEW_GAME,
|
|
|
|
LOAD_GAME,
|
|
|
|
CAMPAIGN,
|
|
|
|
INVALID = 255
|
|
|
|
};
|
|
|
|
|
2023-10-19 16:19:09 +02:00
|
|
|
/// Struct which describes the difficulty, the turn time,.. of a heroes match.
|
2024-05-07 21:17:05 +02:00
|
|
|
struct DLL_LINKAGE StartInfo : public Serializeable
|
2023-10-19 16:19:09 +02:00
|
|
|
{
|
2024-01-21 16:48:36 +02:00
|
|
|
EStartMode mode;
|
2023-10-19 16:19:09 +02:00
|
|
|
ui8 difficulty; //0=easy; 4=impossible
|
|
|
|
|
|
|
|
using TPlayerInfos = std::map<PlayerColor, PlayerSettings>;
|
|
|
|
TPlayerInfos playerInfos; //color indexed
|
|
|
|
|
|
|
|
ui32 seedToBeUsed; //0 if not sure (client requests server to decide, will be send in reply pack)
|
|
|
|
ui32 seedPostInit; //so we know that game is correctly synced at the start; 0 if not known yet
|
|
|
|
ui32 mapfileChecksum; //0 if not relevant
|
|
|
|
std::string startTimeIso8601;
|
|
|
|
std::string fileURI;
|
|
|
|
SimturnsInfo simturnsInfo;
|
|
|
|
TurnTimerInfo turnTimerInfo;
|
2023-12-28 21:48:19 +02:00
|
|
|
ExtraOptionsInfo extraOptionsInfo;
|
2023-10-19 16:19:09 +02:00
|
|
|
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;
|
|
|
|
|
2024-04-20 16:30:50 +02:00
|
|
|
/// Controls hardcoded check for "Steadwick's Fall" scenario from "Dungeon and Devils" campaign
|
|
|
|
bool isSteadwickFallCampaignMission() const;
|
|
|
|
|
2023-10-19 16:19:09 +02:00
|
|
|
template <typename Handler>
|
2024-01-20 20:34:51 +02:00
|
|
|
void serialize(Handler &h)
|
2023-10-19 16:19:09 +02:00
|
|
|
{
|
|
|
|
h & mode;
|
|
|
|
h & difficulty;
|
|
|
|
h & playerInfos;
|
|
|
|
h & seedToBeUsed;
|
|
|
|
h & seedPostInit;
|
|
|
|
h & mapfileChecksum;
|
|
|
|
h & startTimeIso8601;
|
|
|
|
h & fileURI;
|
|
|
|
h & simturnsInfo;
|
|
|
|
h & turnTimerInfo;
|
2024-01-20 20:34:51 +02:00
|
|
|
if(h.version >= Handler::Version::HAS_EXTRA_OPTIONS)
|
2023-12-28 21:48:19 +02:00
|
|
|
h & extraOptionsInfo;
|
2023-12-27 21:44:32 +02:00
|
|
|
else
|
2023-12-28 21:48:19 +02:00
|
|
|
extraOptionsInfo = ExtraOptionsInfo();
|
2023-10-19 16:19:09 +02:00
|
|
|
h & mapname;
|
|
|
|
h & mapGenOptions;
|
|
|
|
h & campState;
|
|
|
|
}
|
|
|
|
|
2024-01-21 16:48:36 +02:00
|
|
|
StartInfo() : mode(EStartMode::INVALID), difficulty(1), seedToBeUsed(0), seedPostInit(0),
|
2023-12-28 21:48:19 +02:00
|
|
|
mapfileChecksum(0), startTimeIso8601(vstd::getDateTimeISO8601Basic(std::time(nullptr))), fileURI("")
|
2023-10-19 16:19:09 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ClientPlayer
|
|
|
|
{
|
|
|
|
int connection;
|
|
|
|
std::string name;
|
|
|
|
|
2024-01-20 20:34:51 +02:00
|
|
|
template <typename Handler> void serialize(Handler &h)
|
2023-10-19 16:19:09 +02:00
|
|
|
{
|
|
|
|
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) {}
|
|
|
|
|
2024-01-20 20:34:51 +02:00
|
|
|
template <typename Handler> void serialize(Handler &h)
|
2023-10-19 16:19:09 +02:00
|
|
|
{
|
|
|
|
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;
|
2023-11-18 16:34:18 +02:00
|
|
|
bool isPlayerHost(const PlayerColor & color) const;
|
|
|
|
std::set<PlayerColor> getAllClientPlayers(int clientId) const;
|
2023-10-19 16:19:09 +02:00
|
|
|
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
|