1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00
vcmi/lib/CGameState.h

569 lines
18 KiB
C
Raw Normal View History

#pragma once
//#ifndef _MSC_VER
#include "CCreatureHandler.h"
2009-05-20 13:08:56 +03:00
#include "VCMI_Lib.h"
2013-04-07 13:48:07 +03:00
#include "mapping/CMap.h"
//#endif
#include "HeroBonus.h"
#include "CCreatureSet.h"
#include "ConstTransitivePtr.h"
#include "IGameCallback.h"
#include "ResourceSet.h"
#include "int3.h"
#include "CObjectHandler.h"
#include "CRandomGenerator.h"
/*
* CGameState.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
*
*/
class CTown;
class CCallback;
class IGameCallback;
class CCreatureSet;
class CStack;
class CQuest;
class CGHeroInstance;
class CGTownInstance;
class CArmedInstance;
class CGDwelling;
class CObjectScript;
class CGObjectInstance;
class CCreature;
class CMap;
struct StartInfo;
struct SDL_Surface;
class CMapHandler;
class CPathfinder;
struct SetObjectProperty;
struct MetaString;
2009-03-07 00:25:19 +02:00
struct CPack;
2009-05-07 18:19:52 +03:00
class CSpell;
struct TerrainTile;
2010-02-07 17:06:14 +02:00
class CHeroClass;
2010-05-08 21:56:38 +03:00
class CCampaign;
class CCampaignState;
class IModableArt;
2011-05-03 06:14:18 +03:00
class CGGarrison;
class CGameInfo;
struct QuestInfo;
class CQuest;
class CCampaignScenario;
2013-12-29 18:48:56 +03:00
struct EventCondition;
2014-01-03 19:36:22 +03:00
class CScenarioTravel;
namespace boost
{
class shared_mutex;
}
//numbers of creatures are exact numbers if detailed else they are quantity ids (0 - a few, 1 - several and so on; additionally -1 - unknown)
2013-02-16 17:03:47 +03:00
struct ArmyDescriptor : public std::map<SlotID, CStackBasicDescriptor>
{
bool isDetailed;
DLL_LINKAGE ArmyDescriptor(const CArmedInstance *army, bool detailed); //not detailed -> quantity ids as count
DLL_LINKAGE ArmyDescriptor();
DLL_LINKAGE int getStrength() const;
};
struct DLL_LINKAGE InfoAboutArmy
{
2013-03-03 20:06:03 +03:00
PlayerColor owner;
std::string name;
ArmyDescriptor army;
InfoAboutArmy();
InfoAboutArmy(const CArmedInstance *Army, bool detailed);
void initFromArmy(const CArmedInstance *Army, bool detailed);
};
struct DLL_LINKAGE InfoAboutHero : public InfoAboutArmy
2010-02-07 17:06:14 +02:00
{
2010-02-07 19:56:06 +02:00
private:
void assign(const InfoAboutHero & iah);
public:
struct DLL_LINKAGE Details
2010-02-07 17:06:14 +02:00
{
std::vector<si32> primskills;
si32 mana, luck, morale;
2010-02-07 17:06:14 +02:00
} *details;
const CHeroClass *hclass;
int portrait;
2010-02-07 17:06:14 +02:00
InfoAboutHero();
2010-02-07 19:56:06 +02:00
InfoAboutHero(const InfoAboutHero & iah);
InfoAboutHero(const CGHeroInstance *h, bool detailed);
2010-02-07 17:06:14 +02:00
~InfoAboutHero();
InfoAboutHero & operator=(const InfoAboutHero & iah);
2010-02-07 17:06:14 +02:00
void initFromHero(const CGHeroInstance *h, bool detailed);
};
/// Struct which holds a int information about a town
struct DLL_LINKAGE InfoAboutTown : public InfoAboutArmy
2011-05-03 06:14:18 +03:00
{
struct DLL_LINKAGE Details
2011-05-03 06:14:18 +03:00
{
si32 hallLevel, goldIncome;
2011-05-03 06:14:18 +03:00
bool customRes;
bool garrisonedHero;
} *details;
2013-09-07 00:57:16 +03:00
const CTown *tType;
2011-05-03 06:14:18 +03:00
si32 built;
si32 fortLevel; //0 - none
2011-05-03 06:14:18 +03:00
InfoAboutTown();
InfoAboutTown(const CGTownInstance *t, bool detailed);
2011-05-03 06:14:18 +03:00
~InfoAboutTown();
void initFromTown(const CGTownInstance *t, bool detailed);
};
2010-07-15 06:04:57 +03:00
// typedef si32 TResourceUnit;
// typedef std::vector<si32> TResourceVector;
// typedef std::set<si32> TResourceSet;
2010-02-07 17:06:14 +02:00
struct DLL_LINKAGE SThievesGuildInfo
2010-02-01 19:51:33 +02:00
{
2013-03-03 20:06:03 +03:00
std::vector<PlayerColor> playerColors; //colors of players that are in-game
2010-02-01 19:51:33 +02:00
2013-03-03 20:06:03 +03:00
std::vector< std::vector< PlayerColor > > numOfTowns, numOfHeroes, gold, woodOre, mercSulfCrystGems, obelisks, artifacts, army, income; // [place] -> [colours of players]
2010-02-01 19:51:33 +02:00
2013-03-03 20:06:03 +03:00
std::map<PlayerColor, InfoAboutHero> colorToBestHero; //maps player's color to his best heros'
2010-02-01 19:51:33 +02:00
2013-03-03 20:06:03 +03:00
std::map<PlayerColor, EAiTactic::EAiTactic> personality; // color to personality // ai tactic
std::map<PlayerColor, si32> bestCreature; // color to ID // id or -1 if not known
2010-02-07 17:06:14 +02:00
// template <typename Handler> void serialize(Handler &h, const int version)
// {
// h & playerColors & numOfTowns & numOfHeroes & gold & woodOre & mercSulfCrystGems & obelisks & artifacts & army & income;
// h & colorToBestHero & personality & bestCreature;
// }
2010-02-01 19:51:33 +02:00
};
struct DLL_LINKAGE PlayerState : public CBonusSystemNode
{
public:
2013-03-03 20:06:03 +03:00
PlayerColor color;
2013-02-09 15:56:35 +03:00
bool human; //true if human controlled player, false for AI
ObjectInstanceID currentSelection; //id of hero/town, 0xffffffff if none
2013-03-03 20:06:03 +03:00
TeamID team;
TResources resources;
std::set<ObjectInstanceID> visitedObjects; // as a std::set, since most accesses here will be from visited status checks
std::vector<ConstTransitivePtr<CGHeroInstance> > heroes;
std::vector<ConstTransitivePtr<CGTownInstance> > towns;
std::vector<ConstTransitivePtr<CGHeroInstance> > availableHeroes; //heroes available in taverns
std::vector<ConstTransitivePtr<CGDwelling> > dwellings; //used for town growth
std::vector<QuestInfo> quests; //store info about all received quests
2013-02-09 15:56:35 +03:00
bool enteredWinningCheatCode, enteredLosingCheatCode; //if true, this player has entered cheat codes for loss / victory
EPlayerStatus::EStatus status;
boost::optional<ui8> daysWithoutCastle;
PlayerState();
std::string nodeName() const override;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & color & human & currentSelection & team & resources & status;
h & heroes & towns & availableHeroes & dwellings & visitedObjects;
h & getBonusList(); //FIXME FIXME FIXME
h & status & daysWithoutCastle;
h & enteredLosingCheatCode & enteredWinningCheatCode;
h & static_cast<CBonusSystemNode&>(*this);
}
};
struct DLL_LINKAGE TeamState : public CBonusSystemNode
{
public:
2013-03-03 20:06:03 +03:00
TeamID id; //position in gameState::teams
std::set<PlayerColor> players; // members of this team
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden
TeamState();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & players & fogOfWarMap;
h & static_cast<CBonusSystemNode&>(*this);
}
};
struct UpgradeInfo
{
CreatureID oldID; //creature to be upgraded
std::vector<CreatureID> newID; //possible upgrades
std::vector<TResources> cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>; cost is for single unit (not entire stack)
UpgradeInfo(){oldID = CreatureID::NONE;};
};
struct DLL_LINKAGE CGPathNode
{
enum EAccessibility
{
NOT_SET = 0,
ACCESSIBLE = 1, //tile can be entered and passed
VISITABLE, //tile can be entered as the last tile in path
BLOCKVIS, //visitable from neighbouring tile but not passable
BLOCKED //tile can't be entered nor visited
};
EAccessibility accessible;
ui8 land;
ui8 turns; //how many turns we have to wait before reachng the tile - 0 means current turn
ui32 moveRemains; //remaining tiles after hero reaches the tile
CGPathNode * theNodeBefore;
int3 coord; //coordinates
CGPathNode();
bool reachable() const;
};
struct DLL_LINKAGE CGPath
{
std::vector<CGPathNode> nodes; //just get node by node
int3 startPos() const; // start point
int3 endPos() const; //destination point
void convert(ui8 mode); //mode=0 -> from 'manifest' to 'object'
};
struct DLL_LINKAGE CPathsInfo
{
2011-09-03 05:54:33 +03:00
bool isValid;
const CGHeroInstance *hero;
int3 hpos;
int3 sizes;
CGPathNode ***nodes; //[w][h][level]
bool getPath(const int3 &dst, CGPath &out);
CPathsInfo(const int3 &Sizes);
~CPathsInfo();
};
struct DLL_EXPORT DuelParameters
2011-01-21 04:36:30 +02:00
{
2013-02-13 01:24:48 +03:00
ETerrainType terType;
BFieldType bfieldType;
struct DLL_EXPORT SideSettings
2011-01-21 04:36:30 +02:00
{
struct DLL_EXPORT StackSettings
2011-01-21 04:36:30 +02:00
{
CreatureID type;
2011-01-21 04:36:30 +02:00
si32 count;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & type & count;
}
StackSettings();
StackSettings(CreatureID Type, si32 Count);
} stacks[GameConstants::ARMY_SIZE];
2011-01-21 04:36:30 +02:00
si32 heroId; //-1 if none
std::vector<si32> heroPrimSkills; //may be empty
std::map<si32, CArtifactInstance*> artifacts;
std::vector<std::pair<si32, si8> > heroSecSkills; //may be empty; pairs <id, level>, level [0-3]
std::set<SpellID> spells;
2011-01-21 04:36:30 +02:00
SideSettings();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stacks & heroId & heroPrimSkills & artifacts & heroSecSkills & spells;
2011-01-21 04:36:30 +02:00
}
} sides[2];
std::vector<shared_ptr<CObstacleInstance> > obstacles;
static DuelParameters fromJSON(const std::string &fname);
struct CusomCreature
{
int id;
int attack, defense, dmg, HP, speed, shoots;
CusomCreature()
{
id = attack = defense = dmg = HP = speed = shoots = -1;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & attack & defense & dmg & HP & speed & shoots;
}
};
std::vector<CusomCreature> creatures;
2011-01-21 04:36:30 +02:00
DuelParameters();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & terType & bfieldType & sides & obstacles & creatures;
2011-01-21 04:36:30 +02:00
}
};
class CPathfinder : private CGameInfoCallback
{
private:
bool useSubterraneanGates;
bool allowEmbarkAndDisembark;
CPathsInfo &out;
const CGHeroInstance *hero;
const std::vector<std::vector<std::vector<ui8> > > &FoW;
std::list<CGPathNode*> mq; //BFS queue -> nodes to be checked
int3 curPos;
CGPathNode *cp; //current (source) path node -> we took it from the queue
CGPathNode *dp; //destination node -> it's a neighbour of cp that we consider
const TerrainTile *ct, *dt; //tile info for both nodes
ui8 useEmbarkCost; //0 - usual movement; 1 - embark; 2 - disembark
int destTopVisObjID;
CGPathNode *getNode(const int3 &coord);
void initializeGraph();
bool goodForLandSeaTransition(); //checks if current move will be between sea<->land. If so, checks it legality (returns false if movement is not possible) and sets useEmbarkCost
CGPathNode::EAccessibility evaluateAccessibility(const TerrainTile *tinfo) const;
bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
public:
CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance *_hero);
void calculatePaths(int3 src = int3(-1,-1,-1), int movement = -1); //calculates possible paths for hero, by default uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
};
2011-01-21 04:36:30 +02:00
2011-05-04 05:38:58 +03:00
struct BattleInfo;
class DLL_LINKAGE EVictoryLossCheckResult
{
public:
static EVictoryLossCheckResult victory(std::string toSelf, std::string toOthers);
static EVictoryLossCheckResult defeat(std::string toSelf, std::string toOthers);
EVictoryLossCheckResult();
bool operator==(EVictoryLossCheckResult const & other) const;
bool operator!=(EVictoryLossCheckResult const & other) const;
bool victory() const;
bool loss() const;
EVictoryLossCheckResult invert();
std::string messageToSelf;
std::string messageToOthers;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & intValue & messageToSelf & messageToOthers;
}
private:
enum EResult
{
DEFEAT = -1,
INGAME = 0,
VICTORY= +1
};
EVictoryLossCheckResult(si32 intValue, std::string toSelf, std::string toOthers);
si32 intValue; // uses EResult
};
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult);
class DLL_LINKAGE CGameState : public CNonConstInfoCallback
{
2009-03-07 00:11:17 +02:00
public:
struct DLL_LINKAGE HeroesPool
{
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > heroesPool; //[subID] - heroes available to buy; nullptr if not available
std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero (binary flags)
CGHeroInstance * pickHeroFor(bool native, PlayerColor player, const CTown *town,
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, CRandomGenerator & rand, const CHeroClass *bannedClass = nullptr) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & heroesPool & pavailable;
}
} hpool; //we have here all heroes available on this map that are not hired
2013-12-18 21:18:12 +03:00
CGameState();
virtual ~CGameState();
void init(StartInfo * si);
2013-12-18 21:18:12 +03:00
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
PlayerColor currentPlayer; //ID of player currently having turn
ConstTransitivePtr<BattleInfo> curB; //current battle
ui32 day; //total number of days in game
ConstTransitivePtr<CMap> map;
std::map<PlayerColor, PlayerState> players;
std::map<TeamID, TeamState> teams;
CBonusSystemNode globalEffects;
boost::shared_mutex *mx;
void giveHeroArtifact(CGHeroInstance *h, ArtifactID aid);
2012-02-17 22:30:40 +03:00
2009-03-07 00:25:19 +02:00
void apply(CPack *pack);
BFieldType battleGetBattlefieldType(int3 tile);
2010-07-15 06:04:57 +03:00
UpgradeInfo getUpgradeInfo(const CStackInstance &stack);
2013-03-03 20:06:03 +03:00
PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2);
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1); //calculates possible paths for hero, by default uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
int3 guardingCreaturePosition (int3 pos) const;
std::vector<CGObjectInstance*> guardingCreatures (int3 pos) const;
// ----- victory, loss condition checks -----
EVictoryLossCheckResult checkForVictoryAndLoss(PlayerColor player) const;
bool checkForVictory(PlayerColor player, const EventCondition & condition) const; //checks if given player is winner
PlayerColor checkForStandardWin() const; //returns color of player that accomplished standard victory conditions or 255 (NEUTRAL) if no winner
bool checkForStandardLoss(PlayerColor player) const; //checks if given player lost the game
void obtainPlayersStats(SThievesGuildInfo & tgi, int level); //fills tgi with info about other players that is available at given level of thieves' guild
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > unusedHeroesFromPool(); //heroes pool without heroes that are available in taverns
BattleInfo * setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town);
2013-03-03 20:06:03 +03:00
bool isVisible(int3 pos, PlayerColor player);
bool isVisible(const CGObjectInstance *obj, boost::optional<PlayerColor> player);
2010-07-10 05:15:49 +03:00
void getNeighbours(const TerrainTile &srct, int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand, bool limitCoastSailing);
int getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, bool flying, int remainingMovePoints=-1, bool checkLast=true);
int getDate(Date::EDateType mode=Date::DAY) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
2013-12-18 21:18:12 +03:00
// ----- getters, setters -----
CRandomGenerator & getRandomGenerator();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & scenarioOps & initialOpts & currentPlayer & day & map & players & teams & hpool & globalEffects & rand;
BONUS_TREE_DESERIALIZATION_FIX
}
private:
struct CrossoverHeroesList
{
std::vector<CGHeroInstance *> heroesFromPreviousScenario, heroesFromAnyPreviousScenarios;
void addHeroToBothLists(CGHeroInstance * hero);
void removeHeroFromBothLists(CGHeroInstance * hero);
};
struct CampaignHeroReplacement
{
CampaignHeroReplacement(CGHeroInstance * hero, ObjectInstanceID heroPlaceholderId);
CGHeroInstance * hero;
ObjectInstanceID heroPlaceholderId;
};
// ----- initialization -----
2013-12-18 21:18:12 +03:00
void initNewGame();
void initCampaign();
void initDuel();
void checkMapChecksum();
void initGrailPosition();
void initRandomFactionsForPlayers();
void randomizeMapObjects();
void randomizeObject(CGObjectInstance *cur);
void initPlayerStates();
void placeCampaignHeroes();
CrossoverHeroesList getCrossoverHeroesFromPreviousScenarios() const;
2014-01-03 19:36:22 +03:00
/// returns heroes and placeholders in where heroes will be put
std::vector<CampaignHeroReplacement> generateCampaignHeroesToReplace(CrossoverHeroesList & crossoverHeroes);
/// gets prepared and copied hero instances with crossover heroes from prev. scenario and travel options from current scenario
void prepareCrossoverHeroes(std::vector<CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const;
void replaceHeroesPlaceholders(const std::vector<CampaignHeroReplacement> & campaignHeroReplacements);
2013-12-18 21:18:12 +03:00
void placeStartingHeroes();
void placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeId, int3 townPos);
2013-12-18 21:18:12 +03:00
void initStartingResources();
void initHeroes();
void giveCampaignBonusToHero(CGHeroInstance * hero);
void initFogOfWar();
void initStartingBonus();
void initTowns();
void initMapObjects();
void initVisitingAndGarrisonedHeroes();
// ----- bonus system handling -----
2013-12-18 21:18:12 +03:00
void buildBonusSystemTree();
void attachArmedObjects();
void buildGlobalTeamPlayerTree();
void deserializationFix();
// ---- misc helpers -----
CGHeroInstance * getUsedHero(HeroTypeID hid) const;
2013-12-18 21:18:12 +03:00
bool isUsedHero(HeroTypeID hid) const; //looks in heroes and prisons
std::set<HeroTypeID> getUnusedAllowedHeroes(bool alsoIncludeNotAllowed = false) const;
std::pair<Obj,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
int pickUnusedHeroTypeRandomly(PlayerColor owner); // picks a unused hero type randomly
int pickNextHeroType(PlayerColor owner); // picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
// ---- data -----
CRandomGenerator rand;
2013-12-18 21:18:12 +03:00
friend class CCallback;
friend class CClient;
friend class IGameCallback;
friend class CMapHandler;
friend class CGameHandler;
};
struct DLL_LINKAGE QuestInfo //universal interface for human and AI
{
const CQuest * quest;
const CGObjectInstance * obj; //related object, most likely Seer Hut
int3 tile;
QuestInfo(){};
2012-07-08 11:42:03 +03:00
QuestInfo (const CQuest * Quest, const CGObjectInstance * Obj, int3 Tile) :
quest (Quest), obj (Obj), tile (Tile){};
//FIXME: assignment operator should return QuestInfo &
bool operator= (const QuestInfo &qi)
{
quest = qi.quest;
obj = qi.obj;
tile = qi.tile;
return true;
}
bool operator== (const QuestInfo & qi) const
{
return (quest == qi.quest && obj == qi.obj);
}
//std::vector<std::string> > texts //allow additional info for quest log?
template <typename Handler> void serialize(Handler &h, const int version)
{
h & quest & obj & tile;
}
};