#pragma once //#ifndef _MSC_VER #include "CCreatureHandler.h" #include "VCMI_Lib.h" #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 "IGameCallback.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 CScriptCallback; class CCallback; class IGameCallback; class CLuaCallback; class CCPPObjectScript; 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; struct CPack; class CSpell; struct TerrainTile; class CHeroClass; class CCampaign; class CCampaignState; class IModableArt; class CGGarrison; class CGameInfo; struct QuestInfo; class CQuest; 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) struct ArmyDescriptor : public std::map { 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 { ui8 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 { private: void assign(const InfoAboutHero & iah); public: struct DLL_LINKAGE Details { std::vector primskills; si32 mana, luck, morale; } *details; const CHeroClass *hclass; int portrait; InfoAboutHero(); InfoAboutHero(const InfoAboutHero & iah); InfoAboutHero(const CGHeroInstance *h, bool detailed); ~InfoAboutHero(); InfoAboutHero & operator=(const InfoAboutHero & iah); void initFromHero(const CGHeroInstance *h, bool detailed); }; /// Struct which holds a int information about a town struct DLL_LINKAGE InfoAboutTown : public InfoAboutArmy { struct DLL_LINKAGE Details { si32 hallLevel, goldIncome; bool customRes; bool garrisonedHero; } *details; CTown *tType; si32 built; si32 fortLevel; //0 - none InfoAboutTown(); InfoAboutTown(const CGTownInstance *t, bool detailed); ~InfoAboutTown(); void initFromTown(const CGTownInstance *t, bool detailed); }; // typedef si32 TResourceUnit; // typedef std::vector TResourceVector; // typedef std::set TResourceSet; struct DLL_LINKAGE SThievesGuildInfo { std::vector playerColors; //colors of players that are in-game std::vector< std::vector< TPlayerColor > > numOfTowns, numOfHeroes, gold, woodOre, mercSulfCrystGems, obelisks, artifacts, army, income; // [place] -> [colours of players] std::map colorToBestHero; //maps player's color to his best heros' std::map personality; // color to personality // ai tactic std::map bestCreature; // color to ID // id or -1 if not known // template void serialize(Handler &h, const int version) // { // h & playerColors & numOfTowns & numOfHeroes & gold & woodOre & mercSulfCrystGems & obelisks & artifacts & army & income; // h & colorToBestHero & personality & bestCreature; // } }; struct DLL_LINKAGE PlayerState : public CBonusSystemNode { public: enum EStatus {WRONG = -1, INGAME, LOSER, WINNER}; TPlayerColor color; ui8 human; //true if human controlled player, false for AI ui32 currentSelection; //id of hero/town, 0xffffffff if none ui8 team; TResources resources; std::vector > heroes; std::vector > towns; std::vector > availableHeroes; //heroes available in taverns std::vector > dwellings; //used for town growth std::vector quests; //store info about all received quests ui8 enteredWinningCheatCode, enteredLosingCheatCode; //if true, this player has entered cheat codes for loss / victory EStatus status; ui8 daysWithoutCastle; PlayerState(); std::string nodeName() const OVERRIDE; //override //void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; //void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const; template void serialize(Handler &h, const int version) { h & color & human & currentSelection & team & resources & status; h & heroes & towns & availableHeroes & dwellings; h & getBonusList(); //FIXME FIXME FIXME h & status & daysWithoutCastle; h & enteredLosingCheatCode & enteredWinningCheatCode; h & static_cast(*this); } }; struct DLL_LINKAGE TeamState : public CBonusSystemNode { public: ui8 id; //position in gameState::teams std::set players; // members of this team std::vector > > fogOfWarMap; //true - visible, false - hidden TeamState(); template void serialize(Handler &h, const int version) { h & id & players & fogOfWarMap; h & static_cast(*this); } }; struct UpgradeInfo { CreatureID::CreatureID oldID; //creature to be upgraded std::vector newID; //possible upgrades std::vector cost; // cost[upgrade_serial] -> set of pairs; 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; ui32 moveRemains; CGPathNode * theNodeBefore; int3 coord; //coordinates CGPathNode(); bool reachable() const; }; struct DLL_LINKAGE CGPath { std::vector 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 { 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 { ETerrainType::ETerrainType terType; BFieldType::BFieldType bfieldType; struct DLL_EXPORT SideSettings { struct DLL_EXPORT StackSettings { CreatureID::CreatureID type; si32 count; template void serialize(Handler &h, const int version) { h & type & count; } StackSettings(); StackSettings(CreatureID::CreatureID Type, si32 Count); } stacks[GameConstants::ARMY_SIZE]; si32 heroId; //-1 if none std::vector heroPrimSkills; //may be empty std::map artifacts; std::vector > heroSecSkills; //may be empty; pairs , level [0-3] std::set spells; SideSettings(); template void serialize(Handler &h, const int version) { h & stacks & heroId & heroPrimSkills & artifacts & heroSecSkills & spells; } } sides[2]; std::vector > 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 void serialize(Handler &h, const int version) { h & id & attack & defense & dmg & HP & speed & shoots; } }; std::vector creatures; DuelParameters(); template void serialize(Handler &h, const int version) { h & terType & bfieldType & sides & obstacles & creatures; } }; class CPathfinder : private CGameInfoCallback { private: bool useSubterraneanGates; bool allowEmbarkAndDisembark; CPathsInfo &out; const CGHeroInstance *hero; const std::vector > > &FoW; std::list 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 NULL if path does not exists }; struct BattleInfo; class DLL_LINKAGE CGameState : public CNonConstInfoCallback { public: ConstTransitivePtr scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized) TPlayerColor currentPlayer; //ID of player currently having turn ConstTransitivePtr curB; //current battle ui32 day; //total number of days in game ConstTransitivePtr map; bmap players; bmap teams; CBonusSystemNode globalEffects; bmap ongoingVisits; struct DLL_LINKAGE HeroesPool { bmap > heroesPool; //[subID] - heroes available to buy; NULL if not available bmap pavailable; // [subid] -> which players can recruit hero (binary flags) CGHeroInstance * pickHeroFor(bool native, TPlayerColor player, const CTown *town, bmap > &available, const CHeroClass *bannedClass = NULL) const; template void serialize(Handler &h, const int version) { h & heroesPool & pavailable; } } hpool; //we have here all heroes available on this map that are not hired boost::shared_mutex *mx; void init(StartInfo * si); void initDuel(); void randomizeObject(CGObjectInstance *cur); std::pair pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns int pickHero(int owner); void giveHeroArtifact(CGHeroInstance *h, int aid); void apply(CPack *pack); BFieldType::BFieldType battleGetBattlefieldType(int3 tile) const; UpgradeInfo getUpgradeInfo(const CStackInstance &stack); PlayerRelations::PlayerRelations getPlayerRelations(TPlayerColor color1, TPlayerColor color2); bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile bool checkForVisitableDir(const int3 & src, const TerrainTile *pom, 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 NULL if path does not exists int3 guardingCreaturePosition (int3 pos) const; std::vector guardingCreatures (int3 pos) const; int victoryCheck(TPlayerColor player) const; //checks if given player is winner; -1 if std victory, 1 if special victory, 0 else int lossCheck(TPlayerColor player) const; //checks if given player is loser; -1 if std loss, 1 if special, 0 else ui8 checkForStandardWin() const; //returns color of player that accomplished standard victory conditions or 255 if no winner bool checkForStandardLoss(TPlayerColor 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 bmap > 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); void buildBonusSystemTree(); void attachArmedObjects(); void buildGlobalTeamPlayerTree(); void deserializationFix(); bool isVisible(int3 pos, TPlayerColor player); bool isVisible(const CGObjectInstance *obj, int player); CGameState(); //c-tor virtual ~CGameState(); //d-tor void getNeighbours(const TerrainTile &srct, int3 tile, std::vector &vec, const boost::logic::tribool &onLand, bool limitCoastSailing); int getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, 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 template void serialize(Handler &h, const int version) { h & scenarioOps & initialOpts & currentPlayer & day & map & players & teams & hpool & globalEffects; BONUS_TREE_DESERIALIZATION_FIX } friend class CCallback; friend class CLuaCallback; friend class CClient; friend void initGameState(CMap * map, CGameInfo * cgi); 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(){}; QuestInfo (const CQuest * Quest, const CGObjectInstance * Obj, int3 Tile) : quest (Quest), obj (Obj), tile (Tile){}; 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 > texts //allow additional info for quest log? template void serialize(Handler &h, const int version) { h & quest & obj & tile; } };