#ifndef __CGAMESTATE_H__ #define __CGAMESTATE_H__ #include "global.h" #ifndef _MSC_VER #include "hch/CCreatureHandler.h" #include "lib/VCMI_Lib.h" #include "map.h" #endif #include #include #ifdef _WIN32 #include #else #include "tchar_amigaos4.h" #endif class CTown; class CScriptCallback; class CCallback; class CLuaCallback; class CCPPObjectScript; class CCreatureSet; class CStack; class CGHeroInstance; class CGTownInstance; class CArmedInstance; class CGDefInfo; class CObjectScript; class CGObjectInstance; class CCreature; struct Mapa; struct StartInfo; struct SDL_Surface; class CMapHandler; class CPathfinder; struct IPack; struct SetObjectProperty; struct MetaString; std::string DLL_EXPORT toString(MetaString &ms); namespace boost { class shared_mutex; } struct DLL_EXPORT PlayerState { public: ui8 color, serial; ui32 currentSelection; //id of hero/town, 0xffffffff if none std::vector > > fogOfWarMap; //true - visible, false - hidden std::vector resources; std::vector heroes; std::vector towns; std::vector availableHeroes; //heroes available in taverns PlayerState():color(-1),currentSelection(0xffffffff){}; template void serialize(Handler &h, const int version) { h & color & serial & currentSelection & fogOfWarMap & resources; ui32 size; if(h.saving) //write subids of available heroes { size = availableHeroes.size(); h & size; for(size_t i=0; i < size; i++) h & availableHeroes[i]->subID; } else { ui32 hid; h & size; for(size_t i=0; i < size; i++) { //fill availableHeroes with dummy hero instances, holding subids h & hid; availableHeroes.push_back(new CGHeroInstance); availableHeroes[availableHeroes.size()-1]->subID = hid; } } } }; struct DLL_EXPORT BattleInfo { ui8 side1, side2; si32 round, activeStack; ui8 siege; // = 0 ordinary battle = 1 a siege with a Fort = 2 a siege with a Citadel = 3 a siege with a Castle int3 tile; //for background and bonuses si32 hero1, hero2; CCreatureSet army1, army2; std::vector stacks; template void serialize(Handler &h, const int version) { h & side1 & side2 & round & activeStack & siege & tile & stacks & army1 & army2 & hero1 & hero2; } CStack * getNextStack(); //which stack will have turn after current one std::vector getStackQueue(); //returns stack in order of their movement action CStack * getStack(int stackID); CStack * getStackT(int tileID); void getAccessibilityMap(bool *accessibility, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes void getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit=-1, bool addOccupiable = false); //send pointer to at least 187 allocated bytes void makeBFS(int start, bool*accessibility, int *predecessor, int *dists); //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result std::vector getPath(int start, int dest, bool*accessibility); std::vector getAccessibility(int stackID, bool addOccupiable); //returns vector of accessible tiles (taking into account the creature range) bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they're distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left) static std::vector neighbouringTiles(int hex); static int calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting); //TODO: add additional conditions and require necessary data void calculateCasualties(std::set > *casualties); }; class DLL_EXPORT CStack { public: ui32 ID; //unique ID of stack CCreature * creature; ui32 amount, baseAmount; ui32 firstHPleft; //HP of first creature in stack ui8 owner, slot; //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures) ui8 attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle) ui16 position; //position on battlefield ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1) si16 shots; //how many shots left si8 morale, luck; //base stack luck/morale std::set abilities; std::set state; struct StackEffect { ui16 id; //spell id ui8 level; //skill level ui16 turnsRemain; template void serialize(Handler &h, const int version) { h & id & level & turnsRemain; } }; std::vector effects; CStack(CCreature * C, int A, int O, int I, bool AO, int S); CStack() : creature(NULL),amount(-1),owner(255), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1), slot(255), baseAmount(-1), counterAttacks(1), effects(), state(), abilities(){} const StackEffect * getEffect(ui16 id) const; //effect id (SP) ui32 speed() const; si8 Morale() const; si8 Luck() const; template void save(Handler &h, const int version) { h & creature->idNumber; } template void load(Handler &h, const int version) { ui32 id; h & id; creature = &VLC->creh->creatures[id]; abilities = creature->abilities; } template void serialize(Handler &h, const int version) { h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks & shots & morale & luck; if(h.saving) save(h,version); else load(h,version); } bool alive() const { return vstd::contains(state,ALIVE); } }; struct UpgradeInfo { int oldID; //creature to be upgraded std::vector newID; //possible upgrades std::vector > > cost; // cost[upgrade_serial] -> set of pairs UpgradeInfo(){oldID = -1;}; }; class DLL_EXPORT CGameState { private: StartInfo* scenarioOps; ui32 seed; ui8 currentPlayer; //ID of player currently having turn BattleInfo *curB; //current battle ui32 day; //total number of days in game Mapa * map; std::map players; //ID <-> player state std::map villages, forts, capitols; //def-info for town graphics std::vector resVals; struct DLL_EXPORT HeroesPool { std::map heroesPool; //[subID] - heroes available to buy; NULL if not available std::map pavailable; // [subid] -> which players can recruit hero CGHeroInstance * pickHeroFor(bool native, int player, const CTown *town, int notThatOne=-1); 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, Mapa * map, int Seed); void loadTownDInfos(); void applyNL(IPack * pack); void setObjProperty( SetObjectProperty * p ); void apply(IPack * pack); void randomizeObject(CGObjectInstance *cur); std::pair pickObject(CGObjectInstance *obj); int pickHero(int owner); CGHeroInstance *getHero(int objid); CGTownInstance *getTown(int objid); bool battleMoveCreatureStack(int ID, int dest); bool battleAttackCreatureStack(int ID, int dest); bool battleShootCreatureStack(int ID, int dest); int battleGetStack(int pos); //returns ID of stack at given tile UpgradeInfo getUpgradeInfo(CArmedInstance *obj, int stackPos); float getMarketEfficiency(int player, int mode=0); std::set tilesToReveal(int3 pos, int radious, int player) const; //if player==-1 => adds all tiles in radious public: CGameState(); ~CGameState(); int getDate(int mode=0) 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 & seed & currentPlayer & day & map & players & resVals & hpool; if(!h.saving) { loadTownDInfos(); //recreating towns/heroes vectors in players entries for(int i=0; itowns.size(); i++) if(map->towns[i]->tempOwner < PLAYER_LIMIT) players[map->towns[i]->tempOwner].towns.push_back(map->towns[i]); for(int i=0; iheroes.size(); i++) if(map->heroes[i]->tempOwner < PLAYER_LIMIT) players[map->heroes[i]->tempOwner].heroes.push_back(map->heroes[i]); //recreating available heroes for(std::map::iterator i=players.begin(); i!=players.end(); i++) { for(size_t j=0; j < i->second.availableHeroes.size(); j++) { ui32 hlp = i->second.availableHeroes[j]->subID; delete i->second.availableHeroes[j]; i->second.availableHeroes[j] = hpool.heroesPool[hlp]; } } } } friend class CCallback; friend class CPathfinder;; friend class CLuaCallback; friend class CClient; friend void initGameState(Mapa * map, CGameInfo * cgi); friend class IGameCallback; friend class CMapHandler; friend class CGameHandler; }; #endif // __CGAMESTATE_H__