From 4a8ae4ed9accb7a62ef5b78ecf835343d0ed24ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Sat, 27 Dec 2008 01:01:59 +0000 Subject: [PATCH] * restored objects functionalities (hopefully working) * new file in vcmi lib: IGameCallback.cpp --- CAdvmapInterface.h | 353 ++++++++-------- CCallback.cpp | 5 +- CGameState.cpp | 132 +++++- CGameState.h | 452 ++++++++++---------- CPlayerInterface.cpp | 4 +- ChangeLog | 20 +- client/Client.cpp | 105 ++--- client/Client.h | 150 ++++--- config/settings.txt | 2 +- hch/CObjectHandler.cpp | 420 +++++++++++++++++-- hch/CObjectHandler.h | 892 ++++++++++++++++++++-------------------- lib/IGameCallback.cpp | 36 ++ lib/IGameCallback.h | 112 ++--- lib/NetPacks.h | 14 +- lib/VCMI_lib.vcproj | 4 + map.cpp | 531 ++++++------------------ map.h | 782 +++++++++++++++++------------------ server/CGameHandler.cpp | 65 +-- server/CGameHandler.h | 340 ++++++++------- 19 files changed, 2316 insertions(+), 2103 deletions(-) create mode 100644 lib/IGameCallback.cpp diff --git a/CAdvmapInterface.h b/CAdvmapInterface.h index a7599208d..f1f13a282 100644 --- a/CAdvmapInterface.h +++ b/CAdvmapInterface.h @@ -1,177 +1,176 @@ -#ifndef __CADVMAPINTERFACE_H__ -#define __CADVMAPINTERFACE_H__ -#include -#include "global.h" -#include "SDL.h" -#include "CPlayerInterface.h" -#include -#include "AdventureMapButton.h" -class CDefHandler; -class CCallback; -struct CPath; -class CAdvMapInt; -class CGHeroInstance; -class CGTownInstance; -class CHeroWindow; -/*****************************/ -class CMinimap - : public ClickableL, public ClickableR, public Hoverable, public MotionInterested, public virtual CIntObject -{ -public: - SDL_Surface * radar; - SDL_Surface * temps; - std::map colors; - std::map colorsBlocked; - std::vector map, FoW; //one bitmap for each level (terrain, Fog of War) - //TODO flagged buildings - std::string statusbarTxt, rcText; - - CMinimap(bool draw=true); - void draw(); - void redraw(int level=-1);// (level==-1) => redraw all levels - void updateRadar(); - - void clickRight (tribool down); - void clickLeft (tribool down); - void hover (bool on); - void mouseMoved (const SDL_MouseMotionEvent & sEvent); - void activate(); // makes button active - void deactivate(); // makes button inactive (but don't deletes) - void hideTile(const int3 &pos); //puts FoW - void showTile(const int3 &pos); //removes FoW -}; -class CTerrainRect - : public ClickableL, public ClickableR, public Hoverable, public MotionInterested -{ -public: - int tilesw, tilesh; //width and height of terrain to blit in tiles - int3 curHoveredTile; - int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels) - - CDefHandler * arrows; - CTerrainRect(); - CPath * currentPath; - void activate(); - void deactivate(); - void clickLeft(tribool down); - void clickRight(tribool down); - void hover(bool on); - void mouseMoved (const SDL_MouseMotionEvent & sEvent); - void show(); - void showPath(); - int3 whichTileIsIt(const int & x, const int & y); //x,y are cursor position - int3 whichTileIsIt(); //uses current cursor pos -}; -class CResDataBar - :public ClickableR, public virtual CIntObject -{ -public: - SDL_Surface * bg; - std::vector > txtpos; - std::string datetext; - - void clickRight (tribool down); - void activate(); - void deactivate(); - CResDataBar(); - CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist); - ~CResDataBar(); - - void draw(); -}; -class CInfoBar - :public virtual CIntObject, public TimeInterested -{ -public: - CDefHandler *day, *week1, *week2, *week3, *week4; - SComponent * current; - int mode; - int pom; - - CInfoBar(); - ~CInfoBar(); - void newDay(int Day); - void showComp(SComponent * comp, int time=5000); - void tick(); - void draw(const CGObjectInstance * specific=NULL); // if specific==0 function draws info about selected hero/town - void blitAnim(int mode);//0 - day, 1 - week - CDefHandler * getAnim(int mode); -}; -/*****************************/ -class CAdvMapInt : public CMainInterface, public KeyInterested //adventure map interface -{ -public: - CAdvMapInt(int Player); - ~CAdvMapInt(); - - int3 position; //top left corner of visible map part - int player; - - std::vector gems; - - bool scrollingLeft ; - bool scrollingRight ; - bool scrollingUp ; - bool scrollingDown ; - bool updateScreen, updateMinimap ; - unsigned char anim, animValHitCount; //animation frame - unsigned char heroAnim, heroAnimValHitCount; //animation frame - - CMinimap minimap; - - - SDL_Surface * bg; - AdventureMapButton kingOverview,//- kingdom overview - underground,//- underground switch - questlog,//- questlog - sleepWake, //- sleep/wake hero - moveHero, //- move hero - spellbook,//- spellbook - advOptions, //- adventure options - sysOptions,//- system options - nextHero, //- next hero - endTurn;//- end turn - //CHeroList herolist; - - CTerrainRect terrain; //visible terrain - - CStatusBar statusbar; - CResDataBar resdatabar; - - CHeroList heroList; - CTownList townList; - CInfoBar infoBar; - - CHeroWindow * heroWindow; - - const CArmedInstance *selection; - - //fuctions binded to buttons - void fshowOverview(); - void fswitchLevel(); - void fshowQuestlog(); - void fsleepWake(); - void fmoveHero(); - void fshowSpellbok(); - void fadventureOPtions(); - void fsystemOptions(); - void fnextHero(); - void fendTurn(); - - void activate(); - void deactivate(); - - void show(SDL_Surface * to=NULL); //shows and activates adv. map interface - void hide(); //deactivates advmap interface - void update(); //redraws terrain - - void select(const CArmedInstance *sel); - void selectionChanged(); - void centerOn(int3 on); - int3 verifyPos(int3 ver); - void handleRightClick(std::string text, tribool down, CIntObject * client); - void keyPressed(const SDL_KeyboardEvent & key); - - -}; -#endif // __CADVMAPINTERFACE_H__ +#ifndef __CADVMAPINTERFACE_H__ +#define __CADVMAPINTERFACE_H__ +#include +#include "global.h" +#include "SDL.h" +#include "CPlayerInterface.h" +#include +#include "AdventureMapButton.h" +class CDefHandler; +class CCallback; +struct CPath; +class CAdvMapInt; +class CGHeroInstance; +class CGTownInstance; +class CHeroWindow; +/*****************************/ +class CMinimap + : public ClickableL, public ClickableR, public Hoverable, public MotionInterested, public virtual CIntObject +{ +public: + SDL_Surface * radar; + SDL_Surface * temps; + std::map colors; + std::map colorsBlocked; + std::vector map, FoW; //one bitmap for each level (terrain, Fog of War) + std::string statusbarTxt, rcText; + + CMinimap(bool draw=true); + void draw(); + void redraw(int level=-1);// (level==-1) => redraw all levels + void updateRadar(); + + void clickRight (tribool down); + void clickLeft (tribool down); + void hover (bool on); + void mouseMoved (const SDL_MouseMotionEvent & sEvent); + void activate(); // makes button active + void deactivate(); // makes button inactive (but don't deletes) + void hideTile(const int3 &pos); //puts FoW + void showTile(const int3 &pos); //removes FoW +}; +class CTerrainRect + : public ClickableL, public ClickableR, public Hoverable, public MotionInterested +{ +public: + int tilesw, tilesh; //width and height of terrain to blit in tiles + int3 curHoveredTile; + int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels) + + CDefHandler * arrows; + CTerrainRect(); + CPath * currentPath; + void activate(); + void deactivate(); + void clickLeft(tribool down); + void clickRight(tribool down); + void hover(bool on); + void mouseMoved (const SDL_MouseMotionEvent & sEvent); + void show(); + void showPath(); + int3 whichTileIsIt(const int & x, const int & y); //x,y are cursor position + int3 whichTileIsIt(); //uses current cursor pos +}; +class CResDataBar + :public ClickableR, public virtual CIntObject +{ +public: + SDL_Surface * bg; + std::vector > txtpos; + std::string datetext; + + void clickRight (tribool down); + void activate(); + void deactivate(); + CResDataBar(); + CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist); + ~CResDataBar(); + + void draw(); +}; +class CInfoBar + :public virtual CIntObject, public TimeInterested +{ +public: + CDefHandler *day, *week1, *week2, *week3, *week4; + SComponent * current; + int mode; + int pom; + + CInfoBar(); + ~CInfoBar(); + void newDay(int Day); + void showComp(SComponent * comp, int time=5000); + void tick(); + void draw(const CGObjectInstance * specific=NULL); // if specific==0 function draws info about selected hero/town + void blitAnim(int mode);//0 - day, 1 - week + CDefHandler * getAnim(int mode); +}; +/*****************************/ +class CAdvMapInt : public CMainInterface, public KeyInterested //adventure map interface +{ +public: + CAdvMapInt(int Player); + ~CAdvMapInt(); + + int3 position; //top left corner of visible map part + int player; + + std::vector gems; + + bool scrollingLeft ; + bool scrollingRight ; + bool scrollingUp ; + bool scrollingDown ; + bool updateScreen, updateMinimap ; + unsigned char anim, animValHitCount; //animation frame + unsigned char heroAnim, heroAnimValHitCount; //animation frame + + CMinimap minimap; + + + SDL_Surface * bg; + AdventureMapButton kingOverview,//- kingdom overview + underground,//- underground switch + questlog,//- questlog + sleepWake, //- sleep/wake hero + moveHero, //- move hero + spellbook,//- spellbook + advOptions, //- adventure options + sysOptions,//- system options + nextHero, //- next hero + endTurn;//- end turn + //CHeroList herolist; + + CTerrainRect terrain; //visible terrain + + CStatusBar statusbar; + CResDataBar resdatabar; + + CHeroList heroList; + CTownList townList; + CInfoBar infoBar; + + CHeroWindow * heroWindow; + + const CArmedInstance *selection; + + //fuctions binded to buttons + void fshowOverview(); + void fswitchLevel(); + void fshowQuestlog(); + void fsleepWake(); + void fmoveHero(); + void fshowSpellbok(); + void fadventureOPtions(); + void fsystemOptions(); + void fnextHero(); + void fendTurn(); + + void activate(); + void deactivate(); + + void show(SDL_Surface * to=NULL); //shows and activates adv. map interface + void hide(); //deactivates advmap interface + void update(); //redraws terrain + + void select(const CArmedInstance *sel); + void selectionChanged(); + void centerOn(int3 on); + int3 verifyPos(int3 ver); + void handleRightClick(std::string text, tribool down, CIntObject * client); + void keyPressed(const SDL_KeyboardEvent & key); + + +}; +#endif // __CADVMAPINTERFACE_H__ diff --git a/CCallback.cpp b/CCallback.cpp index a3870229c..b7f6364ac 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -648,7 +648,10 @@ void CCallback::setFormation(const CGHeroInstance * hero, bool tight) void CCallback::setSelection(const CArmedInstance * obj) { - *cl->serv << ui16(514) << obj->id; + SetSelection ss; + ss.player = player; + ss.id = obj->id; + *cl->serv << ui16(514) << ss; } void CCallback::recruitHero(const CGTownInstance *town, const CGHeroInstance *hero) diff --git a/CGameState.cpp b/CGameState.cpp index 74580f586..ce96cbebe 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -6,6 +6,7 @@ #include #include "hch/CDefObjInfoHandler.h" #include "hch/CArtHandler.h" +#include "hch/CGeneralTextHandler.h" #include "hch/CTownHandler.h" #include "hch/CSpellHandler.h" #include "hch/CHeroHandler.h" @@ -28,6 +29,79 @@ boost::rand48 ran; #undef max #endif +std::string DLL_EXPORT toString(MetaString &ms) +{ + std::string ret; + for(size_t i=0;i0) + { + ret += ms.strings[ms.message[i]-1]; + } + else + { + std::vector *vec; + int type = ms.texts[-ms.message[i]-1].first, + ser = ms.texts[-ms.message[i]-1].second; + if(type == 5) + { + ret += VLC->arth->artifacts[ser].Name(); + continue; + } + else if(type == 7) + { + ret += VLC->creh->creatures[ser].namePl; + continue; + } + else if(type == 9) + { + ret += VLC->objh->mines[ser].first; + continue; + } + else if(type == 10) + { + ret += VLC->objh->mines[ser].second; + continue; + } + else + { + switch(type) + { + case 1: + vec = &VLC->generaltexth->allTexts; + break; + case 2: + vec = &VLC->objh->xtrainfo; + break; + case 3: + vec = &VLC->objh->names; + break; + case 4: + vec = &VLC->objh->restypes; + break; + case 6: + vec = &VLC->generaltexth->arraytxt; + break; + case 8: + vec = &VLC->objh->creGens; + break; + case 11: + vec = &VLC->objh->advobtxt; + break; + case 12: + vec = &VLC->generaltexth->artifEvents; + break; + } + ret += (*vec)[ser]; + } + } + } + for(size_t i=0; i < ms.replacements.size(); ++i) + { + ret.replace(ret.find("%s"),2,ms.replacements[i]); + } + return ret; +} CGObjectInstance * createObject(int id, int subid, int3 pos, int owner) { @@ -624,6 +698,12 @@ void CGameState::applyNL(IPack * pack) h->artifWorn = sha->artifWorn; break; } + case 514: + { + SetSelection *ss = static_cast(pack); + players[ss->player].currentSelection = ss->id; + break; + } case 515: { HeroRecruited *sha = static_cast(pack); @@ -652,23 +732,13 @@ void CGameState::applyNL(IPack * pack) case 1001://set object property { SetObjectProperty *p = static_cast(pack); - if(p->what == 3) //set creatures amount - { - tlog5 << "Setting creatures amount in " << p->id << std::endl; - static_cast(map->objects[p->id])->army.slots[0].second = p->val; - break; - } - ui8 CGObjectInstance::*point; - switch(p->what) - { - case 1: - point = &CGObjectInstance::tempOwner; - break; - case 2: - point = &CGObjectInstance::blockVisit; - break; - } - map->objects[p->id]->*point = p->val; + setObjProperty(p); + break; + } + case 1002: + { + SetHoverName *shn = static_cast(pack); + map->objects[shn->id]->hoverName = toString(shn->name); break; } case 2000: @@ -1381,6 +1451,9 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed) } } } + + for(int i=0; iobjects.size(); i++) + map->objects[i]->initObj(); } bool CGameState::battleShootCreatureStack(int ID, int dest) @@ -1498,6 +1571,31 @@ void CGameState::loadTownDInfos() capitols[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]); } } + +void CGameState::setObjProperty( SetObjectProperty * p ) +{ + CGObjectInstance *obj = map->objects[p->id]; + + switch(p->what) + { + case 1: + obj->tempOwner = p->val; + break; + case 2: + obj->blockVisit = p->val; + break; + case 3: + static_cast(obj)->army.slots[0].second = p->val; + break; + case 4: + static_cast(obj)->visitors.insert(p->val); + break; + case 5: + static_cast(obj)->visited = p->val; + break; + } +} + int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting) { int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0); diff --git a/CGameState.h b/CGameState.h index 89e5e7bb6..f21431b06 100644 --- a/CGameState.h +++ b/CGameState.h @@ -1,222 +1,230 @@ -#ifndef __CGAMESTATE_H__ -#define __CGAMESTATE_H__ -#include "global.h" -#ifndef _MSC_VER -#include "hch/CCreatureHandler.h" -#include "lib/VCMI_Lib.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; - -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; - //TODO: vectors of heroes/towns - } -}; - -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); //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); //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 - - 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; - 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; - 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); - } hpool; //we have here all heroes available on this map that are not hired - - boost::shared_mutex *mx; - - CGameState(); - ~CGameState(); - void init(StartInfo * si, Mapa * map, int Seed); - void loadTownDInfos(); - void applyNL(IPack * pack); - 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: - 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; - if(!h.saving) - { - loadTownDInfos(); - } - //TODO: hero pool - } - - friend class CCallback; - friend class CPathfinder;; - friend class CLuaCallback; - friend class CClient; - friend void initGameState(Mapa * map, CGameInfo * cgi); - friend class CScriptCallback; - friend class CMapHandler; - friend class CGameHandler; -}; - - -#endif // __CGAMESTATE_H__ +#ifndef __CGAMESTATE_H__ +#define __CGAMESTATE_H__ +#include "global.h" +#ifndef _MSC_VER +#include "hch/CCreatureHandler.h" +#include "lib/VCMI_Lib.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; + //TODO: vectors of heroes/towns + } +}; + +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); //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); //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 + + 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; + 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; + 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); + } hpool; //we have here all heroes available on this map that are not hired + + boost::shared_mutex *mx; + + CGameState(); + ~CGameState(); + 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: + 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; + if(!h.saving) + { + loadTownDInfos(); + } + //TODO: hero pool + } + + 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__ diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index 3bc7a7bd4..97191ce62 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -1076,6 +1076,8 @@ void CPlayerInterface::yourTurn() adventureInt->infoBar.newDay(cb->getDate(1)); + //select first hero if available. + //TODO: check if hero is slept if(adventureInt->heroList.items.size()) adventureInt->select(adventureInt->heroList.items[0].first); else @@ -1193,7 +1195,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details) if(adventureInt == curint) adventureInt->minimap.draw(); - if(details.style) + if(details.style>0) return; //initializing objects and performing first step of move diff --git a/ChangeLog b/ChangeLog index 39310a0f1..5caa21fdd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,14 @@ -0.64 -> 0.next (???) [as for r651] +0.64 -> 0.next (???) [as for r672] GENERAL: * move some settings to the config/settings.txt file * partial support for new screen resolutions * /Data and /Sprites subfolders can be used for adding files not present in .lod archives * fixed crashbug occuring when hero levelled above 15 level +* support for non-standard screen resolutions ADVENTURE INTERFACE: * added water animation +* speed of scrolling map and hero movement can be adjusted in the System Options Window TOWN INTERFACE: * the scroll tab won't remain hanged to our mouse position if we move the mouse away from the scroll bar @@ -18,6 +20,9 @@ BATTLES * war machines support partially added * queue of stacks narrowed * spell effect animation displaying improvements +* positive/negative spells cannot be cast on hostile/our stacks +* showing spell effects affecting stack in creature info window +* more appropriate coloring of stack amount box when stack is affected by a spell * several reported bugs fixed * new spells supported: a) Haste @@ -26,12 +31,19 @@ BATTLES d) slow e) implosion f) forgetfulness + g) shield + h) air shield + i) bless + j) curse + k) bloodlust + l) weakness + m) stone skin + n) prayer + o) frenzy -AI: +AI PLAYER: * Genius AI (first VCMI AI) will control computer creatures during the combat. -GENERAL: -* started making external settings file (will be used for support for non 800x600 screen resolutions) And a lot of minor fixes 0.63 -> 0.64 (Nov 01 2008) diff --git a/client/Client.cpp b/client/Client.cpp index 390f5dabc..1667c6c0e 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -18,82 +18,9 @@ #include #include #include +#include CSharedCond > mess(new std::set); -std::string toString(MetaString &ms) -{ - std::string ret; - for(size_t i=0;i0) - { - ret += ms.strings[ms.message[i]-1]; - } - else - { - std::vector *vec; - int type = ms.texts[-ms.message[i]-1].first, - ser = ms.texts[-ms.message[i]-1].second; - if(type == 5) - { - ret += CGI->arth->artifacts[ser].Name(); - continue; - } - else if(type == 7) - { - ret += CGI->creh->creatures[ser].namePl; - continue; - } - else if(type == 9) - { - ret += CGI->objh->mines[ser].first; - continue; - } - else if(type == 10) - { - ret += CGI->objh->mines[ser].second; - continue; - } - else - { - switch(type) - { - case 1: - vec = &CGI->generaltexth->allTexts; - break; - case 2: - vec = &CGI->objh->xtrainfo; - break; - case 3: - vec = &CGI->objh->names; - break; - case 4: - vec = &CGI->objh->restypes; - break; - case 6: - vec = &CGI->generaltexth->arraytxt; - break; - case 8: - vec = &CGI->objh->creGens; - break; - case 11: - vec = &CGI->objh->advobtxt; - break; - case 12: - vec = &CGI->generaltexth->artifEvents; - break; - } - ret += (*vec)[ser]; - } - } - } - for(size_t i=0; i < ms.replacements.size(); ++i) - { - ret.replace(ret.find("%s"),2,ms.replacements[i]); - } - return ret; -} - CClient::CClient(void) { } @@ -101,6 +28,7 @@ CClient::CClient(CConnection *con, StartInfo *si) :serv(con) { timeHandler tmh; + IObjectInterface::cb = this; CGI->state = new CGameState(); tlog0 <<"\tGamestate: "<> ss; + tlog5 << "Selection of player " << (int)ss.player << " set to " << ss.id << std::endl; + gs->apply(&ss); + break; + } case 515: { HeroRecruited hr; @@ -475,9 +411,7 @@ void CClient::process(int what) SetHoverName shn; *serv >> shn; tlog5 << "Setting a name of " << shn.id <<" object to "<< toString(shn.name) <mx->lock(); - //gs->map->objects[shn.id]->hoverName = toString(shn.name); - gs->mx->unlock(); + gs->apply(&shn); break; } case 2000: @@ -668,8 +602,11 @@ void CClient::process(int what) case 9999: break; default: - throw std::string("Not supported server message!"); - break; + { + std::ostringstream ex; + ex << "Not supported server message (type=" << what <<")"; + throw ex.str(); + } } } void CClient::waitForMoveAndSend(int color) @@ -709,3 +646,13 @@ void CClient::save(const std::string & fname) { *serv << ui16(98) << fname; } + +int CClient::getCurrentPlayer() +{ + return gs->currentPlayer; +} + +int CClient::getSelectedHero() +{ + return IGameCallback::getSelectedHero(getCurrentPlayer())->id; +} \ No newline at end of file diff --git a/client/Client.h b/client/Client.h index 14de8ba62..4cd183e84 100644 --- a/client/Client.h +++ b/client/Client.h @@ -1,63 +1,87 @@ -#ifndef __CLIENT_H__ -#define __CLIENT_H__ - - -#include "../global.h" -#include -struct StartInfo; -class CGameState; -class CGameInterface; -class CConnection; -class CCallback; -class CClient; -void processCommand(const std::string &message, CClient *&client); -namespace boost -{ - class mutex; - class condition_variable; -} - -template -struct CSharedCond -{ - boost::mutex *mx; - boost::condition_variable *cv; - T *res; - CSharedCond(T*R) - { - res = R; - mx = new boost::mutex; - cv = new boost::condition_variable; - } - ~CSharedCond() - { - delete res; - delete mx; - delete cv; - } -}; - -class CClient -{ - CCallback *cb; - CGameState *gs; - std::map playerint; - CConnection *serv; - - void waitForMoveAndSend(int color); -public: - CClient(void); - CClient(CConnection *con, StartInfo *si); - ~CClient(void); - - void close(); - void save(const std::string & fname); - void process(int what); - void run(); - - friend class CCallback; //handling players actions - friend class CScriptCallback; //for objects scripts - friend void processCommand(const std::string &message, CClient *&client); //handling console -}; - -#endif // __CLIENT_H__ +#ifndef __CLIENT_H__ +#define __CLIENT_H__ + + +#include "../global.h" +#include +#include "../lib/IGameCallback.h" +struct StartInfo; +class CGameState; +class CGameInterface; +class CConnection; +class CCallback; +class CClient; +void processCommand(const std::string &message, CClient *&client); +namespace boost +{ + class mutex; + class condition_variable; +} + +template +struct CSharedCond +{ + boost::mutex *mx; + boost::condition_variable *cv; + T *res; + CSharedCond(T*R) + { + res = R; + mx = new boost::mutex; + cv = new boost::condition_variable; + } + ~CSharedCond() + { + delete res; + delete mx; + delete cv; + } +}; + +class CClient : public IGameCallback +{ + CCallback *cb; + std::map playerint; + CConnection *serv; + + void waitForMoveAndSend(int color); +public: + CClient(void); + CClient(CConnection *con, StartInfo *si); + ~CClient(void); + + void close(); + void save(const std::string & fname); + void process(int what); + void run(); + ////////////////////////////////////////////////////////////////////////// + //from IGameCallback + int getCurrentPlayer(); + int getSelectedHero(); + + //not working yet, will be implement somewhen later with support for local-sim-based gameplay + void changeSpells(int hid, bool give, const std::set &spells){}; + void removeObject(int objid){}; + void setBlockVis(int objid, bool bv){}; + void setOwner(int objid, ui8 owner){}; + void setHoverName(int objid, MetaString * name){}; + void setObjProperty(int objid, int prop, int val){}; + void changePrimSkill(int ID, int which, int val, bool abs=false){}; + void showInfoDialog(InfoWindow *iw){}; + void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback){}; + void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback){}; //returns question id + void giveResource(int player, int which, int val){}; + void showCompInfo(ShowInInfobox * comp){}; + void heroVisitCastle(int obj, int heroID){}; + void stopHeroVisitCastle(int obj, int heroID){}; + void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack + void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb){}; //use hero=NULL for no hero + void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb){}; //for hero<=>neutral army + void setAmount(int objid, ui32 val){}; + void moveHero(int hid, int3 pos, bool instant){}; + ////////////////////////////////////////////////////////////////////////// + friend class CCallback; //handling players actions + friend void processCommand(const std::string &message, CClient *&client); //handling console +}; + +#endif // __CLIENT_H__ diff --git a/config/settings.txt b/config/settings.txt index 45ab039c6..1ea601b9c 100644 --- a/config/settings.txt +++ b/config/settings.txt @@ -3,7 +3,7 @@ clientSettings { port=3030; - resolution=800x600; // format: WxH + resolution=1024x768; // format: WxH bpp=24; // bpp!=24 => problems fullscreen=0; //0 - windowed mode, 1 - fullscreen server=127.0.0.1; //use 127.0.0.1 for localhost diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index aed02e0bc..39126dd58 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -17,19 +17,20 @@ #include "../CGameState.h" #include "../lib/NetPacks.h" +std::map > > CGTeleport::objs; IGameCallback * IObjectInterface::cb = NULL; DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode); extern CLodHandler * bitmaph; extern boost::rand48 ran; -void IObjectInterface::onHeroVisit(const CGHeroInstance * h) +void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const {}; -void IObjectInterface::onHeroLeave(const CGHeroInstance * h) +void IObjectInterface::onHeroLeave(const CGHeroInstance * h) const {}; -void IObjectInterface::newTurn () +void IObjectInterface::newTurn () const {}; IObjectInterface::~IObjectInterface() @@ -645,7 +646,7 @@ bool CGHeroInstance::needsLastStack() const { return true; } -void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) +void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const { //TODO: check for allies if(tempOwner == h->tempOwner) //our hero @@ -673,7 +674,7 @@ const std::string & CGHeroInstance::getBiography() const } void CGHeroInstance::initObj() { - cb->setBlockVis(id,true); + blockVisit = true; } int CGTownInstance::getSightDistance() const //returns sight distance { @@ -795,7 +796,7 @@ bool CGTownInstance::needsLastStack() const else return false; } -void CGTownInstance::onHeroVisit(const CGHeroInstance * h) +void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const { if(getOwner() != h->getOwner()) { @@ -804,7 +805,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) cb->heroVisitCastle(id,h->id); } -void CGTownInstance::onHeroLeave(const CGHeroInstance * h) +void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const { cb->stopHeroVisitCastle(id,h->id); } @@ -813,28 +814,16 @@ void CGTownInstance::initObj() { MetaString ms; ms << name << ", " << town->Name(); - cb->setHoverName(id,&ms); + hoverName = toString(ms); } -//std::vector CVisitableOPH::yourObjects() -//{ -// std::vector ret; -// ret.push_back(51);//camp -// ret.push_back(23);//tower -// ret.push_back(61);//axis -// ret.push_back(32);//garden -// ret.push_back(100);//stone -// ret.push_back(102);//tree -// return ret; -//} - -void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) +void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const { if(visitors.find(h->id)==visitors.end()) { onNAHeroVisit(h->id, false); if(ID != 102) //not tree - visitors.insert(h->id); + cb->setObjProperty(id,4,h->id); //add to the visitors } else { @@ -850,16 +839,16 @@ void CGVisitableOPH::initObj() ttype = -1; } -void CGVisitableOPH::treeSelected( int heroID, int resType, int resVal, int expVal, ui32 result ) +void CGVisitableOPH::treeSelected( int heroID, int resType, int resVal, int expVal, ui32 result ) const { if(result==0) //player agreed to give res for exp { cb->giveResource(cb->getOwner(heroID),resType,-resVal); //take resource cb->changePrimSkill(heroID,4,expVal); //give exp - visitors.insert(heroID); //set state to visited + cb->setObjProperty(id,4,heroID); //add to the visitors } } -void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) +void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const { int id=0, subid=0, ot=0, val=1; switch(ID) @@ -925,7 +914,7 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) val = VLC->heroh->reqExp(h->level+val) - VLC->heroh->reqExp(h->level); if(!ttype) { - visitors.insert(heroID); + cb->setObjProperty(id,4,heroID); //add to the visitors InfoWindow iw; iw.components.push_back(Component(id,subid,1,0)); iw.player = cb->getOwner(heroID); @@ -1010,9 +999,10 @@ const std::string & CGVisitableOPH::getHoverText() const const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); if(h) { + hoverName += ' '; hoverName += (vstd::contains(visitors,h->id)) - ? (VLC->generaltexth->allTexts[353]) //not visited - : ( VLC->generaltexth->allTexts[352]); //visited + ? (VLC->generaltexth->allTexts[352]) //visited + : ( VLC->generaltexth->allTexts[353]); //not visited } return hoverName; } @@ -1022,13 +1012,12 @@ bool CArmedInstance::needsLastStack() const return false; } -void CGCreature::onHeroVisit( const CGHeroInstance * h ) +void CGCreature::onHeroVisit( const CGHeroInstance * h ) const { - army.slots[0].first = subID; cb->startBattleI(h->id,army,pos,boost::bind(&CGCreature::endBattle,this,_1)); } -void CGCreature::endBattle( BattleResult *result ) +void CGCreature::endBattle( BattleResult *result ) const { if(result->winner==0) { @@ -1040,12 +1029,19 @@ void CGCreature::endBattle( BattleResult *result ) for(std::set >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++) if(i->first == subID) killedAmount += i->second; - cb->setAmount(id, army.slots[0].second - killedAmount); + cb->setAmount(id, army.slots.find(0)->second.second - killedAmount); + + MetaString ms; + int pom = CCreature::getQuantityID(army.slots.find(0)->second.second); + pom = 174 + 3*pom + 1; + ms << std::pair(6,pom) << " " << std::pair(7,subID); + cb->setHoverName(id,&ms); } } void CGCreature::initObj() { + army.slots[0].first = subID; si32 &amount = army.slots[0].second; CCreature &c = VLC->creh->creatures[subID]; if(!amount) @@ -1053,4 +1049,364 @@ void CGCreature::initObj() amount = c.ammMax; else amount = c.ammMin + (ran() % (c.ammMax - c.ammMin)); + + MetaString ms; + int pom = CCreature::getQuantityID(army.slots.find(0)->second.second); + pom = 174 + 3*pom + 1; + ms << std::pair(6,pom) << " " << std::pair(7,subID); + hoverName = toString(ms); +} + +void CGMine::onHeroVisit( const CGHeroInstance * h ) const +{ + if(subID == 7) //TODO: support for abandoned mine + return; + + if(h->tempOwner == tempOwner) //we're visiting our mine + return; //TODO: leaving garrison + + //TODO: check if mine is guarded + cb->setOwner(id,h->tempOwner); //not ours? flag it! + + MetaString ms; + ms << std::pair(9,subID) << " (" << std::pair(6,23+h->tempOwner) << ")"; + cb->setHoverName(id,&ms); + + int vv=1; //amount of resource per turn + if (subID==0 || subID==2) + vv++; + else if (subID==6) + vv = 1000; + + InfoWindow iw; + iw.text << std::pair(10,subID); + iw.player = h->tempOwner; + iw.components.push_back(Component(2,subID,vv,-1)); + cb->showInfoDialog(&iw); +} + +void CGMine::newTurn() const +{ + if (tempOwner == NEUTRAL_PLAYER) + return; + int vv = 1; + if (subID==0 || subID==2) + vv++; + else if (subID==6) + vv = 1000; + cb->giveResource(tempOwner,subID,vv); +} + +void CGMine::initObj() +{ + MetaString ms; + ms << std::pair(9,subID); + if(tempOwner >= PLAYER_LIMIT) + tempOwner = NEUTRAL_PLAYER; + else + ms << " (" << std::pair(6,23+tempOwner) << ")"; + hoverName = toString(ms); +} + +void CGResource::initObj() +{ + blockVisit = true; + hoverName = VLC->objh->restypes[subID]; + + if(!amount) + { + switch(subID) + { + case 6: + amount = 500 + (rand()%6)*100; + break; + case 0: case 2: + amount = 6 + (rand()%5); + break; + default: + amount = 3 + (rand()%3); + break; + } + } +} + +void CGResource::onHeroVisit( const CGHeroInstance * h ) const +{ + //TODO: handle guards (when battles are finished) + if(message.length()) + { + InfoWindow iw; + iw.player = h->tempOwner; + iw.text << message; + cb->showInfoDialog(&iw); + } + + cb->giveResource(h->tempOwner,subID,amount); + + ShowInInfobox sii; + sii.player = h->tempOwner; + sii.c = Component(2,subID,amount,0); + sii.text << std::pair(11,113); + sii.text.replacements.push_back(VLC->objh->restypes[subID]); + cb->showCompInfo(&sii); + cb->removeObject(id); +} + +void CGVisitableOPW::newTurn() const +{ + if (cb->getDate(1)==1) //first day of week + { + cb->setObjProperty(id,5,false); + MetaString ms; //set text to "not visited" + ms << std::pair(3,ID) << " " << std::pair(1,353); + cb->setHoverName(id,&ms); + } +} + +void CGVisitableOPW::onHeroVisit( const CGHeroInstance * h ) const +{ + int mid; + switch (ID) + { + case 55: + mid = 92; + break; + case 112: + mid = 170; + break; + case 109: + mid = 164; + break; + } + if (visited) + { + if (ID!=112) + mid++; + else + mid--; + + InfoWindow iw; + iw.player = h->tempOwner; + iw.text << std::pair(11,mid); + cb->showInfoDialog(&iw); + } + else + { + int type, sub, val; + type = 2; + switch (ID) + { + case 55: + if (rand()%2) + { + sub = 5; + val = 5; + } + else + { + sub = 6; + val = 500; + } + break; + case 112: + mid = 170; + sub = (rand() % 5) + 1; + val = (rand() % 4) + 3; + break; + case 109: + mid = 164; + sub = 6; + if(cb->getDate(2)<2) + val = 500; + else + val = 1000; + } + cb->giveResource(h->tempOwner,sub,val); + InfoWindow iw; + iw.player = h->tempOwner; + iw.components.push_back(Component(type,sub,val,0)); + iw.text << std::pair(11,mid); + cb->showInfoDialog(&iw); + cb->setObjProperty(id,5,true); + MetaString ms; //set text to "visited" + ms << std::pair(3,ID) << " " << std::pair(1,352); + cb->setHoverName(id,&ms); + } +} + +void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const +{ + int destinationid=-1; + switch(ID) + { + case 43: //one way - find correspong exit monolith + if(vstd::contains(objs,44) && vstd::contains(objs[44],subID) && objs[44][subID].size()) + destinationid = objs[44][subID][rand()%objs[44][subID].size()]; + else + tlog2 << "Cannot find corresponding exit monolith for "<< id << std::endl; + break; + case 45: //two way monolith - pick any other one + if(vstd::contains(objs,45) && vstd::contains(objs[45],subID) && objs[45][subID].size()>1) + while ((destinationid = objs[45][subID][rand()%objs[45][subID].size()])==id); + else + tlog2 << "Cannot find corresponding exit monolith for "<< id << std::endl; + break; + case 103: //find nearest subterranean gate on the other level + { + std::pair best(-1,150000); //pair + for(int i=0; igetObj(objs[103][0][i])->pos.z == pos.z) continue; //gates on our level are not interesting + double hlp = cb->getObj(objs[103][0][i])->pos.dist2d(pos); + if(hlpmoveHero(h->id, + (ID!=103) + ? (CGHeroInstance::convertPosition(cb->getObj(destinationid)->pos,true)) + : (cb->getObj(destinationid)->pos), + true); +} + +void CGTeleport::initObj() +{ + objs[ID][subID].push_back(id); +} + +void CGArtifact::initObj() +{ + blockVisit = true; + if(ID == 5) + hoverName = VLC->arth->artifacts[subID].Name(); +} + +void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const +{ + cb->giveHeroArtifact(subID,h->id,-2); + InfoWindow iw; + iw.player = h->tempOwner; + iw.components.push_back(Component(4,subID,0,0)); + iw.text << std::pair(12,subID); + cb->showInfoDialog(&iw); +} + +void CGPickable::initObj() +{ + blockVisit = true; + switch(ID) + { + case 12: //campfire + val2 = (ran()%3) + 4; //4 - 6 + val1 = val2 * 100; + type = ran()%6; //given resource + break; + case 101: //treasure chest + { + int hlp = ran()%100; + if(hlp >= 95) + { + type = 1; + val1 = VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id; + return; + } + else if (hlp >= 65) + { + val1 = 2000; + } + else if(hlp >= 33) + { + val1 = 1500; + } + else + { + val1 = 1000; + } + + val2 = val1 - 500; + type = 0; + break; + } + } +} + +void CGPickable::onHeroVisit( const CGHeroInstance * h ) const +{ + + switch(ID) + { + case 12: //campfire + { + cb->giveResource(h->tempOwner,type,val2); //non-gold resource + cb->giveResource(h->tempOwner,6,val1);//gold + InfoWindow iw; + iw.player = h->tempOwner; + iw.components.push_back(Component(2,6,val1,0)); + iw.components.push_back(Component(2,type,val2,0)); + iw.text << std::pair(11,23); + cb->showInfoDialog(&iw); + break; + } + case 101: //treasure chest + { + if (subID) //not OH3 treasure chest + { + tlog2 << "Not supported WoG treasure chest!\n"; + return; + } + + if(type) //there is an artifact + { + cb->giveHeroArtifact(val1,h->id,-2); + InfoWindow iw; + iw.player = h->tempOwner; + iw.components.push_back(Component(4,val1,1,0)); + iw.text << std::pair(11,145); + iw.text.replacements.push_back(VLC->arth->artifacts[val1].Name()); + cb->showInfoDialog(&iw); + break; + } + else + { + SelectionDialog sd; + sd.player = h->tempOwner; + sd.text << std::pair(11,146); + sd.components.push_back(Component(2,6,val1,0)); + sd.components.push_back(Component(5,0,val2,0)); + boost::function fun = boost::bind(&CGPickable::chosen,this,_1,h->id); + cb->showSelectionDialog(&sd,fun); + return; + } + } + } + cb->removeObject(id); +} + +void CGPickable::chosen( int which, int heroID ) const +{ + switch(which) + { + case 0: //player pick gold + cb->giveResource(cb->getOwner(heroID),6,val1); + break; + case 1: //player pick exp + cb->changePrimSkill(heroID, 4, val2); + break; + default: + throw std::string("Unhandled treasure choice"); + } } \ No newline at end of file diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index d64e61b8a..ca677666d 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -1,439 +1,453 @@ -#ifndef __COBJECTHANDLER_H__ -#define __COBJECTHANDLER_H__ -#include "../global.h" -#include -#include -#include -#include -#include "CCreatureHandler.h" - -using boost::logic::tribool; -class IGameCallback; -struct BattleResult; -class CCPPObjectScript; -class CGObjectInstance; -class CScript; -class CObjectScript; -class CGHeroInstance; -class CTown; -class CHero; -class CBuilding; -class CSpell; -class CGTownInstance; -class CArtifact; -class CGDefInfo; -class CSpecObjInfo; - -class DLL_EXPORT CCastleEvent -{ -public: - std::string name, message; - int wood, mercury, ore, sulfur, crystal, gems, gold; //gain / loss of resources - unsigned char players; //players for whom this event can be applied - bool forHuman, forComputer; - int firstShow; //postpone of first encounter time in days - int forEvery; //every n days this event will occure - - unsigned char bytes[6]; //build specific buildings (raw format, similar to town's) - - int gen[7]; //additional creatures in i-th level dwelling - - bool operator<(const CCastleEvent &drugie) const - { - return firstShow primSkills; //0-attack, 1-defence, 2-spell power, 3-knowledge - std::vector > secSkills; //first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert); if hero has ability (-1, -1) it meansthat it should have default secondary abilities - int movement; //remaining movement points - int identifier; //from the map file - bool sex; - struct DLL_EXPORT Patrol - { - Patrol(){patrolling=false;patrolRadious=-1;}; - bool patrolling; - int patrolRadious; - } patrol; - bool inTownGarrison; // if hero is in town garrison - CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison - std::vector artifacts; //hero's artifacts from bag - std::map artifWorn; //map; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5 - std::set spells; //known spells (spell IDs) - - ////////////////////////////////////////////////////////////////////////// - - const std::string &getBiography() const; - bool needsLastStack()const; - unsigned int getTileCost(const EterrainType & ttype, const Eroad & rdtype, const Eriver & rvtype) const; - unsigned int getLowestCreatureSpeed() const; - unsigned int getAdditiveMoveBonus() const; - float getMultiplicativeMoveBonus() const; - int3 getPosition(bool h3m) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation' - int getSightDistance() const; //returns sight distance of this hero - int manaLimit() const; //maximum mana value for this hero (basically 10*knowledge) - bool canWalkOnSea() const; - int getCurrentLuck() const; - int getCurrentMorale() const; - int getPrimSkillLevel(int id) const; - int getSecSkillLevel(const int & ID) const; //0 - no skill - int maxMovePoints(bool onLand) const; - ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact - void setArtAtPos(ui16 pos, int art); - const CArtifact * getArt(int pos) const; - int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error - static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest - - ////////////////////////////////////////////////////////////////////////// - - void initHero(); - void initHero(int SUBID); - CGHeroInstance(); - virtual ~CGHeroInstance(); - - ////////////////////////////////////////////////////////////////////////// - void initObj(); - void onHeroVisit(const CGHeroInstance * h); -}; - -class DLL_EXPORT CGTownInstance : public CArmedInstance -{ -public: - CTown * town; - std::string name; // name of town - int builded; //how many buildings has been built this turn - int destroyed; //how many buildings has been destroyed this turn - const CGHeroInstance * garrisonHero, *visitingHero; - int identifier; //special identifier from h3m (only > RoE maps) - int alignment; - std::set forbiddenBuildings, builtBuildings; - std::vector possibleSpells, obligatorySpells; - std::vector > spells; //spells[level] -> vector of spells, first will be available in guild - - struct StrInfo - { - std::map creatures; //level - available amount - - template void serialize(Handler &h, const int version) - { - h & creatures; - } - } strInfo; - std::set events; - - - bool needsLastStack() const; - int getSightDistance() const; //returns sight distance - int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle - int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol - int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol - bool creatureDwelling(const int & level, bool upgraded=false) const; - int getHordeLevel(const int & HID) const; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present - int creatureGrowth(const int & level) const; - bool hasFort() const; - bool hasCapitol() const; - int dailyIncome() const; - int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5) - - CGTownInstance(); - virtual ~CGTownInstance(); - - ////////////////////////////////////////////////////////////////////////// - - - void onHeroVisit(const CGHeroInstance * h); - void onHeroLeave(const CGHeroInstance * h); - void initObj(); -}; - -class DLL_EXPORT CGVisitableOPH : public CGObjectInstance //objects visitable only once per hero -{ -public: - std::set visitors; //ids of heroes who have visited this obj - si8 ttype; //tree type - used only by trees of knowledge: 0 - give level for free; 1 - take 2000 gold; 2 - take 10 gems - const std::string & getHoverText() const; - - void onHeroVisit(const CGHeroInstance * h); - void onNAHeroVisit(int heroID, bool alreadyVisited); - void initObj(); - void treeSelected(int heroID, int resType, int resVal, int expVal, ui32 result); //handle player's anwer to the Tree of Knowledge dialog -}; - -class DLL_EXPORT CGEvent : public CGObjectInstance //event objects -{ -public: - bool areGuarders; //true if there are - CCreatureSet guarders; - bool isMessage; //true if there is a message - std::string message; - unsigned int gainedExp; - int manaDiff; //amount of gained / lost mana - int moraleDiff; //morale modifier - int luckDiff; //luck modifier - int wood, mercury, ore, sulfur, crystal, gems, gold; //gained / lost resources - unsigned int attack; //added attack points - unsigned int defence; //added defence points - unsigned int power; //added power points - unsigned int knowledge; //added knowledge points - std::vector abilities; //gained abilities - std::vector abilityLevels; //levels of gained abilities - std::vector artifacts; //gained artifacts - std::vector spells; //gained spells - CCreatureSet creatures; //gained creatures - unsigned char availableFor; //players whom this event is available for - bool computerActivate; //true if computre player can activate this event - bool humanActivate; //true if human player can activate this event -}; - -class DLL_EXPORT CGCreature : public CArmedInstance //creatures on map -{ -public: - ui32 identifier; //unique code for this monster (used in missions) - ui8 character; //chracter of this set of creatures (0 - the most friendly, 4 - the most hostile) - std::string message; //message printed for attacking hero - std::vector resources; //[res_id], resources given to hero that has won with monsters - si32 gainedArtifact; //ID of artifact gained to hero, -1 if none - ui8 neverFlees; //if true, the troops will never flee - ui8 notGrowingTeam; //if true, number of units won't grow - - void onHeroVisit(const CGHeroInstance * h); - void endBattle(BattleResult *result); - void initObj(); -}; - - -class DLL_EXPORT CGSignBottle : public CGObjectInstance //signs and ocean bottles -{ - //TODO: generate default message if sign is 'empty' -public: - std::string message; -}; - -class DLL_EXPORT CGSeerHut : public CGObjectInstance -{ -public: - unsigned char missionType; //type of mission: 0 - no mission; 1 - reach level; 2 - reach main statistics values; 3 - win with a certain hero; 4 - win with a certain creature; 5 - collect some atifacts; 6 - have certain troops in army; 7 - collect resources; 8 - be a certain hero; 9 - be a certain player - bool isDayLimit; //if true, there is a day limit - int lastDay; //after this day (first day is 0) mission cannot be completed - int m1level; //for mission 1 - int m2attack, m2defence, m2power, m2knowledge;//for mission 2 - unsigned char m3bytes[4];//for mission 3 - unsigned char m4bytes[4];//for mission 4 - std::vector m5arts;//for mission 5 - artifact ID - std::vector m6cre;//for mission 6 - std::vector m6number; - int m7wood, m7mercury, m7ore, m7sulfur, m7crystal, m7gems, m7gold; //for mission 7 - int m8hero;//for mission 8 - hero ID - int m9player; //for mission 9 - number; from 0 to 7 - - std::string firstVisitText, nextVisitText, completedText; - - char rewardType; //type of reward: 0 - no reward; 1 - experience; 2 - mana points; 3 - morale bonus; 4 - luck bonus; 5 - resources; 6 - main ability bonus (attak, defence etd.); 7 - secondary ability gain; 8 - artifact; 9 - spell; 10 - creature - //for reward 1 - int r1exp; - //for reward 2 - int r2mana; - //for reward 3 - int r3morale; - //for reward 4 - int r4luck; - //for reward 5 - unsigned char r5type; //0 - wood, 1 - mercury, 2 - ore, 3 - sulfur, 4 - crystal, 5 - gems, 6 - gold - int r5amount; - //for reward 6 - unsigned char r6type; //0 - attack, 1 - defence, 2 - power, 3 - knowledge - int r6amount; - //for reward 7 - int r7ability; //ability id - unsigned char r7level; //1 - basic, 2 - advanced, 3 - expert - //for reward 8 - int r8art;//artifact id - //for reward 9 - int r9spell;//spell id - //for reward 10 - int r10creature; //creature id - int r10amount; -}; - -class DLL_EXPORT CGWitchHut : public CGObjectInstance -{ -public: - std::vector allowedAbilities; -}; - - -class DLL_EXPORT CGScholar : public CGObjectInstance -{ -public: - ui8 bonusType; //255 - random, 0 - primary skill, 1 - secondary skill, 2 - spell - - ui8 r0type; - ui32 r1; //Ability ID - ui32 r2; //Spell ID -}; - -class DLL_EXPORT CGGarrison : public CArmedInstance -{ -public: - bool removableUnits; -}; - -class DLL_EXPORT CGArtifact : public CArmedInstance -{ -public: - std::string message; - ui32 spell; //if it's spell scroll -}; - -class DLL_EXPORT CGResource : public CArmedInstance -{ -public: - int amount; //0 if random - std::string message; -}; - -class DLL_EXPORT CGShrine : public CGObjectInstance -{ -public: - unsigned char spell; //number of spell or 255 if random -}; - -class DLL_EXPORT CGPandoraBox : public CArmedInstance -{ -public: - std::string message; - - //gained things: - unsigned int gainedExp; - int manaDiff; - int moraleDiff; - int luckDiff; - int wood, mercury, ore, sulfur, crystal, gems, gold; - int attack, defence, power, knowledge; - std::vector abilities; - std::vector abilityLevels; - std::vector artifacts; - std::vector spells; - CCreatureSet creatures; -}; - -class DLL_EXPORT CGQuestGuard : public CArmedInstance -{ -public: - char missionType; //type of mission: 0 - no mission; 1 - reach level; 2 - reach main statistics values; 3 - win with a certain hero; 4 - win with a certain creature; 5 - collect some atifacts; 6 - have certain troops in army; 7 - collect resources; 8 - be a certain hero; 9 - be a certain player - bool isDayLimit; //if true, there is a day limit - int lastDay; //after this day (first day is 0) mission cannot be completed - //for mission 1 - int m1level; - //for mission 2 - int m2attack, m2defence, m2power, m2knowledge; - //for mission 3 - unsigned char m3bytes[4]; - //for mission 4 - unsigned char m4bytes[4]; - //for mission 5 - std::vector m5arts; //artifacts id - //for mission 6 - std::vector m6cre; - std::vector m6number; - //for mission 7 - int m7wood, m7mercury, m7ore, m7sulfur, m7crystal, m7gems, m7gold; - //for mission 8 - int m8hero; //hero id - //for mission 9 - int m9player; //number; from 0 to 7 - - std::string firstVisitText, nextVisitText, completedText; -}; - -class DLL_EXPORT CObjectHandler -{ -public: - std::vector names; //vector of objects; i-th object in vector has subnumber i - std::vector cregens; //type 17. dwelling subid -> creature ID - void loadObjects(); - - std::vector creGens; //names of creatures' generators - std::vector advobtxt; - std::vector xtrainfo; - std::vector restypes; - std::vector > mines; //first - name; second - event description -}; - - - -#endif // __COBJECTHANDLER_H__ +#ifndef __COBJECTHANDLER_H__ +#define __COBJECTHANDLER_H__ +#include "../global.h" +#include +#include +#include +#include +#include "CCreatureHandler.h" + +using boost::logic::tribool; +class IGameCallback; +struct BattleResult; +class CCPPObjectScript; +class CGObjectInstance; +class CScript; +class CObjectScript; +class CGHeroInstance; +class CTown; +class CHero; +class CBuilding; +class CSpell; +class CGTownInstance; +class CArtifact; +class CGDefInfo; +class CSpecObjInfo; + +class DLL_EXPORT CCastleEvent +{ +public: + std::string name, message; + int wood, mercury, ore, sulfur, crystal, gems, gold; //gain / loss of resources + unsigned char players; //players for whom this event can be applied + bool forHuman, forComputer; + int firstShow; //postpone of first encounter time in days + int forEvery; //every n days this event will occure + + unsigned char bytes[6]; //build specific buildings (raw format, similar to town's) + + int gen[7]; //additional creatures in i-th level dwelling + + bool operator<(const CCastleEvent &drugie) const + { + return firstShow m2stats; + std::vector m5arts; //artifacts id + std::vector > m6creatures; //pair[cre id, cre count] + std::vector m7resources; + + std::string firstVisitText, nextVisitText, completedText; +}; + +class DLL_EXPORT IObjectInterface +{ +public: + static IGameCallback *cb; + + IObjectInterface(); + virtual ~IObjectInterface(); + + virtual void onHeroVisit(const CGHeroInstance * h) const; + virtual void onHeroLeave(const CGHeroInstance * h) const; + virtual void newTurn() const; + virtual void initObj(); +}; + +class DLL_EXPORT CGObjectInstance : protected IObjectInterface +{ +protected: +public: + mutable std::string hoverName; + int3 pos; //h3m pos + int ID, subID; //normal ID (this one from OH3 maps ;]) - eg. town=98; hero=34 + si32 id;//number of object in CObjectHandler's vector + CGDefInfo * defInfo; + CCPPObjectScript * state; + CSpecObjInfo * info; + unsigned char animPhaseShift; + + ui8 tempOwner; //uzywane dla szybkosci, skrypt ma obowiazek aktualizowac te zmienna + ui8 blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile + + int getOwner() const; + void setOwner(int ow); + int getWidth() const; //returns width of object graphic in tiles + int getHeight() const; //returns height of object graphic in tiles + bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles) + bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) form left top tile of image (x, y in tiles) + bool operator<(const CGObjectInstance & cmp) const; //screen printing priority comparing + CGObjectInstance(); + virtual ~CGObjectInstance(); + CGObjectInstance(const CGObjectInstance & right); + CGObjectInstance& operator=(const CGObjectInstance & right); + virtual const std::string & getHoverText() const; + ////////////////////////////////////////////////////////////////////////// + void initObj(); + + friend class CGameHandler; +}; + +class DLL_EXPORT CArmedInstance: public CGObjectInstance +{ +public: + CCreatureSet army; //army + virtual bool needsLastStack() const; //true if last stack cannot be taken +}; + +class DLL_EXPORT CGHeroInstance : public CArmedInstance +{ +public: + ////////////////////////////////////////////////////////////////////////// + + mutable int moveDir; //format: 123 + // 8 4 + // 765 + mutable ui8 isStanding, tacticFormationEnabled; + + ////////////////////////////////////////////////////////////////////////// + + CHero * type; + ui32 exp; //experience point + int level; //current level of hero + std::string name; //may be custom + std::string biography; //if custom + int portrait; //may be custom + int mana; // remaining spell points + std::vector primSkills; //0-attack, 1-defence, 2-spell power, 3-knowledge + std::vector > secSkills; //first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert); if hero has ability (-1, -1) it meansthat it should have default secondary abilities + int movement; //remaining movement points + int identifier; //from the map file + bool sex; + struct DLL_EXPORT Patrol + { + Patrol(){patrolling=false;patrolRadious=-1;}; + bool patrolling; + int patrolRadious; + } patrol; + bool inTownGarrison; // if hero is in town garrison + CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison + std::vector artifacts; //hero's artifacts from bag + std::map artifWorn; //map; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5 + std::set spells; //known spells (spell IDs) + + ////////////////////////////////////////////////////////////////////////// + + const std::string &getBiography() const; + bool needsLastStack()const; + unsigned int getTileCost(const EterrainType & ttype, const Eroad & rdtype, const Eriver & rvtype) const; + unsigned int getLowestCreatureSpeed() const; + unsigned int getAdditiveMoveBonus() const; + float getMultiplicativeMoveBonus() const; + int3 getPosition(bool h3m) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation' + int getSightDistance() const; //returns sight distance of this hero + int manaLimit() const; //maximum mana value for this hero (basically 10*knowledge) + bool canWalkOnSea() const; + int getCurrentLuck() const; + int getCurrentMorale() const; + int getPrimSkillLevel(int id) const; + int getSecSkillLevel(const int & ID) const; //0 - no skill + int maxMovePoints(bool onLand) const; + ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact + void setArtAtPos(ui16 pos, int art); + const CArtifact * getArt(int pos) const; + int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error + static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest + + ////////////////////////////////////////////////////////////////////////// + + void initHero(); + void initHero(int SUBID); + CGHeroInstance(); + virtual ~CGHeroInstance(); + + ////////////////////////////////////////////////////////////////////////// + void initObj(); + void onHeroVisit(const CGHeroInstance * h) const; +}; + +class DLL_EXPORT CGTownInstance : public CArmedInstance +{ +public: + CTown * town; + std::string name; // name of town + int builded; //how many buildings has been built this turn + int destroyed; //how many buildings has been destroyed this turn + const CGHeroInstance * garrisonHero, *visitingHero; + int identifier; //special identifier from h3m (only > RoE maps) + int alignment; + std::set forbiddenBuildings, builtBuildings; + std::vector possibleSpells, obligatorySpells; + std::vector > spells; //spells[level] -> vector of spells, first will be available in guild + + struct StrInfo + { + std::map creatures; //level - available amount + + template void serialize(Handler &h, const int version) + { + h & creatures; + } + } strInfo; + std::set events; + + + bool needsLastStack() const; + int getSightDistance() const; //returns sight distance + int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle + int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol + int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol + bool creatureDwelling(const int & level, bool upgraded=false) const; + int getHordeLevel(const int & HID) const; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present + int creatureGrowth(const int & level) const; + bool hasFort() const; + bool hasCapitol() const; + int dailyIncome() const; + int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5) + + CGTownInstance(); + virtual ~CGTownInstance(); + + ////////////////////////////////////////////////////////////////////////// + + + void onHeroVisit(const CGHeroInstance * h) const; + void onHeroLeave(const CGHeroInstance * h) const; + void initObj(); +}; + +class DLL_EXPORT CGVisitableOPH : public CGObjectInstance //objects visitable only once per hero +{ +public: + std::set visitors; //ids of heroes who have visited this obj + si8 ttype; //tree type - used only by trees of knowledge: 0 - give level for free; 1 - take 2000 gold; 2 - take 10 gems + const std::string & getHoverText() const; + + void onHeroVisit(const CGHeroInstance * h) const; + void onNAHeroVisit(int heroID, bool alreadyVisited) const; + void initObj(); + void treeSelected(int heroID, int resType, int resVal, int expVal, ui32 result) const; //handle player's anwer to the Tree of Knowledge dialog +}; + +class DLL_EXPORT CGEvent : public CGObjectInstance //event objects +{ +public: + bool areGuarders; //true if there are + CCreatureSet guarders; + bool isMessage; //true if there is a message + std::string message; + unsigned int gainedExp; + int manaDiff; //amount of gained / lost mana + int moraleDiff; //morale modifier + int luckDiff; //luck modifier + int wood, mercury, ore, sulfur, crystal, gems, gold; //gained / lost resources + unsigned int attack; //added attack points + unsigned int defence; //added defence points + unsigned int power; //added power points + unsigned int knowledge; //added knowledge points + std::vector abilities; //gained abilities + std::vector abilityLevels; //levels of gained abilities + std::vector artifacts; //gained artifacts + std::vector spells; //gained spells + CCreatureSet creatures; //gained creatures + unsigned char availableFor; //players whom this event is available for + bool computerActivate; //true if computre player can activate this event + bool humanActivate; //true if human player can activate this event +}; + +class DLL_EXPORT CGCreature : public CArmedInstance //creatures on map +{ +public: + ui32 identifier; //unique code for this monster (used in missions) + ui8 character; //chracter of this set of creatures (0 - the most friendly, 4 - the most hostile) + std::string message; //message printed for attacking hero + std::vector resources; //[res_id], resources given to hero that has won with monsters + si32 gainedArtifact; //ID of artifact gained to hero, -1 if none + ui8 neverFlees; //if true, the troops will never flee + ui8 notGrowingTeam; //if true, number of units won't grow + + void onHeroVisit(const CGHeroInstance * h) const; + void endBattle(BattleResult *result) const; + void initObj(); +}; + + +class DLL_EXPORT CGSignBottle : public CGObjectInstance //signs and ocean bottles +{ + //TODO: generate default message if sign is 'empty' +public: + std::string message; +}; + +class DLL_EXPORT CGSeerHut : public CGObjectInstance, public CQuest +{ +public: + char rewardType; //type of reward: 0 - no reward; 1 - experience; 2 - mana points; 3 - morale bonus; 4 - luck bonus; 5 - resources; 6 - main ability bonus (attak, defence etd.); 7 - secondary ability gain; 8 - artifact; 9 - spell; 10 - creature + //for reward 1 + int r1exp; + //for reward 2 + int r2mana; + //for reward 3 + int r3morale; + //for reward 4 + int r4luck; + //for reward 5 + unsigned char r5type; //0 - wood, 1 - mercury, 2 - ore, 3 - sulfur, 4 - crystal, 5 - gems, 6 - gold + int r5amount; + //for reward 6 + unsigned char r6type; //0 - attack, 1 - defence, 2 - power, 3 - knowledge + int r6amount; + //for reward 7 + int r7ability; //ability id + unsigned char r7level; //1 - basic, 2 - advanced, 3 - expert + //for reward 8 + int r8art;//artifact id + //for reward 9 + int r9spell;//spell id + //for reward 10 + int r10creature; //creature id + int r10amount; +}; + +class DLL_EXPORT CGWitchHut : public CGObjectInstance +{ +public: + std::vector allowedAbilities; +}; + + +class DLL_EXPORT CGScholar : public CGObjectInstance +{ +public: + ui8 bonusType; //255 - random, 0 - primary skill, 1 - secondary skill, 2 - spell + + ui8 r0type; + ui32 r1; //Ability ID + ui32 r2; //Spell ID +}; + +class DLL_EXPORT CGGarrison : public CArmedInstance +{ +public: + bool removableUnits; +}; + +class DLL_EXPORT CGArtifact : public CArmedInstance +{ +public: + std::string message; + ui32 spell; //if it's spell scroll + void onHeroVisit(const CGHeroInstance * h) const; + void initObj(); +}; + +class DLL_EXPORT CGResource : public CArmedInstance +{ +public: + int amount; //0 if random + std::string message; + + void onHeroVisit(const CGHeroInstance * h) const; + void initObj(); +}; + +class DLL_EXPORT CGPickable : public CGObjectInstance //campfire, treasure chest +{ + ui32 type, val1, val2; + + void onHeroVisit(const CGHeroInstance * h) const; + void initObj(); + void chosen(int which, int heroID) const; +}; + +class DLL_EXPORT CGShrine : public CGObjectInstance +{ +public: + unsigned char spell; //number of spell or 255 if random +}; + +class DLL_EXPORT CGPandoraBox : public CArmedInstance +{ +public: + std::string message; + + //gained things: + unsigned int gainedExp; + int manaDiff; + int moraleDiff; + int luckDiff; + int wood, mercury, ore, sulfur, crystal, gems, gold; + int attack, defence, power, knowledge; + std::vector abilities; + std::vector abilityLevels; + std::vector artifacts; + std::vector spells; + CCreatureSet creatures; +}; + +class DLL_EXPORT CGQuestGuard : public CGObjectInstance, public CQuest +{ +public: +}; + +class DLL_EXPORT CGMine : public CArmedInstance +{ +public: + void onHeroVisit(const CGHeroInstance * h) const; + void newTurn() const; + void initObj(); +}; + +class DLL_EXPORT CGVisitableOPW : public CGObjectInstance //objects visitable OPW +{ +public: + ui8 visited; //true if object has been visited this week + + void onHeroVisit(const CGHeroInstance * h) const; + void newTurn() const; +}; + +class DLL_EXPORT CGTeleport : public CGObjectInstance //teleports and subterranean gates +{ +public: + static std::map > > objs; //map[ID][subID] => vector of ids + void onHeroVisit(const CGHeroInstance * h) const; + void initObj(); +}; + +class DLL_EXPORT CObjectHandler +{ +public: + std::vector names; //vector of objects; i-th object in vector has subnumber i + std::vector cregens; //type 17. dwelling subid -> creature ID + void loadObjects(); + + std::vector creGens; //names of creatures' generators + std::vector advobtxt; + std::vector xtrainfo; + std::vector restypes; + std::vector > mines; //first - name; second - event description +}; + + + +#endif // __COBJECTHANDLER_H__ diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp new file mode 100644 index 000000000..260183277 --- /dev/null +++ b/lib/IGameCallback.cpp @@ -0,0 +1,36 @@ +#define VCMI_DLL +#include "IGameCallback.h" +#include "../CGameState.h" +#include "../map.h" +#include "../hch/CObjectHandler.h" + +const CGObjectInstance* IGameCallback::getObj(int objid) +{ + return gs->map->objects[objid]; +} +const CGHeroInstance* IGameCallback::getHero(int objid) +{ + return dynamic_cast(gs->map->objects[objid]); +} +const CGTownInstance* IGameCallback::getTown(int objid) +{ + return dynamic_cast(gs->map->objects[objid]); +} + +int IGameCallback::getOwner(int heroID) +{ + return gs->map->objects[heroID]->tempOwner; +} +int IGameCallback::getResource(int player, int which) +{ + return gs->players.find(player)->second.resources[which]; +} +int IGameCallback::getDate(int mode) +{ + return gs->getDate(mode); +} + +const CGHeroInstance* IGameCallback::getSelectedHero( int player ) +{ + return getHero(gs->players.find(player)->second.currentSelection); +} \ No newline at end of file diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 18219b133..79f0e96f2 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -1,54 +1,58 @@ -#ifndef __IGAMECALLBACK_H__ -#define __IGAMECALLBACK_H__ - -#include "../global.h" -#include -#include -#include "../client/FunctionList.h" - -class CGObjectInstance; -class CGTownInstance; -class CGHeroInstance; -struct SelectionDialog; -struct YesNoDialog; -struct InfoWindow; -struct MetaString; -struct ShowInInfobox; -struct BattleResult; - -class IGameCallback -{ -public: - virtual ~IGameCallback(){}; - - virtual int getOwner(int heroID)=0; - virtual int getResource(int player, int which)=0; - virtual int getSelectedHero()=0; - virtual int getDate(int mode=0)=0; - virtual const CGObjectInstance* getObj(int objid)=0; - virtual const CGHeroInstance* getHero(int objid)=0; - virtual const CGTownInstance* getTown(int objid)=0; - virtual const CGHeroInstance* getSelectedHero(int player)=0; //NULL if no hero is selected - virtual int getCurrentPlayer()=0; - - //do sth - virtual void changeSpells(int hid, bool give, const std::set &spells)=0; - virtual void removeObject(int objid)=0; - virtual void setBlockVis(int objid, bool bv)=0; - virtual void setOwner(int objid, ui8 owner)=0; - virtual void setHoverName(int objid, MetaString * name)=0; - virtual void changePrimSkill(int ID, int which, int val, bool abs=false)=0; - virtual void showInfoDialog(InfoWindow *iw)=0; - virtual void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback)=0; - virtual void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback)=0; //returns question id - virtual void giveResource(int player, int which, int val)=0; - virtual void showCompInfo(ShowInInfobox * comp)=0; - virtual void heroVisitCastle(int obj, int heroID)=0; - virtual void stopHeroVisitCastle(int obj, int heroID)=0; - virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack - virtual void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb)=0; //use hero=NULL for no hero - virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb)=0; //for hero<=>neutral army - virtual void setAmount(int objid, ui32 val)=0; - virtual void moveHero(int hid, int3 pos, bool instant)=0; -}; -#endif // __IGAMECALLBACK_H__ +#ifndef __IGAMECALLBACK_H__ +#define __IGAMECALLBACK_H__ + +#include "../global.h" +#include +#include +#include "../client/FunctionList.h" + +class CGObjectInstance; +class CGTownInstance; +class CGHeroInstance; +struct SelectionDialog; +struct YesNoDialog; +struct InfoWindow; +struct MetaString; +struct ShowInInfobox; +struct BattleResult; +class CGameState; + +class DLL_EXPORT IGameCallback +{ +protected: + CGameState *gs; +public: + virtual ~IGameCallback(){}; + + virtual int getOwner(int heroID); + virtual int getResource(int player, int which); + virtual int getDate(int mode=0); + virtual const CGObjectInstance* getObj(int objid); + virtual const CGHeroInstance* getHero(int objid); + virtual const CGTownInstance* getTown(int objid); + virtual const CGHeroInstance* getSelectedHero(int player); //NULL if no hero is selected + virtual int getCurrentPlayer()=0; + virtual int getSelectedHero()=0; + + //do sth + virtual void changeSpells(int hid, bool give, const std::set &spells)=0; + virtual void removeObject(int objid)=0; + virtual void setBlockVis(int objid, bool bv)=0; + virtual void setOwner(int objid, ui8 owner)=0; + virtual void setHoverName(int objid, MetaString * name)=0; + virtual void setObjProperty(int objid, int prop, int val)=0; + virtual void changePrimSkill(int ID, int which, int val, bool abs=false)=0; + virtual void showInfoDialog(InfoWindow *iw)=0; + virtual void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback)=0; + virtual void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback)=0; //returns question id + virtual void giveResource(int player, int which, int val)=0; + virtual void showCompInfo(ShowInInfobox * comp)=0; + virtual void heroVisitCastle(int obj, int heroID)=0; + virtual void stopHeroVisitCastle(int obj, int heroID)=0; + virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack + virtual void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb)=0; //use hero=NULL for no hero + virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb)=0; //for hero<=>neutral army + virtual void setAmount(int objid, ui32 val)=0; + virtual void moveHero(int hid, int3 pos, bool instant)=0; +}; +#endif // __IGAMECALLBACK_H__ \ No newline at end of file diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 983cb59b4..3448a07b8 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -236,6 +236,18 @@ struct SetHeroArtifacts : public CPack //509 } }; +struct SetSelection : public CPack //514 +{ + SetSelection(){type = 514;}; + ui8 player; + ui32 id; + + template void serialize(Handler &h, const int version) + { + h & id & player; + } +}; + struct HeroRecruited : public CPack //515 { HeroRecruited(){type = 515;}; @@ -346,7 +358,7 @@ struct InfoWindow : public CPack //103 - displays simple info windo struct SetObjectProperty : public CPack//1001 { ui32 id; - ui8 what; //1 - owner; 2 - blockvis; 3 - amount (works with creatures stacks) + ui8 what; //1 - owner; 2 - blockvis ui32 val; SetObjectProperty(){type = 1001;}; SetObjectProperty(ui32 ID, ui8 What, ui32 Val):id(ID),what(What),val(Val){type = 1001;}; diff --git a/lib/VCMI_lib.vcproj b/lib/VCMI_lib.vcproj index 91d6a39f3..7a6e6b6d9 100644 --- a/lib/VCMI_lib.vcproj +++ b/lib/VCMI_lib.vcproj @@ -310,6 +310,10 @@ RelativePath="..\hch\CTownHandler.cpp" > + + diff --git a/map.cpp b/map.cpp index e55840ae0..8b682d40c 100644 --- a/map.cpp +++ b/map.cpp @@ -577,203 +577,7 @@ int Mapa::loadSeerHut( unsigned char * bufor, int i, CGObjectInstance *& nobj ) if(version>RoE) { - hut->missionType = bufor[i]; ++i; - switch(hut->missionType) - { - case 0: - i+=3; - return i; - case 1: - { - hut->m1level = readNormalNr(bufor,i); i+=4; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 2: - { - hut->m2attack = bufor[i]; ++i; - hut->m2defence = bufor[i]; ++i; - hut->m2power = bufor[i]; ++i; - hut->m2knowledge = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 3: - { - hut->m3bytes[0] = bufor[i]; ++i; - hut->m3bytes[1] = bufor[i]; ++i; - hut->m3bytes[2] = bufor[i]; ++i; - hut->m3bytes[3] = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 4: - { - hut->m4bytes[0] = bufor[i]; ++i; - hut->m4bytes[1] = bufor[i]; ++i; - hut->m4bytes[2] = bufor[i]; ++i; - hut->m4bytes[3] = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 5: - { - int artNumber = bufor[i]; ++i; - for(int yy=0; yym5arts.push_back(artid); - } - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 6: - { - int typeNumber = bufor[i]; ++i; - for(int hh=0; hhm6cre.push_back(&(VLC->creh->creatures[creType])); - hut->m6number.push_back(creNumb); - } - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 7: - { - hut->m7wood = readNormalNr(bufor,i); i+=4; - hut->m7mercury = readNormalNr(bufor,i); i+=4; - hut->m7ore = readNormalNr(bufor,i); i+=4; - hut->m7sulfur = readNormalNr(bufor,i); i+=4; - hut->m7crystal = readNormalNr(bufor,i); i+=4; - hut->m7gems = readNormalNr(bufor,i); i+=4; - hut->m7gold = readNormalNr(bufor,i); i+=4; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 8: - { - int heroType = bufor[i]; ++i; - hut->m8hero = heroType; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - case 9: - { - hut->m9player = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - hut->isDayLimit = false; - hut->lastDay = -1; - } - else - { - hut->isDayLimit = true; - hut->lastDay = limit; - } - break; - } - }//internal switch end (seer huts) - - int len1 = readNormalNr(bufor,i); i+=4; - for(int ee=0; eefirstVisitText += bufor[i]; ++i; - } - - int len2 = readNormalNr(bufor,i); i+=4; - for(int ee=0; eenextVisitText += bufor[i]; ++i; - } - - int len3 = readNormalNr(bufor,i); i+=4; - for(int ee=0; eecompletedText += bufor[i]; ++i; - } + loadQuest(hut,bufor,i); } else //RoE { @@ -1848,7 +1652,40 @@ void Mapa::readObjects( unsigned char * bufor, int &i) loadHero(nobj, bufor, i); break; } - case 54: case 71: case 72: case 73: case 74: case 75: case 162: case 163: case 164: + case 51: //Mercenary Camp + case 23: //Marletto Tower + case 61: // Star Axis + case 32: // Garden of Revelation + case 100: //Learning Stone + case 102: //Tree of Knowledge + { + nobj = new CGVisitableOPH(); + break; + } + case 55: //mystical garden + case 112://windmill + case 109://water wheel + { + nobj = new CGVisitableOPW(); + break; + } + case 43: //teleport + case 44: //teleport + case 45: //teleport + case 103://subterranean gate + { + nobj = new CGTeleport(); + break; + } + case 12: //campfire + case 101: //treasure chest + { + nobj = new CGPickable(); + break; + } + case 54: //Monster + case 71: case 72: case 73: case 74: case 75: // Random Monster 1 - 4 + case 162: case 163: case 164: // Random Monster 5 - 7 { CGCreature *cre = new CGCreature(); nobj = cre; @@ -1971,7 +1808,8 @@ void Mapa::readObjects( unsigned char * bufor, int &i) i+=8; break; } - case 5: case 65: case 66: case 67: case 68: case 69: //artifact + case 5: //artifact + case 65: case 66: case 67: case 68: case 69: //random artifact case 93: //spell scroll { CGArtifact *art = new CGArtifact(); @@ -1991,7 +1829,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i) } break; } - case 76: case 79: //resource + case 76: case 79: //random resource; resource { CGResource *res = new CGResource(); nobj = res; @@ -2011,12 +1849,22 @@ void Mapa::readObjects( unsigned char * bufor, int &i) break; } - case 77: case 98: //town + case 77: case 98: //random town; town { loadTown(nobj, bufor, i); break; } - case 53: case 17: case 18: case 19: case 20: case 42: case 87: case 220://cases 17 - 20 and 42 - tests + case 53: + { + nobj = new CGMine(); + nobj->setOwner(bufor[i++]); + i+=3; + break; + } + case 17: case 18: case 19: case 20: //dwellings + case 42: //lighthouse + case 87: //shipyard + case 220://mine (?) { nobj = new CGObjectInstance(); nobj->setOwner(bufor[i++]); @@ -2157,206 +2005,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i) { CGQuestGuard *guard = new CGQuestGuard(); nobj = guard; - guard->missionType = bufor[i]; ++i; - int len1, len2, len3; - switch(guard->missionType) - { - case 0: - { - goto borderguardend; - break; - } - case 1: - { - guard->m1level = readNormalNr(bufor,i); i+=4; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 2: - { - guard->m2attack = bufor[i]; ++i; - guard->m2defence = bufor[i]; ++i; - guard->m2power = bufor[i]; ++i; - guard->m2knowledge = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 3: - { - guard->m3bytes[0] = bufor[i]; ++i; - guard->m3bytes[1] = bufor[i]; ++i; - guard->m3bytes[2] = bufor[i]; ++i; - guard->m3bytes[3] = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 4: - { - guard->m4bytes[0] = bufor[i]; ++i; - guard->m4bytes[1] = bufor[i]; ++i; - guard->m4bytes[2] = bufor[i]; ++i; - guard->m4bytes[3] = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 5: - { - int artNumber = bufor[i]; ++i; - for(int yy=0; yym5arts.push_back(readNormalNr(bufor,i, 2)); i+=2; - } - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 6: - { - int typeNumber = bufor[i]; ++i; - for(int hh=0; hhm6cre.push_back(&(VLC->creh->creatures[creType])); - guard->m6number.push_back(creNumb); - } - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 7: - { - guard->m7wood = readNormalNr(bufor,i); i+=4; - guard->m7mercury = readNormalNr(bufor,i); i+=4; - guard->m7ore = readNormalNr(bufor,i); i+=4; - guard->m7sulfur = readNormalNr(bufor,i); i+=4; - guard->m7crystal = readNormalNr(bufor,i); i+=4; - guard->m7gems = readNormalNr(bufor,i); i+=4; - guard->m7gold = readNormalNr(bufor,i); i+=4; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 8: - { - int heroType = bufor[i]; ++i; - guard->m8hero = heroType; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - case 9: - { - guard->m9player = bufor[i]; ++i; - int limit = readNormalNr(bufor,i); i+=4; - if(limit == ((int)0xffffffff)) - { - guard->isDayLimit = false; - guard->lastDay = -1; - } - else - { - guard->isDayLimit = true; - guard->lastDay = limit; - } - break; - } - }//internal switch end (seer huts) - - len1 = readNormalNr(bufor,i); i+=4; - for(int ee=0; eefirstVisitText += bufor[i]; ++i; - } - - len2 = readNormalNr(bufor,i); i+=4; - for(int ee=0; eenextVisitText += bufor[i]; ++i; - } - - len3 = readNormalNr(bufor,i); i+=4; - for(int ee=0; eecompletedText += bufor[i]; ++i; - } -borderguardend: + loadQuest(guard, bufor, i); break; } case 214: //hero placeholder @@ -2428,3 +2077,81 @@ bool Mapa::isInTheMap( int3 pos ) return false; else return true; } + +void Mapa::loadQuest(CQuest * guard, unsigned char * bufor, int & i) +{ + guard->missionType = bufor[i]; ++i; + int len1, len2, len3; + switch(guard->missionType) + { + case 0: + return; + case 2: + { + guard->m2stats.resize(4); + for(int x=0; x<4; x++) + { + guard->m2stats[x] = bufor[i++]; + } + } + break; + case 1: + case 3: + case 4: + { + guard->m13489val = readNormalNr(bufor,i); i+=4; + break; + } + case 5: + { + int artNumber = bufor[i]; ++i; + for(int yy=0; yym5arts.push_back(readNormalNr(bufor,i, 2)); i+=2; + } + break; + } + case 6: + { + int typeNumber = bufor[i]; ++i; + for(int hh=0; hhm6creatures.push_back(std::make_pair(creType,creNumb)); + } + break; + } + case 7: + { + guard->m7resources.resize(7); + for(int x=0; x<7; x++) + { + guard->m7resources[x] = readNormalNr(bufor,i); + i+=4; + } + break; + } + case 8: + case 9: + { + guard->m13489val = bufor[i]; ++i; + break; + } + } + + + int limit = readNormalNr(bufor,i); i+=4; + if(limit == ((int)0xffffffff)) + { + guard->lastDay = -1; + } + else + { + guard->lastDay = limit; + } + + guard->firstVisitText = readString(bufor,i); + guard->nextVisitText = readString(bufor,i); + guard->completedText = readString(bufor,i); +} \ No newline at end of file diff --git a/map.h b/map.h index ef46318e8..2aeda08c4 100644 --- a/map.h +++ b/map.h @@ -1,390 +1,392 @@ -#ifndef __MAP_H__ -#define __MAP_H__ -#ifdef _MSC_VER -#pragma warning (disable : 4482) -#endif -#include -#include -#include -#include -#include "global.h" -class CGDefInfo; -class CGObjectInstance; -class CGHeroInstance; -class CGTownInstance; -enum ESortBy{_name, _playerAm, _size, _format, _viccon, _loscon}; -enum EDefType {TOWN_DEF, HERO_DEF, CREATURES_DEF, SEERHUT_DEF, RESOURCE_DEF, TERRAINOBJ_DEF, - EVENTOBJ_DEF, SIGN_DEF, GARRISON_DEF, ARTIFACT_DEF, WITCHHUT_DEF, SCHOLAR_DEF, PLAYERONLY_DEF, - SHRINE_DEF, SPELLSCROLL_DEF, PANDORA_DEF, GRAIL_DEF, CREGEN_DEF, CREGEN2_DEF, CREGEN3_DEF, - BORDERGUARD_DEF, HEROPLACEHOLDER_DEF}; - -class DLL_EXPORT CSpecObjInfo -{ -public: - virtual ~CSpecObjInfo(){}; -}; - -class DLL_EXPORT CCreGenObjInfo : public CSpecObjInfo -{ -public: - unsigned char player; //owner - bool asCastle; - int identifier; - unsigned char castles[2]; //allowed castles -}; -class DLL_EXPORT CCreGen2ObjInfo : public CSpecObjInfo -{ -public: - unsigned char player; //owner - bool asCastle; - int identifier; - unsigned char castles[2]; //allowed castles - unsigned char minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6> -}; -class DLL_EXPORT CCreGen3ObjInfo : public CSpecObjInfo -{ -public: - unsigned char player; //owner - unsigned char minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6> -}; - -struct DLL_EXPORT Sresource -{ - std::string resName; //name of this resource - int amount; //it can be greater and lesser than 0 -}; -struct DLL_EXPORT TimeEvent -{ - std::string eventName; - std::string message; - std::vector decIncRes; //decreases / increases of resources - unsigned int whichPlayers; //which players are affected by this event (+1 - first, +2 - second, +4 - third, +8 - fourth etc.) - bool areHumansAffected; - bool areCompsAffected; - int firstAfterNDays; //how many days after appears this event - int nextAfterNDays; //how many days after the epperance before appaers this event -}; -struct DLL_EXPORT TerrainTile -{ - EterrainType tertype; // type of terrain - unsigned char terview; // look of terrain - Eriver nuine; // type of Eriver (0 if there is no Eriver) - unsigned char rivDir; // direction of Eriver - Eroad malle; // type of Eroad (0 if there is no Eriver) - unsigned char roadDir; // direction of Eroad - unsigned char siodmyTajemniczyBajt; //bitfield, info whether this tile is coastal and how to rotate tile graphics - - bool visitable; //false = not visitable; true = visitable - bool blocked; //false = free; true = blocked; - - std::vector visitableObjects; //pointers to objects hero can visit while being on this tile - std::vector blockingObjects; //pointers to objects that are blocking this tile - - template void serialize(Handler &h, const int version) - { - h & tertype & terview & nuine & rivDir & malle &roadDir & siodmyTajemniczyBajt; - } -}; -struct DLL_EXPORT SheroName //name of starting hero -{ - int heroID; - std::string heroName; - - template void serialize(Handler &h, const int version) - { - h & heroID & heroName; - } -}; -struct DLL_EXPORT PlayerInfo -{ - si32 p7, p8, p9; - ui8 canHumanPlay; - ui8 canComputerPlay; - ui32 AITactic; //(00 - random, 01 - warrior, 02 - builder, 03 - explorer) - ui32 allowedFactions; //(01 - castle; 02 - rampart; 04 - tower; 08 - inferno; 16 - necropolis; 32 - dungeon; 64 - stronghold; 128 - fortress; 256 - conflux); - ui8 isFactionRandom; - ui32 mainHeroPortrait; //it's ID of hero with choosen portrait; 255 if standard - std::string mainHeroName; - std::vector heroesNames; - ui8 hasMainTown; - ui8 generateHeroAtMainTown; - int3 posOfMainTown; - ui8 team; - ui8 generateHero; - - template void serialize(Handler &h, const int version) - { - h & p7 & p8 & p9 & canHumanPlay & canComputerPlay & AITactic & allowedFactions & isFactionRandom & - mainHeroPortrait & mainHeroName & heroesNames & hasMainTown & generateHeroAtMainTown & - posOfMainTown & team & generateHero; - } -}; -struct DLL_EXPORT LossCondition -{ - ElossCon typeOfLossCon; - int3 castlePos; - int3 heroPos; - int timeLimit; // in days - - template void serialize(Handler &h, const int version) - { - h & typeOfLossCon & castlePos & heroPos & timeLimit; - } -}; -struct DLL_EXPORT CspecificVictoryConidtions -{ - bool allowNormalVictory; - bool appliesToAI; -}; -struct DLL_EXPORT VicCon0 : public CspecificVictoryConidtions //acquire artifact -{ - int ArtifactID; -}; -struct DLL_EXPORT VicCon1 : public CspecificVictoryConidtions //accumulate creatures -{ - int monsterID; - int neededQuantity; -}; -struct DLL_EXPORT VicCon2 : public CspecificVictoryConidtions // accumulate resources -{ - int resourceID; - int neededQuantity; -}; -struct DLL_EXPORT VicCon3 : public CspecificVictoryConidtions // upgrade specific town -{ - int3 posOfCity; - int councilNeededLevel; //0 - town; 1 - city; 2 - capitol - int fortNeededLevel;// 0 - fort; 1 - citadel; 2 - castle -}; -struct DLL_EXPORT VicCon4 : public CspecificVictoryConidtions // build grail structure -{ - bool anyLocation; - int3 whereBuildGrail; -}; -struct DLL_EXPORT VicCon5 : public CspecificVictoryConidtions // defeat a specific hero -{ - int3 locationOfHero; -}; -struct DLL_EXPORT VicCon6 : public CspecificVictoryConidtions // capture a specific town -{ - int3 locationOfTown; -}; -struct DLL_EXPORT VicCon7 : public CspecificVictoryConidtions // defeat a specific monster -{ - int3 locationOfMonster; -}; -struct DLL_EXPORT VicCona : public CspecificVictoryConidtions //transport specific artifact -{ - int artifactID; - int3 destinationPlace; -}; -struct DLL_EXPORT Rumor -{ - std::string name, text; - - template void serialize(Handler &h, const int version) - { - h & name & text; - } -}; - -struct DLL_EXPORT DisposedHero -{ - ui32 ID; - ui16 portrait; //0xFF - default - std::string name; - ui8 players; //who can hire this hero (bitfield) - - template void serialize(Handler &h, const int version) - { - h & ID & portrait & name & players; - } -}; - -class DLL_EXPORT CMapEvent -{ -public: - std::string name, message; - si32 wood, mercury, ore, sulfur, crystal, gems, gold; //gained / taken resources - ui8 players; //affected players - ui8 humanAffected; - ui8 computerAffected; - ui32 firstOccurence; - ui32 nextOccurence; //after nextOccurance day event will occure; if it it 0, event occures only one time; - template void serialize(Handler &h, const int version) - { - h & name & message & wood & mercury & ore & sulfur & crystal & gems & gold - & players & humanAffected & computerAffected & firstOccurence & nextOccurence; - } -}; -class DLL_EXPORT CMapHeader -{ -public: - Eformat version; // version of map Eformat - bool areAnyPLayers; // if there are any playable players on map - int height, width; - bool twoLevel; // if map has underground level - std::string name; //name of map - std::string description; //and description - int difficulty; // 0 easy - 4 impossible - int levelLimit; - LossCondition lossCondition; - EvictoryConditions victoryCondition; //victory conditions - CspecificVictoryConidtions * vicConDetails; // used only if vistory conditions aren't standard - PlayerInfo players[8]; // info about players - std::vector teams; // teams[i] = team of player no i - int howManyTeams; - CMapHeader(unsigned char *map); //an argument is a reference to string described a map (unpacked) -}; -class DLL_EXPORT CMapInfo : public CMapHeader -{ -public: - std::string filename; - int playerAmnt, humenPlayers; - CMapInfo(std::string fname, unsigned char *map):CMapHeader(map),filename(fname) - { - playerAmnt=humenPlayers=0; - for (int i=0;i rumors; - std::vector disposedHeroes; - std::vector predefinedHeroes; - std::vector defy; // list of .def files with definitions from .h3m (may be custom) - std::set defs; // other defInfos - for randomized objects, objects added or modified by scripts - PlayerInfo players[8]; // info about players - std::vector teams; // teams[i] = team of player no i - LossCondition lossCondition; - EvictoryConditions victoryCondition; //victory conditions - CspecificVictoryConidtions * vicConDetails; // used only if vistory conditions aren't standard - int howManyTeams; - std::vector allowedSpell; //allowedSpell[spell_ID] - if the spell is allowed - std::vector allowedArtifact; //allowedArtifact[artifact_ID] - if the artifact is allowed - std::vector allowedAbilities; //allowedAbilities[ability_ID] - if the ability is allowed - std::vector allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed - std::vector events; - - int3 grailPos; - int grailRadious; - - std::vector objects; - std::vector heroes; - std::vector towns; - - void initFromBytes(unsigned char * bufor); //creates map from decompressed .h3m data - - void readEvents( unsigned char * bufor, int &i); - void readObjects( unsigned char * bufor, int &i); - void readDefInfo( unsigned char * bufor, int &i); - void readTerrain( unsigned char * bufor, int &i); - void readPredefinedHeroes( unsigned char * bufor, int &i); - void readHeader( unsigned char * bufor, int &i); - void readRumors( unsigned char * bufor, int &i); - void loadViCLossConditions( unsigned char * bufor, int &i); - void loadPlayerInfo( int &pom, unsigned char * bufor, int &i); - void loadHero( CGObjectInstance * &nobj, unsigned char * bufor, int &i); - void loadTown( CGObjectInstance * &nobj, unsigned char * bufor, int &i); - int loadSeerHut( unsigned char * bufor, int i, CGObjectInstance *& nobj); - - - void addBlockVisTiles(CGObjectInstance * obj); - void removeBlockVisTiles(CGObjectInstance * obj); - Mapa(std::string filename); //creates map structure from .h3m file - CGHeroInstance * getHero(int ID, int mode=0); - bool isInTheMap(int3 pos); - template void serialize(Handler &h, const int version) - { - h & version & name & description & width & height & twoLevel & difficulty & levelLimit & rumors & defy & defs - & players & teams & lossCondition & victoryCondition & howManyTeams & allowedSpell & allowedAbilities - & allowedArtifact &allowedHeroes & events; - //TODO: viccondetails - if(h.saving) - { - //saving terrain - for (int i = 0; i < width ; i++) - for (int j = 0; j < height ; j++) - for (int k = 0; k <= twoLevel ; k++) - h & terrain[i][j][k]; - } - else - { - //loading terrain - terrain = new TerrainTile**[width]; // allocate memory - for (int ii=0;ii +#include +#include +#include +#include "global.h" +class CGDefInfo; +class CGObjectInstance; +class CGHeroInstance; +class CQuest; +class CGTownInstance; +enum ESortBy{_name, _playerAm, _size, _format, _viccon, _loscon}; +enum EDefType {TOWN_DEF, HERO_DEF, CREATURES_DEF, SEERHUT_DEF, RESOURCE_DEF, TERRAINOBJ_DEF, + EVENTOBJ_DEF, SIGN_DEF, GARRISON_DEF, ARTIFACT_DEF, WITCHHUT_DEF, SCHOLAR_DEF, PLAYERONLY_DEF, + SHRINE_DEF, SPELLSCROLL_DEF, PANDORA_DEF, GRAIL_DEF, CREGEN_DEF, CREGEN2_DEF, CREGEN3_DEF, + BORDERGUARD_DEF, HEROPLACEHOLDER_DEF}; + +class DLL_EXPORT CSpecObjInfo +{ +public: + virtual ~CSpecObjInfo(){}; +}; + +class DLL_EXPORT CCreGenObjInfo : public CSpecObjInfo +{ +public: + unsigned char player; //owner + bool asCastle; + int identifier; + unsigned char castles[2]; //allowed castles +}; +class DLL_EXPORT CCreGen2ObjInfo : public CSpecObjInfo +{ +public: + unsigned char player; //owner + bool asCastle; + int identifier; + unsigned char castles[2]; //allowed castles + unsigned char minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6> +}; +class DLL_EXPORT CCreGen3ObjInfo : public CSpecObjInfo +{ +public: + unsigned char player; //owner + unsigned char minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6> +}; + +struct DLL_EXPORT Sresource +{ + std::string resName; //name of this resource + int amount; //it can be greater and lesser than 0 +}; +struct DLL_EXPORT TimeEvent +{ + std::string eventName; + std::string message; + std::vector decIncRes; //decreases / increases of resources + unsigned int whichPlayers; //which players are affected by this event (+1 - first, +2 - second, +4 - third, +8 - fourth etc.) + bool areHumansAffected; + bool areCompsAffected; + int firstAfterNDays; //how many days after appears this event + int nextAfterNDays; //how many days after the epperance before appaers this event +}; +struct DLL_EXPORT TerrainTile +{ + EterrainType tertype; // type of terrain + unsigned char terview; // look of terrain + Eriver nuine; // type of Eriver (0 if there is no Eriver) + unsigned char rivDir; // direction of Eriver + Eroad malle; // type of Eroad (0 if there is no Eriver) + unsigned char roadDir; // direction of Eroad + unsigned char siodmyTajemniczyBajt; //bitfield, info whether this tile is coastal and how to rotate tile graphics + + bool visitable; //false = not visitable; true = visitable + bool blocked; //false = free; true = blocked; + + std::vector visitableObjects; //pointers to objects hero can visit while being on this tile + std::vector blockingObjects; //pointers to objects that are blocking this tile + + template void serialize(Handler &h, const int version) + { + h & tertype & terview & nuine & rivDir & malle &roadDir & siodmyTajemniczyBajt; + } +}; +struct DLL_EXPORT SheroName //name of starting hero +{ + int heroID; + std::string heroName; + + template void serialize(Handler &h, const int version) + { + h & heroID & heroName; + } +}; +struct DLL_EXPORT PlayerInfo +{ + si32 p7, p8, p9; + ui8 canHumanPlay; + ui8 canComputerPlay; + ui32 AITactic; //(00 - random, 01 - warrior, 02 - builder, 03 - explorer) + ui32 allowedFactions; //(01 - castle; 02 - rampart; 04 - tower; 08 - inferno; 16 - necropolis; 32 - dungeon; 64 - stronghold; 128 - fortress; 256 - conflux); + ui8 isFactionRandom; + ui32 mainHeroPortrait; //it's ID of hero with choosen portrait; 255 if standard + std::string mainHeroName; + std::vector heroesNames; + ui8 hasMainTown; + ui8 generateHeroAtMainTown; + int3 posOfMainTown; + ui8 team; + ui8 generateHero; + + template void serialize(Handler &h, const int version) + { + h & p7 & p8 & p9 & canHumanPlay & canComputerPlay & AITactic & allowedFactions & isFactionRandom & + mainHeroPortrait & mainHeroName & heroesNames & hasMainTown & generateHeroAtMainTown & + posOfMainTown & team & generateHero; + } +}; +struct DLL_EXPORT LossCondition +{ + ElossCon typeOfLossCon; + int3 castlePos; + int3 heroPos; + int timeLimit; // in days + + template void serialize(Handler &h, const int version) + { + h & typeOfLossCon & castlePos & heroPos & timeLimit; + } +}; +struct DLL_EXPORT CspecificVictoryConidtions +{ + bool allowNormalVictory; + bool appliesToAI; +}; +struct DLL_EXPORT VicCon0 : public CspecificVictoryConidtions //acquire artifact +{ + int ArtifactID; +}; +struct DLL_EXPORT VicCon1 : public CspecificVictoryConidtions //accumulate creatures +{ + int monsterID; + int neededQuantity; +}; +struct DLL_EXPORT VicCon2 : public CspecificVictoryConidtions // accumulate resources +{ + int resourceID; + int neededQuantity; +}; +struct DLL_EXPORT VicCon3 : public CspecificVictoryConidtions // upgrade specific town +{ + int3 posOfCity; + int councilNeededLevel; //0 - town; 1 - city; 2 - capitol + int fortNeededLevel;// 0 - fort; 1 - citadel; 2 - castle +}; +struct DLL_EXPORT VicCon4 : public CspecificVictoryConidtions // build grail structure +{ + bool anyLocation; + int3 whereBuildGrail; +}; +struct DLL_EXPORT VicCon5 : public CspecificVictoryConidtions // defeat a specific hero +{ + int3 locationOfHero; +}; +struct DLL_EXPORT VicCon6 : public CspecificVictoryConidtions // capture a specific town +{ + int3 locationOfTown; +}; +struct DLL_EXPORT VicCon7 : public CspecificVictoryConidtions // defeat a specific monster +{ + int3 locationOfMonster; +}; +struct DLL_EXPORT VicCona : public CspecificVictoryConidtions //transport specific artifact +{ + int artifactID; + int3 destinationPlace; +}; +struct DLL_EXPORT Rumor +{ + std::string name, text; + + template void serialize(Handler &h, const int version) + { + h & name & text; + } +}; + +struct DLL_EXPORT DisposedHero +{ + ui32 ID; + ui16 portrait; //0xFF - default + std::string name; + ui8 players; //who can hire this hero (bitfield) + + template void serialize(Handler &h, const int version) + { + h & ID & portrait & name & players; + } +}; + +class DLL_EXPORT CMapEvent +{ +public: + std::string name, message; + si32 wood, mercury, ore, sulfur, crystal, gems, gold; //gained / taken resources + ui8 players; //affected players + ui8 humanAffected; + ui8 computerAffected; + ui32 firstOccurence; + ui32 nextOccurence; //after nextOccurance day event will occure; if it it 0, event occures only one time; + template void serialize(Handler &h, const int version) + { + h & name & message & wood & mercury & ore & sulfur & crystal & gems & gold + & players & humanAffected & computerAffected & firstOccurence & nextOccurence; + } +}; +class DLL_EXPORT CMapHeader +{ +public: + Eformat version; // version of map Eformat + bool areAnyPLayers; // if there are any playable players on map + int height, width; + bool twoLevel; // if map has underground level + std::string name; //name of map + std::string description; //and description + int difficulty; // 0 easy - 4 impossible + int levelLimit; + LossCondition lossCondition; + EvictoryConditions victoryCondition; //victory conditions + CspecificVictoryConidtions * vicConDetails; // used only if vistory conditions aren't standard + PlayerInfo players[8]; // info about players + std::vector teams; // teams[i] = team of player no i + int howManyTeams; + CMapHeader(unsigned char *map); //an argument is a reference to string described a map (unpacked) +}; +class DLL_EXPORT CMapInfo : public CMapHeader +{ +public: + std::string filename; + int playerAmnt, humenPlayers; + CMapInfo(std::string fname, unsigned char *map):CMapHeader(map),filename(fname) + { + playerAmnt=humenPlayers=0; + for (int i=0;i rumors; + std::vector disposedHeroes; + std::vector predefinedHeroes; + std::vector defy; // list of .def files with definitions from .h3m (may be custom) + std::set defs; // other defInfos - for randomized objects, objects added or modified by scripts + PlayerInfo players[8]; // info about players + std::vector teams; // teams[i] = team of player no i + LossCondition lossCondition; + EvictoryConditions victoryCondition; //victory conditions + CspecificVictoryConidtions * vicConDetails; // used only if vistory conditions aren't standard + int howManyTeams; + std::vector allowedSpell; //allowedSpell[spell_ID] - if the spell is allowed + std::vector allowedArtifact; //allowedArtifact[artifact_ID] - if the artifact is allowed + std::vector allowedAbilities; //allowedAbilities[ability_ID] - if the ability is allowed + std::vector allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed + std::vector events; + + int3 grailPos; + int grailRadious; + + std::vector objects; + std::vector heroes; + std::vector towns; + + void initFromBytes(unsigned char * bufor); //creates map from decompressed .h3m data + + void readEvents( unsigned char * bufor, int &i); + void readObjects( unsigned char * bufor, int &i); + void loadQuest( CQuest * guard, unsigned char * bufor, int & i); + void readDefInfo( unsigned char * bufor, int &i); + void readTerrain( unsigned char * bufor, int &i); + void readPredefinedHeroes( unsigned char * bufor, int &i); + void readHeader( unsigned char * bufor, int &i); + void readRumors( unsigned char * bufor, int &i); + void loadViCLossConditions( unsigned char * bufor, int &i); + void loadPlayerInfo( int &pom, unsigned char * bufor, int &i); + void loadHero( CGObjectInstance * &nobj, unsigned char * bufor, int &i); + void loadTown( CGObjectInstance * &nobj, unsigned char * bufor, int &i); + int loadSeerHut( unsigned char * bufor, int i, CGObjectInstance *& nobj); + + + void addBlockVisTiles(CGObjectInstance * obj); + void removeBlockVisTiles(CGObjectInstance * obj); + Mapa(std::string filename); //creates map structure from .h3m file + CGHeroInstance * getHero(int ID, int mode=0); + bool isInTheMap(int3 pos); + template void serialize(Handler &h, const int version) + { + h & version & name & description & width & height & twoLevel & difficulty & levelLimit & rumors & defy & defs + & players & teams & lossCondition & victoryCondition & howManyTeams & allowedSpell & allowedAbilities + & allowedArtifact &allowedHeroes & events; + //TODO: viccondetails + if(h.saving) + { + //saving terrain + for (int i = 0; i < width ; i++) + for (int j = 0; j < height ; j++) + for (int k = 0; k <= twoLevel ; k++) + h & terrain[i][j][k]; + } + else + { + //loading terrain + terrain = new TerrainTile**[width]; // allocate memory + for (int ii=0;ii> id; - gs->players[*players.begin()].currentSelection = id; + SetSelection ss; + c >> ss; + sendAndApply(&ss); break; } case 515: @@ -1517,9 +1517,6 @@ void CGameHandler::init(StartInfo *si, int Seed) gs->init(si,map,Seed); tlog0 << "Gamestate initialized!" << std::endl; - - for(int i=0; imap->objects.size(); i++) - gs->map->objects[i]->initObj(); /****************************LUA OBJECT SCRIPTS************************************************/ //std::vector * lf = CLuaHandler::searchForScripts("scripts/lua/objects"); //files //for (int i=0; isize(); i++) @@ -1627,7 +1624,8 @@ void CGameHandler::newTurn() sendAndApply(&n); tlog5 << "Info about turn " << n.day << "has been sent!" << std::endl; for(size_t i = 0; imap->objects.size(); i++) - gs->map->objects[i]->newTurn(); + if(gs->map->objects[i]) + gs->map->objects[i]->newTurn(); } void CGameHandler::run() { @@ -1962,32 +1960,11 @@ void CGameHandler::setOwner(int objid, ui8 owner) SetObjectProperty sop(objid,1,owner); sendAndApply(&sop); } -const CGObjectInstance* CGameHandler::getObj(int objid) -{ - return gs->map->objects[objid]; -} -const CGHeroInstance* CGameHandler::getHero(int objid) -{ - return dynamic_cast(gs->map->objects[objid]); -} -const CGTownInstance* CGameHandler::getTown(int objid) -{ - return dynamic_cast(gs->map->objects[objid]); -} void CGameHandler::setHoverName(int objid, MetaString* name) { SetHoverName shn(objid, *name); sendAndApply(&shn); } - -int CGameHandler::getOwner(int heroID) -{ - return gs->map->objects[heroID]->tempOwner; -} -int CGameHandler::getResource(int player, int which) -{ - return gs->players.find(player)->second.resources[which]; -} void CGameHandler::showInfoDialog(InfoWindow *iw) { sendToAllClients(iw); @@ -2000,26 +1977,11 @@ void CGameHandler::showSelectionDialog(SelectionDialog *iw, const CFunctionList< { ask(iw,iw->player,callback); } - -int CGameHandler::getSelectedHero() -{ - //int ret; - //if (LOCPLINT->adventureInt->selection->ID == HEROI_TYPE) - // ret = ((CGHeroInstance*)(LOCPLINT->adventureInt->selection))->subID; - //else - // ret = -1;; - return -1; -} - -const CGHeroInstance* CGameHandler::getSelectedHero( int player ) +int CGameHandler::getCurrentPlayer() { - return getHero(gs->players.find(player)->second.currentSelection); + return gs->currentPlayer; } -int CGameHandler::getDate(int mode) -{ - return getDate(mode); -} void CGameHandler::giveResource(int player, int which, int val) { SetResource sr; @@ -2108,7 +2070,16 @@ void CGameHandler::changeSpells( int hid, bool give, const std::set &spell sendAndApply(&cs); } -int CGameHandler::getCurrentPlayer() +int CGameHandler::getSelectedHero() { - return gs->currentPlayer; + return IGameCallback::getSelectedHero(getCurrentPlayer())->id; +} + +void CGameHandler::setObjProperty( int objid, int prop, int val ) +{ + SetObjectProperty sob; + sob.id = objid; + sob.what = prop; + sob.val = val; + sendAndApply(&sob); } \ No newline at end of file diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 4a77c13db..031353b81 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -1,173 +1,167 @@ -#ifndef __CGAMEHANDLER_H__ -#define __CGAMEHANDLER_H__ - -#include "../global.h" -#include -#include "../client/FunctionList.h" -#include "../CGameState.h" -#include "../lib/Connection.h" -#include "../lib/IGameCallback.h" -#include -#include -class CVCMIServer; -class CGameState; -struct StartInfo; -class CCPPObjectScript; -class CScriptCallback; -struct BattleResult; -struct BattleAttack; -struct BattleStackAttacked; -template struct CPack; -template struct Query; -class CGHeroInstance; -extern std::map > callbacks; //question id => callback functions - for selection dialogs -extern boost::mutex gsm; - -struct PlayerStatus -{ - bool makingTurn, engagedIntoBattle; - std::set queries; - - PlayerStatus():makingTurn(false),engagedIntoBattle(false){}; - template void serialize(Handler &h, const int version) - { - h & makingTurn & engagedIntoBattle & queries; - } -}; -class PlayerStatuses -{ -public: - std::map players; - boost::mutex mx; - boost::condition_variable cv; //notifies when any changes are made - - void addPlayer(ui8 player); - PlayerStatus operator[](ui8 player); - bool hasQueries(ui8 player); - bool checkFlag(ui8 player, bool PlayerStatus::*flag); - void setFlag(ui8 player, bool PlayerStatus::*flag, bool val); - void addQuery(ui8 player, ui32 id); - void removeQuery(ui8 player, ui32 id); - template void serialize(Handler &h, const int version) - { - h & players; - } -}; - -class CGameHandler : public IGameCallback -{ - static ui32 QID; - CGameState *gs; - //std::set cppscripts; //C++ scripts - //std::map > objscr; //non-C++ scripts - - CVCMIServer *s; - std::map connections; //player color -> connection to clinet with interface of that player - PlayerStatuses states; //player color -> player state - std::set conns; - - void changeSecSkill(int ID, ui16 which, int val, bool abs=false); - void giveSpells(const CGTownInstance *t, const CGHeroInstance *h); - void moveStack(int stack, int dest); - void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero - void prepareAttack(BattleAttack &bat, CStack *att, CStack *def); //if last parameter is true, attack is by shooting, if false it's a melee attack - void prepareAttacked(BattleStackAttacked &bsa, CStack *def); - void checkForBattleEnd( std::vector &stacks ); - void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 ); - -public: - CGameHandler(void); - ~CGameHandler(void); - - ////////////////////////////////////////////////////////////////////////// - //from IGameCallback - //get info - int getOwner(int heroID); - int getResource(int player, int which); - int getSelectedHero(); - int getDate(int mode=0); - const CGObjectInstance* getObj(int objid); - const CGHeroInstance* getHero(int objid); - const CGTownInstance* getTown(int objid); - const CGHeroInstance* getSelectedHero(int player); //NULL if no hero is selected - int getCurrentPlayer(); - - //do sth - void changeSpells(int hid, bool give, const std::set &spells); - void removeObject(int objid); - void setBlockVis(int objid, bool bv); - void setOwner(int objid, ui8 owner); - void setHoverName(int objid, MetaString * name); - void changePrimSkill(int ID, int which, int val, bool abs=false); - void showInfoDialog(InfoWindow *iw); - void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback); - void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback); //returns question id - void giveResource(int player, int which, int val); - void showCompInfo(ShowInInfobox * comp); - void heroVisitCastle(int obj, int heroID); - void stopHeroVisitCastle(int obj, int heroID); - void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack - void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero - void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb); //for hero<=>neutral army - void setAmount(int objid, ui32 val); - void moveHero(int hid, int3 pos, bool instant); - ////////////////////////////////////////////////////////////////////////// - - void init(StartInfo *si, int Seed); - void handleConnection(std::set players, CConnection &c); - template void serialize(Handler &h, const int version) - { - h & QID & gs & states; - } - template void applyAndAsk(Query * sel, ui8 player, boost::function &callback) - { - gsm.lock(); - sel->id = QID; - callbacks[QID] = callback; - states.addQuery(player,QID); - QID++; - sendAndApply(sel); - gsm.unlock(); - } - template void ask(Query * sel, ui8 player, const CFunctionList &callback) - { - gsm.lock(); - sel->id = QID; - callbacks[QID] = callback; - states.addQuery(player,QID); - sendToAllClients(sel); - QID++; - gsm.unlock(); - } - - template void sendDataToClients(const T & data) - { - for(std::set::iterator i=conns.begin(); i!=conns.end();i++) - { - (*i)->wmx->lock(); - **i << data; - (*i)->wmx->unlock(); - } - } - template void sendToAllClients(CPack * info) - { - for(std::set::iterator i=conns.begin(); i!=conns.end();i++) - { - (*i)->wmx->lock(); - **i << info->getType() << *info->This(); - (*i)->wmx->unlock(); - } - } - template void sendAndApply(CPack * info) - { - gs->apply(info); - sendToAllClients(info); - } - void run(); - void newTurn(); - - friend class CVCMIServer; - friend class CScriptCallback; -}; - -#endif // __CGAMEHANDLER_H__ +#ifndef __CGAMEHANDLER_H__ +#define __CGAMEHANDLER_H__ + +#include "../global.h" +#include +#include "../client/FunctionList.h" +#include "../CGameState.h" +#include "../lib/Connection.h" +#include "../lib/IGameCallback.h" +#include +#include +class CVCMIServer; +class CGameState; +struct StartInfo; +class CCPPObjectScript; +class CScriptCallback; +struct BattleResult; +struct BattleAttack; +struct BattleStackAttacked; +template struct CPack; +template struct Query; +class CGHeroInstance; +extern std::map > callbacks; //question id => callback functions - for selection dialogs +extern boost::mutex gsm; + +struct PlayerStatus +{ + bool makingTurn, engagedIntoBattle; + std::set queries; + + PlayerStatus():makingTurn(false),engagedIntoBattle(false){}; + template void serialize(Handler &h, const int version) + { + h & makingTurn & engagedIntoBattle & queries; + } +}; +class PlayerStatuses +{ +public: + std::map players; + boost::mutex mx; + boost::condition_variable cv; //notifies when any changes are made + + void addPlayer(ui8 player); + PlayerStatus operator[](ui8 player); + bool hasQueries(ui8 player); + bool checkFlag(ui8 player, bool PlayerStatus::*flag); + void setFlag(ui8 player, bool PlayerStatus::*flag, bool val); + void addQuery(ui8 player, ui32 id); + void removeQuery(ui8 player, ui32 id); + template void serialize(Handler &h, const int version) + { + h & players; + } +}; + +class CGameHandler : public IGameCallback +{ + static ui32 QID; + //std::set cppscripts; //C++ scripts + //std::map > objscr; //non-C++ scripts + + CVCMIServer *s; + std::map connections; //player color -> connection to clinet with interface of that player + PlayerStatuses states; //player color -> player state + std::set conns; + + void changeSecSkill(int ID, ui16 which, int val, bool abs=false); + void giveSpells(const CGTownInstance *t, const CGHeroInstance *h); + void moveStack(int stack, int dest); + void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero + void prepareAttack(BattleAttack &bat, CStack *att, CStack *def); //if last parameter is true, attack is by shooting, if false it's a melee attack + void prepareAttacked(BattleStackAttacked &bsa, CStack *def); + void checkForBattleEnd( std::vector &stacks ); + void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 ); + +public: + CGameHandler(void); + ~CGameHandler(void); + + ////////////////////////////////////////////////////////////////////////// + //from IGameCallback + //get info + int getCurrentPlayer(); + int getSelectedHero(); + + + //do sth + void changeSpells(int hid, bool give, const std::set &spells); + void removeObject(int objid); + void setBlockVis(int objid, bool bv); + void setOwner(int objid, ui8 owner); + void setHoverName(int objid, MetaString * name); + void setObjProperty(int objid, int prop, int val); + void changePrimSkill(int ID, int which, int val, bool abs=false); + void showInfoDialog(InfoWindow *iw); + void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback); + void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback); //returns question id + void giveResource(int player, int which, int val); + void showCompInfo(ShowInInfobox * comp); + void heroVisitCastle(int obj, int heroID); + void stopHeroVisitCastle(int obj, int heroID); + void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack + void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero + void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb); //for hero<=>neutral army + void setAmount(int objid, ui32 val); + void moveHero(int hid, int3 pos, bool instant); + ////////////////////////////////////////////////////////////////////////// + + void init(StartInfo *si, int Seed); + void handleConnection(std::set players, CConnection &c); + template void serialize(Handler &h, const int version) + { + h & QID & gs & states; + } + template void applyAndAsk(Query * sel, ui8 player, boost::function &callback) + { + gsm.lock(); + sel->id = QID; + callbacks[QID] = callback; + states.addQuery(player,QID); + QID++; + sendAndApply(sel); + gsm.unlock(); + } + template void ask(Query * sel, ui8 player, const CFunctionList &callback) + { + gsm.lock(); + sel->id = QID; + callbacks[QID] = callback; + states.addQuery(player,QID); + sendToAllClients(sel); + QID++; + gsm.unlock(); + } + + template void sendDataToClients(const T & data) + { + for(std::set::iterator i=conns.begin(); i!=conns.end();i++) + { + (*i)->wmx->lock(); + **i << data; + (*i)->wmx->unlock(); + } + } + template void sendToAllClients(CPack * info) + { + for(std::set::iterator i=conns.begin(); i!=conns.end();i++) + { + (*i)->wmx->lock(); + **i << info->getType() << *info->This(); + (*i)->wmx->unlock(); + } + } + template void sendAndApply(CPack * info) + { + gs->apply(info); + sendToAllClients(info); + } + void run(); + void newTurn(); + + friend class CVCMIServer; + friend class CScriptCallback; +}; + +#endif // __CGAMEHANDLER_H__