mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-02 00:10:22 +02:00
Big change: Introduced new mechanism to handle queries. It should not cause any visible changes ATM apart from fixing several long-standing bugs realted to handling post-visit/battle/levelup callback, including infamous creature bank issues: #955, #1053, #1063, #1191. Needs testing.
Minor changes: * default log level set to trace * LOG_TRACE raii guardian lifetime will last till the end of block * compile fixes * minor refactorings
This commit is contained in:
parent
1fca335a2c
commit
e8354908c3
@ -43,24 +43,6 @@ struct SetGlobalState
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Container>
|
|
||||||
typename Container::value_type backOrNull(const Container &c) //returns last element of container or NULL if it is empty (to be used with containers of pointers)
|
|
||||||
{
|
|
||||||
if(c.size())
|
|
||||||
return c.back();
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Container>
|
|
||||||
typename Container::value_type frontOrNull(const Container &c) //returns first element of container or NULL if it is empty (to be used with containers of pointers)
|
|
||||||
{
|
|
||||||
if(c.size())
|
|
||||||
return c.front();
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define SET_GLOBAL_STATE(ai) SetGlobalState _hlpSetState(ai);
|
#define SET_GLOBAL_STATE(ai) SetGlobalState _hlpSetState(ai);
|
||||||
|
|
||||||
@ -793,7 +775,7 @@ void VCAI::heroManaPointsChanged(const CGHeroInstance * hero)
|
|||||||
|
|
||||||
void VCAI::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val)
|
void VCAI::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val)
|
||||||
{
|
{
|
||||||
LOG_TRACE_PARAMS(logAi, "which '%', val '%'", which % val);
|
LOG_TRACE_PARAMS(logAi, "which '%d', val '%d'", which % val);
|
||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2579,6 +2561,7 @@ AIStatus::~AIStatus()
|
|||||||
void AIStatus::setBattle(BattleState BS)
|
void AIStatus::setBattle(BattleState BS)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(mx);
|
boost::unique_lock<boost::mutex> lock(mx);
|
||||||
|
LOG_TRACE_PARAMS(logAi, "battle state=%d", (int)BS);
|
||||||
battle = BS;
|
battle = BS;
|
||||||
cv.notify_all();
|
cv.notify_all();
|
||||||
}
|
}
|
||||||
|
18
Global.h
18
Global.h
@ -568,6 +568,24 @@ namespace vstd
|
|||||||
{
|
{
|
||||||
obj = (T)(((int)obj) + change);
|
obj = (T)(((int)obj) + change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
typename Container::value_type backOrNull(const Container &c) //returns last element of container or NULL if it is empty (to be used with containers of pointers)
|
||||||
|
{
|
||||||
|
if(c.size())
|
||||||
|
return c.back();
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
typename Container::value_type frontOrNull(const Container &c) //returns first element of container or NULL if it is empty (to be used with containers of pointers)
|
||||||
|
{
|
||||||
|
if(c.size())
|
||||||
|
return c.front();
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
using vstd::operator-=;
|
using vstd::operator-=;
|
||||||
using vstd::make_unique;
|
using vstd::make_unique;
|
||||||
|
@ -17,4 +17,4 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -176,7 +176,9 @@ static void prog_help(const po::options_description &opts)
|
|||||||
void OSX_checkForUpdates();
|
void OSX_checkForUpdates();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#ifdef _WIN32
|
||||||
|
int wmain(int argc, wchar_t* argv[])
|
||||||
|
#elif defined(__APPLE__)
|
||||||
int SDL_main(int argc, char *argv[])
|
int SDL_main(int argc, char *argv[])
|
||||||
#else
|
#else
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
@ -230,10 +230,10 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
|||||||
if(LOCPLINT != this)
|
if(LOCPLINT != this)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const CGHeroInstance * ho = cb->getHero(details.id); //object representing this hero
|
const CGHeroInstance * hero = cb->getHero(details.id); //object representing this hero
|
||||||
int3 hp = details.start;
|
int3 hp = details.start;
|
||||||
|
|
||||||
if(!ho)
|
if(!hero)
|
||||||
{
|
{
|
||||||
//AI hero left the visible area (we can't obtain info)
|
//AI hero left the visible area (we can't obtain info)
|
||||||
//TODO very evil workaround -> retreive pointer to hero so we could animate it
|
//TODO very evil workaround -> retreive pointer to hero so we could animate it
|
||||||
@ -241,25 +241,25 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
|||||||
const TerrainTile2 &tile = CGI->mh->ttiles[hp.x-1][hp.y][hp.z];
|
const TerrainTile2 &tile = CGI->mh->ttiles[hp.x-1][hp.y][hp.z];
|
||||||
for(int i = 0; i < tile.objects.size(); i++)
|
for(int i = 0; i < tile.objects.size(); i++)
|
||||||
if(tile.objects[i].first->id == details.id)
|
if(tile.objects[i].first->id == details.id)
|
||||||
ho = dynamic_cast<const CGHeroInstance *>(tile.objects[i].first);
|
hero = dynamic_cast<const CGHeroInstance *>(tile.objects[i].first);
|
||||||
|
|
||||||
if(!ho) //still nothing...
|
if(!hero) //still nothing...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
adventureInt->centerOn(ho); //actualizing screen pos
|
adventureInt->centerOn(hero); //actualizing screen pos
|
||||||
adventureInt->minimap.redraw();
|
adventureInt->minimap.redraw();
|
||||||
adventureInt->heroList.redraw();
|
adventureInt->heroList.redraw();
|
||||||
|
|
||||||
bool directlyAttackingCreature =
|
bool directlyAttackingCreature =
|
||||||
CGI->mh->map->isInTheMap(details.attackedFrom)
|
details.attackedFrom
|
||||||
&& adventureInt->terrain.currentPath //in case if movement has been canceled in the meantime and path was already erased
|
&& adventureInt->terrain.currentPath //in case if movement has been canceled in the meantime and path was already erased
|
||||||
&& adventureInt->terrain.currentPath->nodes.size() == 3;//FIXME should be 2 but works nevertheless...
|
&& adventureInt->terrain.currentPath->nodes.size() == 3;//FIXME should be 2 but works nevertheless...
|
||||||
|
|
||||||
if(makingTurn && ho->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
|
if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
|
||||||
{
|
{
|
||||||
//We may need to change music - select new track, music handler will change it if needed
|
//We may need to change music - select new track, music handler will change it if needed
|
||||||
CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(ho->visitablePos())->terType, true);
|
CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType, true);
|
||||||
|
|
||||||
if(details.result == TryMoveHero::TELEPORTATION)
|
if(details.result == TryMoveHero::TELEPORTATION)
|
||||||
{
|
{
|
||||||
@ -272,42 +272,42 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
|||||||
&& (nodesIt-1)->coord == CGHeroInstance::convertPosition(details.end, false))
|
&& (nodesIt-1)->coord == CGHeroInstance::convertPosition(details.end, false))
|
||||||
{
|
{
|
||||||
//path was between entrance and exit of teleport -> OK, erase node as usual
|
//path was between entrance and exit of teleport -> OK, erase node as usual
|
||||||
removeLastNodeFromPath(ho);
|
removeLastNodeFromPath(hero);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//teleport was not along current path, it'll now be invalid (hero is somewhere else)
|
//teleport was not along current path, it'll now be invalid (hero is somewhere else)
|
||||||
eraseCurrentPathOf(ho);
|
eraseCurrentPathOf(hero);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adventureInt->heroList.update(ho);
|
adventureInt->heroList.update(hero);
|
||||||
return; //teleport - no fancy moving animation
|
return; //teleport - no fancy moving animation
|
||||||
//TODO: smooth disappear / appear effect
|
//TODO: smooth disappear / appear effect
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ho->pos != details.end //hero didn't change tile but visit succeeded
|
if (hero->pos != details.end //hero didn't change tile but visit succeeded
|
||||||
|| directlyAttackingCreature) // or creature was attacked from endangering tile.
|
|| directlyAttackingCreature) // or creature was attacked from endangering tile.
|
||||||
{
|
{
|
||||||
eraseCurrentPathOf(ho, false);
|
eraseCurrentPathOf(hero, false);
|
||||||
}
|
}
|
||||||
else if(adventureInt->terrain.currentPath && ho->pos == details.end) //&& hero is moving
|
else if(adventureInt->terrain.currentPath && hero->pos == details.end) //&& hero is moving
|
||||||
{
|
{
|
||||||
if(details.start != details.end) //so we don't touch path when revisiting with spacebar
|
if(details.start != details.end) //so we don't touch path when revisiting with spacebar
|
||||||
removeLastNodeFromPath(ho);
|
removeLastNodeFromPath(hero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details.result != TryMoveHero::SUCCESS) //hero failed to move
|
if (details.result != TryMoveHero::SUCCESS) //hero failed to move
|
||||||
{
|
{
|
||||||
ho->isStanding = true;
|
hero->isStanding = true;
|
||||||
stillMoveHero.setn(STOP_MOVE);
|
stillMoveHero.setn(STOP_MOVE);
|
||||||
GH.totalRedraw();
|
GH.totalRedraw();
|
||||||
adventureInt->heroList.update(ho);
|
adventureInt->heroList.update(hero);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
initMovement(details, ho, hp);
|
initMovement(details, hero, hp);
|
||||||
|
|
||||||
//first initializing done
|
//first initializing done
|
||||||
GH.mainFPSmng->framerateDelay(); // after first move
|
GH.mainFPSmng->framerateDelay(); // after first move
|
||||||
@ -316,7 +316,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
|||||||
//main moving
|
//main moving
|
||||||
for(int i=1; i<32; i+=2*speed)
|
for(int i=1; i<32; i+=2*speed)
|
||||||
{
|
{
|
||||||
movementPxStep(details, i, hp, ho);
|
movementPxStep(details, i, hp, hero);
|
||||||
adventureInt->updateScreen = true;
|
adventureInt->updateScreen = true;
|
||||||
adventureInt->show(screen);
|
adventureInt->show(screen);
|
||||||
CSDL_Ext::update(screen);
|
CSDL_Ext::update(screen);
|
||||||
@ -325,12 +325,12 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
|||||||
//main moving done
|
//main moving done
|
||||||
|
|
||||||
//finishing move
|
//finishing move
|
||||||
finishMovement(details, hp, ho);
|
finishMovement(details, hp, hero);
|
||||||
ho->isStanding = true;
|
hero->isStanding = true;
|
||||||
|
|
||||||
//move finished
|
//move finished
|
||||||
adventureInt->minimap.redraw();
|
adventureInt->minimap.redraw();
|
||||||
adventureInt->heroList.update(ho);
|
adventureInt->heroList.update(hero);
|
||||||
|
|
||||||
//check if user cancelled movement
|
//check if user cancelled movement
|
||||||
{
|
{
|
||||||
@ -358,14 +358,14 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
|||||||
// Hero attacked creature directly, set direction to face it.
|
// Hero attacked creature directly, set direction to face it.
|
||||||
if (directlyAttackingCreature) {
|
if (directlyAttackingCreature) {
|
||||||
// Get direction to attacker.
|
// Get direction to attacker.
|
||||||
int3 posOffset = details.attackedFrom - details.end + int3(2, 1, 0);
|
int3 posOffset = *details.attackedFrom - details.end + int3(2, 1, 0);
|
||||||
static const ui8 dirLookup[3][3] = {
|
static const ui8 dirLookup[3][3] = {
|
||||||
{ 1, 2, 3 },
|
{ 1, 2, 3 },
|
||||||
{ 8, 0, 4 },
|
{ 8, 0, 4 },
|
||||||
{ 7, 6, 5 }
|
{ 7, 6, 5 }
|
||||||
};
|
};
|
||||||
// FIXME: Avoid const_cast, make moveDir mutable in some other way?
|
// FIXME: Avoid const_cast, make moveDir mutable in some other way?
|
||||||
const_cast<CGHeroInstance *>(ho)->moveDir = dirLookup[posOffset.y][posOffset.x];
|
const_cast<CGHeroInstance *>(hero)->moveDir = dirLookup[posOffset.y][posOffset.x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
|
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
|
||||||
|
@ -170,11 +170,12 @@ public:
|
|||||||
void setHoverName(const CGObjectInstance * obj, MetaString * name) OVERRIDE {};
|
void setHoverName(const CGObjectInstance * obj, MetaString * name) OVERRIDE {};
|
||||||
void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) OVERRIDE {};
|
void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) OVERRIDE {};
|
||||||
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) OVERRIDE {};
|
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) OVERRIDE {};
|
||||||
void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback) OVERRIDE {};
|
|
||||||
ui32 showBlockingDialog(BlockingDialog *iw) OVERRIDE {return 0;}; //synchronous version of above
|
void showBlockingDialog(BlockingDialog *iw) OVERRIDE {};
|
||||||
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE {};
|
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE {};
|
||||||
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE {};
|
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE {};
|
||||||
void giveResource(PlayerColor player, Res::ERes which, int val) OVERRIDE {};
|
void giveResource(PlayerColor player, Res::ERes which, int val) OVERRIDE {};
|
||||||
|
virtual void giveResources(PlayerColor player, TResources resources) OVERRIDE {};
|
||||||
|
|
||||||
void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE {};
|
void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE {};
|
||||||
void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE {};
|
void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE {};
|
||||||
@ -199,11 +200,11 @@ public:
|
|||||||
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE {};
|
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE {};
|
||||||
//void giveHeroArtifact(int artid, int hid, int position){};
|
//void giveHeroArtifact(int artid, int hid, int position){};
|
||||||
//void giveNewArtifact(int hid, int position){};
|
//void giveNewArtifact(int hid, int position){};
|
||||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL) OVERRIDE {}; //use hero=NULL for no hero
|
void startBattlePrimary(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, const CGTownInstance *town = NULL) OVERRIDE {}; //use hero=NULL for no hero
|
||||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used
|
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used
|
||||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
|
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
|
||||||
void setAmount(ObjectInstanceID objid, ui32 val) OVERRIDE {};
|
void setAmount(ObjectInstanceID objid, ui32 val) OVERRIDE {};
|
||||||
bool moveHero(ObjectInstanceID hid, int3 dst, ui8 instant, PlayerColor asker = PlayerColor::NEUTRAL) OVERRIDE {return false;};
|
bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) OVERRIDE {return false;};
|
||||||
void giveHeroBonus(GiveBonus * bonus) OVERRIDE {};
|
void giveHeroBonus(GiveBonus * bonus) OVERRIDE {};
|
||||||
void setMovePoints(SetMovePoints * smp) OVERRIDE {};
|
void setMovePoints(SetMovePoints * smp) OVERRIDE {};
|
||||||
void setManaPoints(ObjectInstanceID hid, int val) OVERRIDE {};
|
void setManaPoints(ObjectInstanceID hid, int val) OVERRIDE {};
|
||||||
|
@ -545,11 +545,10 @@ void SetObjectProperty::applyCl( CClient *cl )
|
|||||||
|
|
||||||
void HeroLevelUp::applyCl( CClient *cl )
|
void HeroLevelUp::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
const CGHeroInstance *h = cl->getHero(heroid);
|
|
||||||
//INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroGotLevel, h, primskill, skills, id);
|
//INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroGotLevel, h, primskill, skills, id);
|
||||||
if(vstd::contains(cl->playerint,h->tempOwner))
|
if(vstd::contains(cl->playerint,hero->tempOwner))
|
||||||
{
|
{
|
||||||
cl->playerint[h->tempOwner]->heroGotLevel(h, primskill, skills, queryID);
|
cl->playerint[hero->tempOwner]->heroGotLevel(hero, primskill, skills, queryID);
|
||||||
}
|
}
|
||||||
//else
|
//else
|
||||||
// cb->selectionMade(0, queryID);
|
// cb->selectionMade(0, queryID);
|
||||||
@ -557,9 +556,9 @@ void HeroLevelUp::applyCl( CClient *cl )
|
|||||||
|
|
||||||
void CommanderLevelUp::applyCl( CClient *cl )
|
void CommanderLevelUp::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
CCommanderInstance * commander = GS(cl)->getHero(heroid)->commander;
|
const CCommanderInstance * commander = hero->commander;
|
||||||
assert (commander);
|
assert (commander);
|
||||||
PlayerColor player = commander->armyObj->tempOwner;
|
PlayerColor player = hero->tempOwner;
|
||||||
if (commander->armyObj && vstd::contains(cl->playerint, player)) //is it possible for Commander to exist beyond armed instance?
|
if (commander->armyObj && vstd::contains(cl->playerint, player)) //is it possible for Commander to exist beyond armed instance?
|
||||||
{
|
{
|
||||||
cl->playerint[player]->commanderGotLevel(commander, skills, queryID);
|
cl->playerint[player]->commanderGotLevel(commander, skills, queryID);
|
||||||
|
@ -207,7 +207,7 @@
|
|||||||
},
|
},
|
||||||
"loggers" : {
|
"loggers" : {
|
||||||
"type" : "array",
|
"type" : "array",
|
||||||
"default" : [ { "domain" : "global", "level" : "info" } ],
|
"default" : [ { "domain" : "global", "level" : "trace" } ],
|
||||||
"items" : {
|
"items" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
|
@ -741,6 +741,11 @@ ArtBearer::ArtBearer CCommanderInstance::bearerType() const
|
|||||||
return ArtBearer::COMMANDER;
|
return ArtBearer::COMMANDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCommanderInstance::gainsLevel() const
|
||||||
|
{
|
||||||
|
return experience >= VLC->heroh->reqExp(level+1);
|
||||||
|
}
|
||||||
|
|
||||||
CStackBasicDescriptor::CStackBasicDescriptor()
|
CStackBasicDescriptor::CStackBasicDescriptor()
|
||||||
{
|
{
|
||||||
type = NULL;
|
type = NULL;
|
||||||
|
@ -103,6 +103,7 @@ public:
|
|||||||
void giveStackExp (TExpType exp);
|
void giveStackExp (TExpType exp);
|
||||||
void levelUp ();
|
void levelUp ();
|
||||||
|
|
||||||
|
bool gainsLevel() const; //true if commander has lower level than should upon his experience
|
||||||
ui64 getPower() const {return 0;};
|
ui64 getPower() const {return 0;};
|
||||||
int getExpRank() const;
|
int getExpRank() const;
|
||||||
int getLevel() const OVERRIDE;
|
int getLevel() const OVERRIDE;
|
||||||
|
@ -3196,7 +3196,7 @@ CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const TerrainTile
|
|||||||
{
|
{
|
||||||
BOOST_FOREACH(const CGObjectInstance *obj, tinfo->visitableObjects)
|
BOOST_FOREACH(const CGObjectInstance *obj, tinfo->visitableObjects)
|
||||||
{
|
{
|
||||||
if(obj->getPassableness() & 1<<hero->tempOwner.getNum()) //special object instance specific passableness flag - overwrites other accessibility flags
|
if(obj->passableFor(hero->tempOwner)) //special object instance specific passableness flag - overwrites other accessibility flags
|
||||||
{
|
{
|
||||||
ret = CGPathNode::ACCESSIBLE;
|
ret = CGPathNode::ACCESSIBLE;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -113,6 +113,13 @@ public:
|
|||||||
virtual void newTurn() const;
|
virtual void newTurn() const;
|
||||||
virtual void initObj(); //synchr
|
virtual void initObj(); //synchr
|
||||||
virtual void setProperty(ui8 what, ui32 val);//synchr
|
virtual void setProperty(ui8 what, ui32 val);//synchr
|
||||||
|
|
||||||
|
//Called when queries created DURING HERO VISIT are resolved
|
||||||
|
//First parameter is always hero that visited object and triggered the query
|
||||||
|
virtual void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const;
|
||||||
|
virtual void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const;
|
||||||
|
virtual void garrisonDialogClosed(const CGHeroInstance *hero) const;
|
||||||
|
|
||||||
//unified interface, AI helpers
|
//unified interface, AI helpers
|
||||||
virtual bool wasVisited (PlayerColor player) const;
|
virtual bool wasVisited (PlayerColor player) const;
|
||||||
virtual bool wasVisited (const CGHeroInstance * h) const;
|
virtual bool wasVisited (const CGHeroInstance * h) const;
|
||||||
@ -179,6 +186,7 @@ public:
|
|||||||
virtual ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used
|
virtual ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used
|
||||||
virtual int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
|
virtual int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
|
||||||
virtual int getSightRadious() const; //sight distance (should be used if player-owned structure)
|
virtual int getSightRadious() const; //sight distance (should be used if player-owned structure)
|
||||||
|
bool passableFor(PlayerColor color) const;
|
||||||
void getSightTiles(boost::unordered_set<int3, ShashInt3> &tiles) const; //returns reference to the set
|
void getSightTiles(boost::unordered_set<int3, ShashInt3> &tiles) const; //returns reference to the set
|
||||||
PlayerColor getOwner() const;
|
PlayerColor getOwner() const;
|
||||||
void setOwner(PlayerColor ow);
|
void setOwner(PlayerColor ow);
|
||||||
@ -396,6 +404,8 @@ public:
|
|||||||
CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
|
CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
|
||||||
void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
|
void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
|
||||||
ECanDig diggingStatus() const; //0 - can dig; 1 - lack of movement; 2 -
|
ECanDig diggingStatus() const; //0 - can dig; 1 - lack of movement; 2 -
|
||||||
|
std::vector<SecondarySkill> levelUpProposedSkills() const;
|
||||||
|
bool gainsLevel() const; //true if hero has lower level than should upon his experience
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -471,10 +481,11 @@ public:
|
|||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void newTurn() const override;
|
void newTurn() const override;
|
||||||
void setProperty(ui8 what, ui32 val) override;
|
void setProperty(ui8 what, ui32 val) override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void heroAcceptsCreatures(const CGHeroInstance *h, ui32 answer) const;
|
void heroAcceptsCreatures(const CGHeroInstance *h) const;
|
||||||
void fightOver(const CGHeroInstance *h, BattleResult *result) const;
|
|
||||||
void wantsFight(const CGHeroInstance *h, ui32 answer) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -482,25 +493,26 @@ class DLL_LINKAGE CGVisitableOPH : public CGObjectInstance //objects visitable o
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::set<ObjectInstanceID> visitors; //ids of heroes who have visited this obj
|
std::set<ObjectInstanceID> 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
|
TResources treePrice; //used only by trees of knowledge: empty, 2000 gold, 10 gems
|
||||||
|
|
||||||
const std::string & getHoverText() const override;
|
const std::string & getHoverText() const override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
bool wasVisited (const CGHeroInstance * h) const override;
|
bool wasVisited (const CGHeroInstance * h) const override;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CGObjectInstance&>(*this);
|
h & static_cast<CGObjectInstance&>(*this);
|
||||||
h & visitors & ttype;
|
h & visitors & treePrice;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void setPropertyDer(ui8 what, ui32 val) override;//synchr
|
void setPropertyDer(ui8 what, ui32 val) override;//synchr
|
||||||
private:
|
private:
|
||||||
void onNAHeroVisit(ObjectInstanceID heroID, bool alreadyVisited) const;
|
void onNAHeroVisit(ObjectInstanceID heroID, bool alreadyVisited) const;
|
||||||
///dialog callbacks
|
///dialog callbacks
|
||||||
void treeSelected(ObjectInstanceID heroID, int resType, int resVal, TExpType expVal, ui32 result) const;
|
void treeSelected(ObjectInstanceID heroID, ui32 result) const;
|
||||||
void schoolSelected(ObjectInstanceID heroID, ui32 which) const;
|
void schoolSelected(ObjectInstanceID heroID, ui32 which) const;
|
||||||
void arenaSelected(ObjectInstanceID heroID, int primSkill) const;
|
void arenaSelected(ObjectInstanceID heroID, int primSkill) const;
|
||||||
};
|
};
|
||||||
@ -662,11 +674,9 @@ public:
|
|||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void onHeroLeave(const CGHeroInstance * h) const override;
|
void onHeroLeave(const CGHeroInstance * h) const override;
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
protected:
|
protected:
|
||||||
void setPropertyDer(ui8 what, ui32 val) override;
|
void setPropertyDer(ui8 what, ui32 val) override;
|
||||||
private:
|
|
||||||
///dialog callbacks
|
|
||||||
void fightOver(const CGHeroInstance *h, BattleResult *result) const;
|
|
||||||
};
|
};
|
||||||
class DLL_LINKAGE CGPandoraBox : public CArmedInstance
|
class DLL_LINKAGE CGPandoraBox : public CArmedInstance
|
||||||
{
|
{
|
||||||
@ -688,6 +698,8 @@ public:
|
|||||||
|
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -696,10 +708,8 @@ public:
|
|||||||
& abilities & abilityLevels & artifacts & spells & creatures;
|
& abilities & abilityLevels & artifacts & spells & creatures;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void endBattle(const CGHeroInstance *h, BattleResult *result) const;
|
|
||||||
void giveContents(const CGHeroInstance *h, bool afterBattle) const;
|
void giveContents(const CGHeroInstance *h, bool afterBattle) const;
|
||||||
private:
|
private:
|
||||||
void open (const CGHeroInstance * h, ui32 accept) const;
|
|
||||||
void getText( InfoWindow &iw, bool &afterBattle, int val, int negative, int positive, const CGHeroInstance * h ) const;
|
void getText( InfoWindow &iw, bool &afterBattle, int val, int negative, int positive, const CGHeroInstance * h ) const;
|
||||||
void getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const;
|
void getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const;
|
||||||
};
|
};
|
||||||
@ -725,6 +735,10 @@ private:
|
|||||||
|
|
||||||
class DLL_LINKAGE CGCreature : public CArmedInstance //creatures on map
|
class DLL_LINKAGE CGCreature : public CArmedInstance //creatures on map
|
||||||
{
|
{
|
||||||
|
enum Action {
|
||||||
|
FIGHT = -2, FLEE = -1, JOIN_FOR_FREE = 0 //values > 0 mean gold price
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ui32 identifier; //unique code for this monster (used in missions)
|
ui32 identifier; //unique code for this monster (used in missions)
|
||||||
si8 character; //character of this set of creatures (0 - the most friendly, 4 - the most hostile) => on init changed to -4 (compliant) ... 10 value (savage)
|
si8 character; //character of this set of creatures (0 - the most friendly, 4 - the most hostile) => on init changed to -4 (compliant) ... 10 value (savage)
|
||||||
@ -735,11 +749,14 @@ public:
|
|||||||
bool notGrowingTeam; //if true, number of units won't grow
|
bool notGrowingTeam; //if true, number of units won't grow
|
||||||
ui64 temppower; //used to handle fractional stack growth for tiny stacks
|
ui64 temppower; //used to handle fractional stack growth for tiny stacks
|
||||||
|
|
||||||
|
bool refusedJoining;
|
||||||
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
const std::string & getHoverText() const override;
|
const std::string & getHoverText() const override;
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
void newTurn() const override;
|
void newTurn() const override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
|
|
||||||
struct DLL_LINKAGE RestoredCreature // info about merging stacks after battle back into one
|
struct DLL_LINKAGE RestoredCreature // info about merging stacks after battle back into one
|
||||||
@ -754,7 +771,8 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CArmedInstance&>(*this);
|
h & static_cast<CArmedInstance&>(*this);
|
||||||
h & identifier & character & message & resources & gainedArtifact & neverFlees & notGrowingTeam & temppower & restore;
|
h & identifier & character & message & resources & gainedArtifact & neverFlees & notGrowingTeam & temppower;
|
||||||
|
h & refusedJoining & restore;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void setPropertyDer(ui8 what, ui32 val) override;
|
void setPropertyDer(ui8 what, ui32 val) override;
|
||||||
@ -762,7 +780,6 @@ private:
|
|||||||
|
|
||||||
void fight(const CGHeroInstance *h) const;
|
void fight(const CGHeroInstance *h) const;
|
||||||
void flee( const CGHeroInstance * h ) const;
|
void flee( const CGHeroInstance * h ) const;
|
||||||
void endBattle(BattleResult *result) const;
|
|
||||||
void fleeDecision(const CGHeroInstance *h, ui32 pursue) const;
|
void fleeDecision(const CGHeroInstance *h, ui32 pursue) const;
|
||||||
void joinDecision(const CGHeroInstance *h, int cost, ui32 accept) const;
|
void joinDecision(const CGHeroInstance *h, int cost, ui32 accept) const;
|
||||||
|
|
||||||
@ -815,6 +832,7 @@ public:
|
|||||||
const std::string & getHoverText() const override;
|
const std::string & getHoverText() const override;
|
||||||
void newTurn() const override;
|
void newTurn() const override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
int checkDirection() const; //calculates the region of map where monster is placed
|
int checkDirection() const; //calculates the region of map where monster is placed
|
||||||
void setObjToKill(); //remember creatures / heroes to kill after they are initialized
|
void setObjToKill(); //remember creatures / heroes to kill after they are initialized
|
||||||
@ -888,7 +906,7 @@ public:
|
|||||||
|
|
||||||
ui8 getPassableness() const;
|
ui8 getPassableness() const;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void fightOver (const CGHeroInstance *h, BattleResult *result) const;
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -904,8 +922,9 @@ public:
|
|||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void fightForArt(ui32 agreed, const CGHeroInstance *h) const;
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
void endBattle(BattleResult *result, const CGHeroInstance *h) const;
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
void pick( const CGHeroInstance * h ) const;
|
void pick( const CGHeroInstance * h ) const;
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
|
|
||||||
@ -924,10 +943,10 @@ public:
|
|||||||
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
void collectRes(PlayerColor player) const;
|
void collectRes(PlayerColor player) const;
|
||||||
void fightForRes(ui32 agreed, const CGHeroInstance *h) const;
|
|
||||||
void endBattle(BattleResult *result, const CGHeroInstance *h) const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -943,7 +962,7 @@ public:
|
|||||||
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
void chosen(int which, ObjectInstanceID heroID) const;
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -972,12 +991,10 @@ class DLL_LINKAGE CGMine : public CArmedInstance
|
|||||||
public:
|
public:
|
||||||
Res::ERes producedResource;
|
Res::ERes producedResource;
|
||||||
ui32 producedQuantity;
|
ui32 producedQuantity;
|
||||||
|
|
||||||
void offerLeavingGuards(const CGHeroInstance *h) const;
|
|
||||||
void endBattle(BattleResult *result, PlayerColor attackingPlayer) const;
|
|
||||||
void fight(ui32 agreed, const CGHeroInstance *h) const;
|
|
||||||
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
void flagMine(PlayerColor player) const;
|
void flagMine(PlayerColor player) const;
|
||||||
void newTurn() const override;
|
void newTurn() const override;
|
||||||
@ -1125,13 +1142,12 @@ public:
|
|||||||
CGBorderGuard() : IQuestObject(){};
|
CGBorderGuard() : IQuestObject(){};
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = NULL) const;
|
void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = NULL) const;
|
||||||
void getRolloverText (MetaString &text, bool onHover) const;
|
void getRolloverText (MetaString &text, bool onHover) const;
|
||||||
bool checkQuest (const CGHeroInstance * h) const;
|
bool checkQuest (const CGHeroInstance * h) const;
|
||||||
|
|
||||||
void openGate(const CGHeroInstance *h, ui32 accept) const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<IQuestObject&>(*this);
|
h & static_cast<IQuestObject&>(*this);
|
||||||
@ -1184,8 +1200,7 @@ public:
|
|||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
const std::string & getHoverText() const override;
|
const std::string & getHoverText() const override;
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
void searchTomb(const CGHeroInstance *h, ui32 accept) const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -1210,9 +1225,8 @@ class DLL_LINKAGE CBank : public CArmedInstance
|
|||||||
void newTurn() const override;
|
void newTurn() const override;
|
||||||
bool wasVisited (PlayerColor player) const override;
|
bool wasVisited (PlayerColor player) const override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
virtual void fightGuards (const CGHeroInstance *h, ui32 accept) const;
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
virtual void endBattle (const CGHeroInstance *h, const BattleResult *result) const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -1231,8 +1245,7 @@ public:
|
|||||||
const std::string & getHoverText() const override;
|
const std::string & getHoverText() const override;
|
||||||
void newTurn() const override {}; //empty, no reset
|
void newTurn() const override {}; //empty, no reset
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const OVERRIDE;
|
||||||
void endBattle (const CGHeroInstance *h, const BattleResult *result) const override;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -1270,7 +1283,7 @@ class DLL_LINKAGE CCartographer : public CPlayersVisited
|
|||||||
///behaviour varies depending on surface and floor
|
///behaviour varies depending on surface and floor
|
||||||
public:
|
public:
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void buyMap (const CGHeroInstance *h, ui32 accept) const;
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const OVERRIDE;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
@ -98,3 +98,8 @@ CSpell * SpellID::toSpell() const
|
|||||||
|
|
||||||
//template std::ostream & operator << <ArtifactInstanceID>(std::ostream & os, BaseForID<ArtifactInstanceID> id);
|
//template std::ostream & operator << <ArtifactInstanceID>(std::ostream & os, BaseForID<ArtifactInstanceID> id);
|
||||||
//template std::ostream & operator << <ObjectInstanceID>(std::ostream & os, BaseForID<ObjectInstanceID> id);
|
//template std::ostream & operator << <ObjectInstanceID>(std::ostream & os, BaseForID<ObjectInstanceID> id);
|
||||||
|
|
||||||
|
bool PlayerColor::isValidPlayer() const
|
||||||
|
{
|
||||||
|
return num < PLAYER_LIMIT_I;
|
||||||
|
}
|
||||||
|
@ -215,6 +215,8 @@ class PlayerColor : public BaseForID<PlayerColor, ui8>
|
|||||||
DLL_LINKAGE static const int PLAYER_LIMIT_I = 8; //player limit per map
|
DLL_LINKAGE static const int PLAYER_LIMIT_I = 8; //player limit per map
|
||||||
DLL_LINKAGE static const PlayerColor PLAYER_LIMIT; //player limit per map
|
DLL_LINKAGE static const PlayerColor PLAYER_LIMIT; //player limit per map
|
||||||
|
|
||||||
|
DLL_LINKAGE bool isValidPlayer() const; //valid means < PLAYER_LIMIT (especially non-neutral)
|
||||||
|
|
||||||
friend class CGameInfoCallback;
|
friend class CGameInfoCallback;
|
||||||
friend class CNonConstInfoCallback;
|
friend class CNonConstInfoCallback;
|
||||||
};
|
};
|
||||||
|
@ -220,11 +220,11 @@ public:
|
|||||||
virtual void setHoverName(const CGObjectInstance * obj, MetaString * name)=0;
|
virtual void setHoverName(const CGObjectInstance * obj, MetaString * name)=0;
|
||||||
virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false)=0;
|
virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false)=0;
|
||||||
virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0;
|
virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0;
|
||||||
virtual void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback)=0;
|
virtual void showBlockingDialog(BlockingDialog *iw) =0;
|
||||||
virtual ui32 showBlockingDialog(BlockingDialog *iw) =0; //synchronous version of above //TODO:
|
|
||||||
virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
|
virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
|
||||||
virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0;
|
virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0;
|
||||||
virtual void giveResource(PlayerColor player, Res::ERes which, int val)=0;
|
virtual void giveResource(PlayerColor player, Res::ERes which, int val)=0;
|
||||||
|
virtual void giveResources(PlayerColor player, TResources resources)=0;
|
||||||
|
|
||||||
virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
|
virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
|
||||||
virtual void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) =0;
|
virtual void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) =0;
|
||||||
@ -247,11 +247,11 @@ public:
|
|||||||
virtual void showCompInfo(ShowInInfobox * comp)=0;
|
virtual void showCompInfo(ShowInInfobox * comp)=0;
|
||||||
virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
||||||
virtual void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
virtual void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
||||||
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
|
virtual void startBattlePrimary(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
|
||||||
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
|
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
|
||||||
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
|
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
|
||||||
virtual void setAmount(ObjectInstanceID objid, ui32 val)=0;
|
virtual void setAmount(ObjectInstanceID objid, ui32 val)=0;
|
||||||
virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 instant, PlayerColor asker = PlayerColor::NEUTRAL)=0;
|
virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL)=0;
|
||||||
virtual void giveHeroBonus(GiveBonus * bonus)=0;
|
virtual void giveHeroBonus(GiveBonus * bonus)=0;
|
||||||
virtual void setMovePoints(SetMovePoints * smp)=0;
|
virtual void setMovePoints(SetMovePoints * smp)=0;
|
||||||
virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
|
virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
|
||||||
|
@ -633,7 +633,7 @@ struct RemoveObject : public CPackForClient //500
|
|||||||
};
|
};
|
||||||
struct TryMoveHero : public CPackForClient //501
|
struct TryMoveHero : public CPackForClient //501
|
||||||
{
|
{
|
||||||
TryMoveHero(){type = 501;humanKnows=false; attackedFrom = int3(-1, -1, -1);};
|
TryMoveHero(){type = 501;humanKnows=false;};
|
||||||
void applyFirstCl(CClient *cl);
|
void applyFirstCl(CClient *cl);
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
void applyGs(CGameState *gs);
|
void applyGs(CGameState *gs);
|
||||||
@ -648,7 +648,7 @@ struct TryMoveHero : public CPackForClient //501
|
|||||||
EResult result; //uses EResult
|
EResult result; //uses EResult
|
||||||
int3 start, end; //h3m format
|
int3 start, end; //h3m format
|
||||||
boost::unordered_set<int3, ShashInt3> fowRevealed; //revealed tiles
|
boost::unordered_set<int3, ShashInt3> fowRevealed; //revealed tiles
|
||||||
int3 attackedFrom; // Set when stepping into endangered tile.
|
boost::optional<int3> attackedFrom; // Set when stepping into endangered tile.
|
||||||
|
|
||||||
bool humanKnows; //used locally during applying to client
|
bool humanKnows; //used locally during applying to client
|
||||||
|
|
||||||
@ -1168,7 +1168,7 @@ struct InfoWindow : public CPackForClient //103 - displays simple info window
|
|||||||
namespace ObjProperty
|
namespace ObjProperty
|
||||||
{
|
{
|
||||||
enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8,
|
enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8,
|
||||||
MONSTER_COUNT = 10, MONSTER_POWER = 11, MONSTER_EXP = 12, MONSTER_RESTORE_TYPE = 13,
|
MONSTER_COUNT = 10, MONSTER_POWER = 11, MONSTER_EXP = 12, MONSTER_RESTORE_TYPE = 13, MONSTER_REFUSED_JOIN,
|
||||||
|
|
||||||
//town-specific
|
//town-specific
|
||||||
STRUCTURE_ADD_VISITING_HERO, STRUCTURE_CLEAR_VISITORS, STRUCTURE_ADD_GARRISONED_HERO, //changing buildings state
|
STRUCTURE_ADD_VISITING_HERO, STRUCTURE_CLEAR_VISITORS, STRUCTURE_ADD_GARRISONED_HERO, //changing buildings state
|
||||||
@ -1216,7 +1216,7 @@ struct HeroLevelUp : public Query//2000
|
|||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||||
|
|
||||||
ObjectInstanceID heroid;
|
const CGHeroInstance *hero;
|
||||||
PrimarySkill::PrimarySkill primskill;
|
PrimarySkill::PrimarySkill primskill;
|
||||||
ui8 level;
|
ui8 level;
|
||||||
std::vector<SecondarySkill> skills;
|
std::vector<SecondarySkill> skills;
|
||||||
@ -1225,7 +1225,7 @@ struct HeroLevelUp : public Query//2000
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & queryID & heroid & primskill & level & skills;
|
h & queryID & hero & primskill & level & skills;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1234,8 +1234,7 @@ struct CommanderLevelUp : public Query
|
|||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||||
|
|
||||||
ObjectInstanceID heroid; //for commander attached to hero
|
const CGHeroInstance *hero;
|
||||||
StackLocation sl; //for commander not on the hero?
|
|
||||||
|
|
||||||
std::vector<ui32> skills; //0-5 - secondary skills, val-100 - special skill
|
std::vector<ui32> skills; //0-5 - secondary skills, val-100 - special skill
|
||||||
|
|
||||||
@ -1243,7 +1242,7 @@ struct CommanderLevelUp : public Query
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & queryID & heroid & sl & skills;
|
h & queryID & hero & skills;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1302,6 +1301,12 @@ struct BlockingDialog : public Query//2003
|
|||||||
soundID = 0;
|
soundID = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void addResourceComponents(TResources resources)
|
||||||
|
{
|
||||||
|
for(TResources::nziterator i(resources); i.valid(); i++)
|
||||||
|
components.push_back(Component(Component::RESOURCE, i->resType, i->resVal, 0));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & queryID & text & components & player & flags & soundID;
|
h & queryID & text & components & player & flags & soundID;
|
||||||
|
@ -994,7 +994,7 @@ DLL_LINKAGE void SetHoverName::applyGs( CGameState *gs )
|
|||||||
|
|
||||||
DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs )
|
DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
CGHeroInstance* h = gs->getHero(heroid);
|
CGHeroInstance* h = gs->getHero(hero->id);
|
||||||
h->level = level;
|
h->level = level;
|
||||||
//specialty
|
//specialty
|
||||||
h->Updatespecialty();
|
h->Updatespecialty();
|
||||||
@ -1002,7 +1002,7 @@ DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs )
|
|||||||
|
|
||||||
DLL_LINKAGE void CommanderLevelUp::applyGs (CGameState *gs)
|
DLL_LINKAGE void CommanderLevelUp::applyGs (CGameState *gs)
|
||||||
{
|
{
|
||||||
CCommanderInstance * commander = gs->getHero(heroid)->commander;
|
CCommanderInstance * commander = gs->getHero(hero->id)->commander;
|
||||||
assert (commander);
|
assert (commander);
|
||||||
commander->levelUp();
|
commander->levelUp();
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ void Res::ResourceSet::nziterator::advance()
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
cur.resType++;
|
vstd::advance(cur.resType, +1);
|
||||||
} while(cur.resType < GameConstants::RESOURCE_QUANTITY && !(cur.resVal=rs[cur.resType]));
|
} while(cur.resType < GameConstants::RESOURCE_QUANTITY && !(cur.resVal=rs[cur.resType]));
|
||||||
|
|
||||||
if(cur.resType >= GameConstants::RESOURCE_QUANTITY)
|
if(cur.resType >= GameConstants::RESOURCE_QUANTITY)
|
||||||
@ -102,8 +102,8 @@ void Res::ResourceSet::nziterator::advance()
|
|||||||
Res::ResourceSet::nziterator::nziterator(const ResourceSet &RS)
|
Res::ResourceSet::nziterator::nziterator(const ResourceSet &RS)
|
||||||
: rs(RS)
|
: rs(RS)
|
||||||
{
|
{
|
||||||
cur.resType = 0;
|
cur.resType = WOOD;
|
||||||
cur.resVal = rs[0];
|
cur.resVal = rs[WOOD];
|
||||||
|
|
||||||
if(!valid())
|
if(!valid())
|
||||||
advance();
|
advance();
|
||||||
|
@ -98,6 +98,14 @@ namespace Res
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceSet operator-() const
|
||||||
|
{
|
||||||
|
ResourceSet ret;
|
||||||
|
for(int i = 0; i < size(); i++)
|
||||||
|
ret[i] = -at(i);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i]
|
// WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i]
|
||||||
// that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a
|
// that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a
|
||||||
// bool operator<(const ResourceSet &rhs)
|
// bool operator<(const ResourceSet &rhs)
|
||||||
@ -124,7 +132,8 @@ namespace Res
|
|||||||
{
|
{
|
||||||
struct ResEntry
|
struct ResEntry
|
||||||
{
|
{
|
||||||
TResourceCap resType, resVal;
|
Res::ERes resType;
|
||||||
|
TResourceCap resVal;
|
||||||
} cur;
|
} cur;
|
||||||
const ResourceSet &rs;
|
const ResourceSet &rs;
|
||||||
void advance();
|
void advance();
|
||||||
|
@ -128,7 +128,7 @@ extern DLL_LINKAGE CLogger * logAi;
|
|||||||
|
|
||||||
/// RAII class for tracing the program execution.
|
/// RAII class for tracing the program execution.
|
||||||
/// It prints "Leaving function XYZ" automatically when the object gets destructed.
|
/// It prints "Leaving function XYZ" automatically when the object gets destructed.
|
||||||
class DLL_LINKAGE CTraceLogger
|
class DLL_LINKAGE CTraceLogger : boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CTraceLogger(const CLogger * logger, const std::string & beginMessage, const std::string & endMessage);
|
CTraceLogger(const CLogger * logger, const std::string & beginMessage, const std::string & endMessage);
|
||||||
@ -141,10 +141,20 @@ private:
|
|||||||
|
|
||||||
/// Macros for tracing the control flow of the application conveniently. If the LOG_TRACE macro is used it should be
|
/// Macros for tracing the control flow of the application conveniently. If the LOG_TRACE macro is used it should be
|
||||||
/// the first statement in the function. Logging traces via this macro have almost no impact when the trace is disabled.
|
/// the first statement in the function. Logging traces via this macro have almost no impact when the trace is disabled.
|
||||||
#define LOG_TRACE(logger) if(logger->isTraceEnabled()) CTraceLogger ctl00(logger, boost::str(boost::format("Entering %s.") % BOOST_CURRENT_FUNCTION), \
|
///
|
||||||
boost::str(boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION))
|
#define RAII_TRACE(logger, onEntry, onLeave) \
|
||||||
#define LOG_TRACE_PARAMS(logger, formatStr, params) if(logger->isTraceEnabled()) CTraceLogger ctl00(logger, boost::str(boost::format("Entering %s: " + \
|
unique_ptr<CTraceLogger> ctl00; \
|
||||||
std::string(formatStr) + ".") % BOOST_CURRENT_FUNCTION % params), boost::str(boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION))
|
if(logger->isTraceEnabled()) \
|
||||||
|
ctl00 = make_unique<CTraceLogger>(logger, onEntry, onLeave);
|
||||||
|
|
||||||
|
#define LOG_TRACE(logger) RAII_TRACE(logger, \
|
||||||
|
boost::str(boost::format("Entering %s.") % BOOST_CURRENT_FUNCTION), \
|
||||||
|
boost::str(boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION))
|
||||||
|
|
||||||
|
|
||||||
|
#define LOG_TRACE_PARAMS(logger, formatStr, params) RAII_TRACE(logger, \
|
||||||
|
boost::str(boost::format("Entering %s: " + std::string(formatStr) + ".") % BOOST_CURRENT_FUNCTION % params), \
|
||||||
|
boost::str(boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION))
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------- */
|
||||||
/* Implementation/Detail classes, Private API */
|
/* Implementation/Detail classes, Private API */
|
||||||
|
@ -55,7 +55,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The CMapUndoManager provides the functionality to save operations and undo/redo them.
|
/// The CMapUndoManager provides the functionality to save operations and undo/redo them.
|
||||||
class CMapUndoManager
|
class CMapUndoManager : boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CMapUndoManager();
|
CMapUndoManager();
|
||||||
@ -87,7 +87,7 @@ private:
|
|||||||
|
|
||||||
/// The map edit manager provides functionality for drawing terrain and placing
|
/// The map edit manager provides functionality for drawing terrain and placing
|
||||||
/// objects on the map.
|
/// objects on the map.
|
||||||
class DLL_LINKAGE CMapEditManager
|
class DLL_LINKAGE CMapEditManager : boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CMapEditManager(CMap * map);
|
CMapEditManager(CMap * map);
|
||||||
|
@ -56,7 +56,7 @@ class DLL_LINKAGE CMapGenOptions
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// The player settings class maps the player color, starting town and human player flag.
|
/// The player settings class maps the player color, starting town and human player flag.
|
||||||
class CPlayerSettings
|
class DLL_LINKAGE CPlayerSettings
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerSettings();
|
CPlayerSettings();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,8 @@
|
|||||||
#include "../lib/IGameCallback.h"
|
#include "../lib/IGameCallback.h"
|
||||||
#include "../lib/BattleAction.h"
|
#include "../lib/BattleAction.h"
|
||||||
#include "../lib/NetPacks.h"
|
#include "../lib/NetPacks.h"
|
||||||
|
#include "CQuery.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CGameHandler.h, part of VCMI engine
|
* CGameHandler.h, part of VCMI engine
|
||||||
@ -41,13 +43,12 @@ extern boost::mutex gsm;
|
|||||||
|
|
||||||
struct PlayerStatus
|
struct PlayerStatus
|
||||||
{
|
{
|
||||||
bool makingTurn, engagedIntoBattle;
|
bool makingTurn;
|
||||||
std::set<ui32> queries;
|
|
||||||
|
|
||||||
PlayerStatus():makingTurn(false),engagedIntoBattle(false){};
|
PlayerStatus():makingTurn(false){};
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & makingTurn & engagedIntoBattle & queries;
|
h & makingTurn;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class PlayerStatuses
|
class PlayerStatuses
|
||||||
@ -59,11 +60,8 @@ public:
|
|||||||
|
|
||||||
void addPlayer(PlayerColor player);
|
void addPlayer(PlayerColor player);
|
||||||
PlayerStatus operator[](PlayerColor player);
|
PlayerStatus operator[](PlayerColor player);
|
||||||
int getQueriesCount(PlayerColor player); //returns 0 if there is no such player
|
|
||||||
bool checkFlag(PlayerColor player, bool PlayerStatus::*flag);
|
bool checkFlag(PlayerColor player, bool PlayerStatus::*flag);
|
||||||
void setFlag(PlayerColor player, bool PlayerStatus::*flag, bool val);
|
void setFlag(PlayerColor player, bool PlayerStatus::*flag, bool val);
|
||||||
void addQuery(PlayerColor player, ui32 id);
|
|
||||||
void removeQuery(PlayerColor player, ui32 id);
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & players;
|
h & players;
|
||||||
@ -85,7 +83,6 @@ class CGameHandler : public IGameCallback, CBattleInfoCallback
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
void makeStackDoNothing(const CStack * next);
|
void makeStackDoNothing(const CStack * next);
|
||||||
bool isAllowedExchangeForQuery(ObjectInstanceID id1, ObjectInstanceID id2);
|
|
||||||
public:
|
public:
|
||||||
CVCMIServer *s;
|
CVCMIServer *s;
|
||||||
std::map<PlayerColor, CConnection*> connections; //player color -> connection to client with interface of that player
|
std::map<PlayerColor, CConnection*> connections; //player color -> connection to client with interface of that player
|
||||||
@ -95,25 +92,22 @@ public:
|
|||||||
//queries stuff
|
//queries stuff
|
||||||
boost::recursive_mutex gsm;
|
boost::recursive_mutex gsm;
|
||||||
ui32 QID;
|
ui32 QID;
|
||||||
|
Queries queries;
|
||||||
|
|
||||||
//TODO get rid of cfunctionlist (or similar) and use serialziable callback structure
|
//TODO get rid of cfunctionlist (or similar) and use serialziable callback structure
|
||||||
std::map<ui32, CFunctionList<void(ui32)> > callbacks; //query id => callback function - for selection and yes/no dialogs
|
std::map<ui32, CFunctionList<void(ui32)> > callbacks; //query id => callback function - for selection and yes/no dialogs
|
||||||
std::map<ui32, std::pair<ObjectInstanceID, ObjectInstanceID> > allowedExchanges;
|
|
||||||
|
|
||||||
bool isBlockedByQueries(const CPack *pack, int packType, PlayerColor player);
|
bool isValidObject(const CGObjectInstance *obj) const;
|
||||||
|
bool isBlockedByQueries(const CPack *pack, PlayerColor player);
|
||||||
bool isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2);
|
bool isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2);
|
||||||
bool isAllowedArrangePack(const ArrangeStacks *pack);
|
|
||||||
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
|
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
|
||||||
int moveStack(int stack, BattleHex dest); //returned value - travelled distance
|
int moveStack(int stack, BattleHex dest); //returned value - travelled distance
|
||||||
void startBattle(const CArmedInstance *armies[2], int3 tile, const CGHeroInstance *heroes[2], bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
|
|
||||||
void runBattle();
|
void runBattle();
|
||||||
void checkLossVictory(PlayerColor player);
|
void checkLossVictory(PlayerColor player);
|
||||||
void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
|
void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
|
||||||
void getLossVicMessage(PlayerColor player, si8 standard, bool victory, InfoWindow &out) const;
|
void getLossVicMessage(PlayerColor player, si8 standard, bool victory, InfoWindow &out) const;
|
||||||
|
|
||||||
////used only in endBattle - don't touch elsewhere
|
////used only in endBattle - don't touch elsewhere
|
||||||
boost::function<void(BattleResult*)> * battleEndCallback;
|
|
||||||
//const CArmedInstance * bEndArmy1, * bEndArmy2;
|
|
||||||
bool visitObjectAfterVictory;
|
bool visitObjectAfterVictory;
|
||||||
//
|
//
|
||||||
void endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2); //ends battle
|
void endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2); //ends battle
|
||||||
@ -137,11 +131,12 @@ public:
|
|||||||
void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) OVERRIDE;
|
void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) OVERRIDE;
|
||||||
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) OVERRIDE;
|
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) OVERRIDE;
|
||||||
//void showInfoDialog(InfoWindow *iw) OVERRIDE;
|
//void showInfoDialog(InfoWindow *iw) OVERRIDE;
|
||||||
void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback) OVERRIDE;
|
|
||||||
ui32 showBlockingDialog(BlockingDialog *iw) OVERRIDE; //synchronous version of above
|
void showBlockingDialog(BlockingDialog *iw) OVERRIDE;
|
||||||
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE;
|
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE;
|
||||||
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE;
|
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE;
|
||||||
void giveResource(PlayerColor player, Res::ERes which, int val) OVERRIDE;
|
void giveResource(PlayerColor player, Res::ERes which, int val) OVERRIDE;
|
||||||
|
void giveResources(PlayerColor player, TResources resources) OVERRIDE;
|
||||||
|
|
||||||
void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE;
|
void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE;
|
||||||
void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE;
|
void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE;
|
||||||
@ -165,11 +160,11 @@ public:
|
|||||||
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE;
|
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE;
|
||||||
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE;
|
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE;
|
||||||
//bool removeArtifact(const CArtifact* art, int hid) OVERRIDE;
|
//bool removeArtifact(const CArtifact* art, int hid) OVERRIDE;
|
||||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL) OVERRIDE; //use hero=NULL for no hero
|
void startBattlePrimary(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, const CGTownInstance *town = NULL) OVERRIDE; //use hero=NULL for no hero
|
||||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used
|
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used
|
||||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) OVERRIDE; //for hero<=>neutral army
|
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) OVERRIDE; //for hero<=>neutral army
|
||||||
void setAmount(ObjectInstanceID objid, ui32 val) OVERRIDE;
|
void setAmount(ObjectInstanceID objid, ui32 val) OVERRIDE;
|
||||||
bool moveHero(ObjectInstanceID hid, int3 dst, ui8 instant, PlayerColor asker = PlayerColor::NEUTRAL) OVERRIDE;
|
bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) OVERRIDE;
|
||||||
void giveHeroBonus(GiveBonus * bonus) OVERRIDE;
|
void giveHeroBonus(GiveBonus * bonus) OVERRIDE;
|
||||||
void setMovePoints(SetMovePoints * smp) OVERRIDE;
|
void setMovePoints(SetMovePoints * smp) OVERRIDE;
|
||||||
void setManaPoints(ObjectInstanceID hid, int val) OVERRIDE;
|
void setManaPoints(ObjectInstanceID hid, int val) OVERRIDE;
|
||||||
@ -179,7 +174,6 @@ public:
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
void useScholarSkill(ObjectInstanceID hero1, ObjectInstanceID hero2);
|
void useScholarSkill(ObjectInstanceID hero1, ObjectInstanceID hero2);
|
||||||
void setPortalDwelling(const CGTownInstance * town, bool forced, bool clear);
|
void setPortalDwelling(const CGTownInstance * town, bool forced, bool clear);
|
||||||
bool tryAttackingGuard(const int3 &guardPos, const CGHeroInstance * h);
|
|
||||||
void visitObjectOnTile(const TerrainTile &t, const CGHeroInstance * h);
|
void visitObjectOnTile(const TerrainTile &t, const CGHeroInstance * h);
|
||||||
bool teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui8 source, PlayerColor asker = PlayerColor::NEUTRAL);
|
bool teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui8 source, PlayerColor asker = PlayerColor::NEUTRAL);
|
||||||
void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);
|
void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);
|
||||||
@ -187,7 +181,8 @@ public:
|
|||||||
void levelUpHero(const CGHeroInstance * hero);//initial call - check if hero have remaining levelups & handle them
|
void levelUpHero(const CGHeroInstance * hero);//initial call - check if hero have remaining levelups & handle them
|
||||||
void levelUpCommander (const CCommanderInstance * c, int skill); //secondary skill 1 to 6, special skill : skill - 100
|
void levelUpCommander (const CCommanderInstance * c, int skill); //secondary skill 1 to 6, special skill : skill - 100
|
||||||
void levelUpCommander (const CCommanderInstance * c);
|
void levelUpCommander (const CCommanderInstance * c);
|
||||||
void afterBattleCallback(); // called after level-ups are finished
|
|
||||||
|
void expGiven(const CGHeroInstance *hero); //triggers needed level-ups, handles also commander of this hero
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void commitPackage(CPackForClient *pack) OVERRIDE;
|
void commitPackage(CPackForClient *pack) OVERRIDE;
|
||||||
@ -233,6 +228,7 @@ public:
|
|||||||
void handleTownEvents(CGTownInstance *town, NewTurn &n);
|
void handleTownEvents(CGTownInstance *town, NewTurn &n);
|
||||||
bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true
|
bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true
|
||||||
void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
|
void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
|
||||||
|
void objectVisitEnded(const CObjectVisitQuery &query);
|
||||||
void engageIntoBattle( PlayerColor player );
|
void engageIntoBattle( PlayerColor player );
|
||||||
bool dig(const CGHeroInstance *h);
|
bool dig(const CGHeroInstance *h);
|
||||||
bool castSpell(const CGHeroInstance *h, SpellID spellID, const int3 &pos);
|
bool castSpell(const CGHeroInstance *h, SpellID spellID, const int3 &pos);
|
||||||
@ -240,15 +236,11 @@ public:
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & QID & states;
|
h & QID & states & finishingBattle;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui32 getQueryResult(PlayerColor player, int queryID);
|
|
||||||
void sendMessageToAll(const std::string &message);
|
void sendMessageToAll(const std::string &message);
|
||||||
void sendMessageTo(CConnection &c, const std::string &message);
|
void sendMessageTo(CConnection &c, const std::string &message);
|
||||||
void applyAndAsk(Query * sel, PlayerColor player, boost::function<void(ui32)> &callback);
|
|
||||||
void prepareNewQuery(Query * queryPack, PlayerColor player, const boost::function<void(ui32)> &callback = 0); //generates unique query id and writes it to the pack; blocks the player till query is answered (then callback is called)
|
|
||||||
void ask(Query * sel, PlayerColor player, const CFunctionList<void(ui32)> &callback);
|
|
||||||
void sendToAllClients(CPackForClient * info);
|
void sendToAllClients(CPackForClient * info);
|
||||||
void sendAndApply(CPackForClient * info);
|
void sendAndApply(CPackForClient * info);
|
||||||
void applyAndSend(CPackForClient * info);
|
void applyAndSend(CPackForClient * info);
|
||||||
@ -257,6 +249,28 @@ public:
|
|||||||
void sendAndApply(SetResources * info);
|
void sendAndApply(SetResources * info);
|
||||||
void sendAndApply(NewStructures * info);
|
void sendAndApply(NewStructures * info);
|
||||||
|
|
||||||
|
struct FinishingBattleHelper
|
||||||
|
{
|
||||||
|
FinishingBattleHelper();
|
||||||
|
FinishingBattleHelper(shared_ptr<const CBattleQuery> Query, bool Duel, int RemainingBattleQueriesCount);
|
||||||
|
|
||||||
|
shared_ptr<const CBattleQuery> query;
|
||||||
|
const CGHeroInstance *winnerHero, *loserHero;
|
||||||
|
PlayerColor victor, loser;
|
||||||
|
bool duel;
|
||||||
|
|
||||||
|
int remainingBattleQueriesCount;
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & query & winnerHero & loserHero & victor & loser & duel & remainingBattleQueriesCount;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
unique_ptr<FinishingBattleHelper> finishingBattle;
|
||||||
|
|
||||||
|
void battleAfterLevelUp(const BattleResult &result);
|
||||||
|
|
||||||
void run(bool resume);
|
void run(bool resume);
|
||||||
void newTurn();
|
void newTurn();
|
||||||
void handleAttackBeforeCasting (const BattleAttack & bat);
|
void handleAttackBeforeCasting (const BattleAttack & bat);
|
||||||
|
@ -6,6 +6,7 @@ include_directories(${Boost_INCLUDE_DIRS})
|
|||||||
|
|
||||||
set(server_SRCS
|
set(server_SRCS
|
||||||
CGameHandler.cpp
|
CGameHandler.cpp
|
||||||
|
CQuery.cpp
|
||||||
CVCMIServer.cpp
|
CVCMIServer.cpp
|
||||||
NetPacksServer.cpp
|
NetPacksServer.cpp
|
||||||
)
|
)
|
||||||
|
342
server/CQuery.cpp
Normal file
342
server/CQuery.cpp
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
#include "StdInc.h"
|
||||||
|
#include "CQuery.h"
|
||||||
|
#include "CGameHandler.h"
|
||||||
|
#include "..\lib\BattleState.h"
|
||||||
|
|
||||||
|
boost::mutex Queries::mx;
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
std::string formatContainer(const Container &c, std::string delimeter=", ", std::string opener="(", std::string closer=")")
|
||||||
|
{
|
||||||
|
std::string ret = opener;
|
||||||
|
auto itr = boost::begin(c);
|
||||||
|
if(itr != boost::end(c))
|
||||||
|
{
|
||||||
|
ret += boost::lexical_cast<std::string>(*itr);
|
||||||
|
while(++itr != boost::end(c))
|
||||||
|
{
|
||||||
|
ret += delimeter;
|
||||||
|
ret += boost::lexical_cast<std::string>(*itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret += closer;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream & operator<<(std::ostream &out, const CQuery &query)
|
||||||
|
{
|
||||||
|
return out << query.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream & operator<<(std::ostream &out, QueryPtr query)
|
||||||
|
{
|
||||||
|
return out << "[" << query.get() << "] " << query->toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
CQuery::CQuery(void)
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> l(Queries::mx);
|
||||||
|
|
||||||
|
static TQueryID QID = 1;
|
||||||
|
|
||||||
|
queryID = QID++;
|
||||||
|
logGlobal->traceStream() << "Created a new query with id " << queryID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CQuery::~CQuery(void)
|
||||||
|
{
|
||||||
|
logGlobal->traceStream() << "Destructed the query with id " << queryID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CQuery::addPlayer(PlayerColor color)
|
||||||
|
{
|
||||||
|
if(color.isValidPlayer())
|
||||||
|
{
|
||||||
|
players.push_back(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CQuery::toString() const
|
||||||
|
{
|
||||||
|
std::string ret = boost::str(boost::format("A query of type %s and qid=%d affecting players %s") % typeid(*this).name() % queryID % formatContainer(players));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CQuery::endsByPlayerAnswer() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CQuery::onRemoval(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CQuery::blocksPack(const CPack *pack) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CQuery::onExposure(CGameHandler *gh, QueryPtr topQuery)
|
||||||
|
{
|
||||||
|
gh->queries.popQuery(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CObjectVisitQuery::CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroInstance *Hero, int3 Tile)
|
||||||
|
: visitedObject(Obj), visitingHero(Hero), tile(Tile)
|
||||||
|
{
|
||||||
|
addPlayer(Hero->tempOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CObjectVisitQuery::blocksPack(const CPack *pack) const
|
||||||
|
{
|
||||||
|
//During the visit itself ALL actions are blocked.
|
||||||
|
//(However, the visit may trigger a query above that'll pass some.)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CObjectVisitQuery::onRemoval(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
gh->objectVisitEnded(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CObjectVisitQuery::onExposure(CGameHandler *gh, QueryPtr topQuery)
|
||||||
|
{
|
||||||
|
//Object may have been removed and deleted.
|
||||||
|
if(gh->isValidObject(visitedObject))
|
||||||
|
topQuery->notifyObjectAboutRemoval(*this);
|
||||||
|
|
||||||
|
gh->queries.popQuery(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Queries::popQuery(PlayerColor player, QueryPtr query)
|
||||||
|
{
|
||||||
|
LOG_TRACE_PARAMS(logGlobal, "player='%s', query='%s'", player % query);
|
||||||
|
if(topQuery(player) != query)
|
||||||
|
{
|
||||||
|
logGlobal->traceStream() << "Cannot remove, not a top!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
queries[player] -= query;
|
||||||
|
auto nextQuery = topQuery(player);
|
||||||
|
|
||||||
|
query->onRemoval(gh, player);
|
||||||
|
|
||||||
|
//Exposure on query below happens only if removal didnt trigger any new query
|
||||||
|
if(nextQuery && nextQuery == topQuery(player))
|
||||||
|
{
|
||||||
|
nextQuery->onExposure(gh, query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Queries::popQuery(const CQuery &query)
|
||||||
|
{
|
||||||
|
LOG_TRACE_PARAMS(logGlobal, "query='%s'", query);
|
||||||
|
|
||||||
|
assert(query.players.size());
|
||||||
|
BOOST_FOREACH(auto player, query.players)
|
||||||
|
{
|
||||||
|
auto top = topQuery(player);
|
||||||
|
if(top.get() == &query)
|
||||||
|
popQuery(top);
|
||||||
|
else
|
||||||
|
logGlobal->traceStream() << "Cannot remove query " << query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Queries::popQuery(QueryPtr query)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(auto player, query->players)
|
||||||
|
popQuery(player, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Queries::addQuery(QueryPtr query)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(auto player, query->players)
|
||||||
|
addQuery(player, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Queries::addQuery(PlayerColor player, QueryPtr query)
|
||||||
|
{
|
||||||
|
LOG_TRACE_PARAMS(logGlobal, "player='%s', query='%s'", player % query);
|
||||||
|
queries[player].push_back(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryPtr Queries::topQuery(PlayerColor player)
|
||||||
|
{
|
||||||
|
return vstd::backOrNull(queries[player]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Queries::popIfTop(QueryPtr query)
|
||||||
|
{
|
||||||
|
popIfTop(*query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Queries::popIfTop(const CQuery &query)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(PlayerColor color, query.players)
|
||||||
|
if(topQuery(color).get() == &query)
|
||||||
|
popQuery(color, topQuery(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<shared_ptr<const CQuery>> Queries::allQueries() const
|
||||||
|
{
|
||||||
|
std::vector<shared_ptr<const CQuery>> ret;
|
||||||
|
BOOST_FOREACH(auto &playerQueries, queries)
|
||||||
|
BOOST_FOREACH(auto &query, playerQueries.second)
|
||||||
|
ret.push_back(query);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<shared_ptr<CQuery>> Queries::allQueries()
|
||||||
|
{
|
||||||
|
//TODO code duplication with const function :(
|
||||||
|
std::vector<shared_ptr<CQuery>> ret;
|
||||||
|
BOOST_FOREACH(auto &playerQueries, queries)
|
||||||
|
BOOST_FOREACH(auto &query, playerQueries.second)
|
||||||
|
ret.push_back(query);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBattleQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const
|
||||||
|
{
|
||||||
|
assert(result);
|
||||||
|
objectVisit.visitedObject->battleFinished(objectVisit.visitingHero, *result);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBattleQuery::CBattleQuery(const BattleInfo *Bi)
|
||||||
|
{
|
||||||
|
belligerents[0] = Bi->belligerents[0];
|
||||||
|
belligerents[1] = Bi->belligerents[1];
|
||||||
|
|
||||||
|
bi = Bi;
|
||||||
|
|
||||||
|
BOOST_FOREACH(PlayerColor side, bi->sides)
|
||||||
|
addPlayer(side);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBattleQuery::CBattleQuery()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBattleQuery::blocksPack(const CPack *pack) const
|
||||||
|
{
|
||||||
|
return !dynamic_cast<const MakeAction*>(pack) && !dynamic_cast<const MakeCustomAction*>(pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBattleQuery::onRemoval(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
gh->battleAfterLevelUp(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGarrisonDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const
|
||||||
|
{
|
||||||
|
objectVisit.visitedObject->garrisonDialogClosed(objectVisit.visitingHero);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGarrisonDialogQuery::CGarrisonDialogQuery(const CArmedInstance *up, const CArmedInstance *down)
|
||||||
|
{
|
||||||
|
exchangingArmies[0] = up;
|
||||||
|
exchangingArmies[1] = down;
|
||||||
|
|
||||||
|
addPlayer(up->tempOwner);
|
||||||
|
addPlayer(down->tempOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGarrisonDialogQuery::blocksPack(const CPack *pack) const
|
||||||
|
{
|
||||||
|
if(auto stacks = dynamic_cast<const ArrangeStacks*>(pack))
|
||||||
|
{
|
||||||
|
std::set<ObjectInstanceID> ourIds;
|
||||||
|
ourIds.insert(this->exchangingArmies[0]->id);
|
||||||
|
ourIds.insert(this->exchangingArmies[1]->id);
|
||||||
|
|
||||||
|
return !vstd::contains(ourIds, stacks->id1) || !vstd::contains(ourIds, stacks->id2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CDialogQuery::blocksPack(pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBlockingDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const
|
||||||
|
{
|
||||||
|
assert(answer);
|
||||||
|
objectVisit.visitedObject->blockingDialogAnswered(objectVisit.visitingHero, *answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlockingDialogQuery::CBlockingDialogQuery(const BlockingDialog &bd)
|
||||||
|
{
|
||||||
|
this->bd = bd;
|
||||||
|
addPlayer(bd.player);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHeroLevelUpDialogQuery::CHeroLevelUpDialogQuery(const HeroLevelUp &Hlu)
|
||||||
|
{
|
||||||
|
hlu = Hlu;
|
||||||
|
addPlayer(hlu.hero->tempOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHeroLevelUpDialogQuery::onRemoval(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
assert(answer);
|
||||||
|
logGlobal->traceStream() << "Completing hero level-up query. " << hlu.hero->getHoverText() << " gains skill " << answer;
|
||||||
|
gh->levelUpHero(hlu.hero, hlu.skills[*answer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCommanderLevelUpDialogQuery::CCommanderLevelUpDialogQuery(const CommanderLevelUp &Clu)
|
||||||
|
{
|
||||||
|
clu = Clu;
|
||||||
|
addPlayer(clu.hero->tempOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCommanderLevelUpDialogQuery::onRemoval(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
assert(answer);
|
||||||
|
logGlobal->traceStream() << "Completing commander level-up query. Commander of hero " << clu.hero->getHoverText() << " gains skill " << answer;
|
||||||
|
gh->levelUpCommander(clu.hero->commander, clu.skills[*answer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDialogQuery::endsByPlayerAnswer() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDialogQuery::blocksPack(const CPack *pack) const
|
||||||
|
{
|
||||||
|
//We accept only query replies from correct player
|
||||||
|
if(auto reply = dynamic_cast<const QueryReply *>(pack))
|
||||||
|
{
|
||||||
|
return !vstd::contains(players, reply->player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHeroMovementQuery::CHeroMovementQuery(const TryMoveHero &Tmh, const CGHeroInstance *Hero, bool VisitDestAfterVictory)
|
||||||
|
: tmh(Tmh), visitDestAfterVictory(VisitDestAfterVictory), hero(Hero)
|
||||||
|
{
|
||||||
|
players.push_back(hero->tempOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHeroMovementQuery::onExposure(CGameHandler *gh, QueryPtr topQuery)
|
||||||
|
{
|
||||||
|
assert(players.size() == 1);
|
||||||
|
|
||||||
|
if(visitDestAfterVictory && hero->tempOwner == players[0]) //hero still alive, so he won with the guard
|
||||||
|
//TODO what if there were H4-like escape? we should also check pos
|
||||||
|
{
|
||||||
|
logGlobal->traceStream() << "Hero " << hero->name << " after victory over guard finishes visit to " << tmh.end;
|
||||||
|
//finish movement
|
||||||
|
visitDestAfterVictory = false;
|
||||||
|
gh->visitObjectOnTile(*gh->getTile(CGHeroInstance::convertPosition(tmh.end, false)), hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
gh->queries.popIfTop(*this);
|
||||||
|
}
|
177
server/CQuery.h
Normal file
177
server/CQuery.h
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "..\lib\GameConstants.h"
|
||||||
|
#include "..\lib\int3.h"
|
||||||
|
#include "..\lib\NetPacks.h"
|
||||||
|
|
||||||
|
class CGObjectInstance;
|
||||||
|
class CGHeroInstance;
|
||||||
|
class CArmedInstance;
|
||||||
|
struct CPack;
|
||||||
|
class CGameHandler;
|
||||||
|
class CObjectVisitQuery;
|
||||||
|
struct TryMoveHero;
|
||||||
|
class CQuery;
|
||||||
|
|
||||||
|
typedef si32 TQueryID;
|
||||||
|
typedef shared_ptr<CQuery> QueryPtr;
|
||||||
|
|
||||||
|
// This class represents any kind of prolonged interaction that may need to do something special after it is over.
|
||||||
|
// It does not necessarily has to be "query" requiring player action, it can be also used internally within server.
|
||||||
|
// Examples:
|
||||||
|
// - all kinds of blocking dialog windows
|
||||||
|
// - battle
|
||||||
|
// - object visit
|
||||||
|
// - hero movement
|
||||||
|
// Queries can cause another queries, forming a stack of queries for each player. Eg: hero movement -> object visit -> dialog.
|
||||||
|
class CQuery
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void addPlayer(PlayerColor color);
|
||||||
|
public:
|
||||||
|
std::vector<PlayerColor> players; //players that are affected (often "blocked") by query
|
||||||
|
TQueryID queryID;
|
||||||
|
|
||||||
|
CQuery(void);
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool blocksPack(const CPack *pack) const; //query can block attempting actions by player. Eg. he can't move hero during the battle.
|
||||||
|
|
||||||
|
virtual bool endsByPlayerAnswer() const; //query is removed after player gives answer (like dialogs)
|
||||||
|
virtual void onRemoval(CGameHandler *gh, PlayerColor color); //called after query is removed from stack
|
||||||
|
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);//called when query immediately above is removed and this is exposed (becomes top)
|
||||||
|
virtual std::string toString() const;
|
||||||
|
|
||||||
|
virtual void notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const;
|
||||||
|
|
||||||
|
virtual ~CQuery(void);
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & players & queryID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const CQuery &query);
|
||||||
|
std::ostream &operator<<(std::ostream &out, QueryPtr query);
|
||||||
|
|
||||||
|
//Created when hero visits object.
|
||||||
|
//Removed when query above is resolved (or immediately after visit if no queries were created)
|
||||||
|
class CObjectVisitQuery : public CQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const CGObjectInstance *visitedObject;
|
||||||
|
const CGHeroInstance *visitingHero;
|
||||||
|
int3 tile; //may be different than hero pos -> eg. visit via teleport
|
||||||
|
|
||||||
|
CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroInstance *Hero, int3 Tile);
|
||||||
|
|
||||||
|
virtual bool blocksPack(const CPack *pack) const OVERRIDE;
|
||||||
|
virtual void onRemoval(CGameHandler *gh, PlayerColor color) OVERRIDE;
|
||||||
|
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery) OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBattleQuery : public CQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::array<const CArmedInstance *,2> belligerents;
|
||||||
|
|
||||||
|
const BattleInfo *bi;
|
||||||
|
boost::optional<BattleResult> result;
|
||||||
|
|
||||||
|
CBattleQuery();
|
||||||
|
CBattleQuery(const BattleInfo *Bi); //TODO
|
||||||
|
virtual void notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const OVERRIDE;
|
||||||
|
virtual bool blocksPack(const CPack *pack) const OVERRIDE;
|
||||||
|
virtual void onRemoval(CGameHandler *gh, PlayerColor color) OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Created when hero attempts move and something happens
|
||||||
|
//(not necessarily position change, could be just an object interaction).
|
||||||
|
class CHeroMovementQuery : public CQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TryMoveHero tmh;
|
||||||
|
bool visitDestAfterVictory; //if hero moved to guarded tile and it should be visited once guard is defeated
|
||||||
|
const CGHeroInstance *hero;
|
||||||
|
|
||||||
|
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);
|
||||||
|
|
||||||
|
CHeroMovementQuery(const TryMoveHero &Tmh, const CGHeroInstance *Hero, bool VisitDestAfterVictory = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDialogQuery : public CQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
boost::optional<ui32> answer;
|
||||||
|
virtual bool endsByPlayerAnswer() const OVERRIDE;
|
||||||
|
virtual bool blocksPack(const CPack *pack) const OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CGarrisonDialogQuery : public CDialogQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::array<const CArmedInstance *,2> exchangingArmies;
|
||||||
|
|
||||||
|
CGarrisonDialogQuery(const CArmedInstance *up, const CArmedInstance *down);
|
||||||
|
virtual void notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const OVERRIDE;
|
||||||
|
virtual bool blocksPack(const CPack *pack) const OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
//yes/no and component selection dialogs
|
||||||
|
class CBlockingDialogQuery : public CDialogQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlockingDialog bd; //copy of pack... debug purposes
|
||||||
|
|
||||||
|
CBlockingDialogQuery(const BlockingDialog &bd);
|
||||||
|
|
||||||
|
virtual void notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHeroLevelUpDialogQuery : public CDialogQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CHeroLevelUpDialogQuery(const HeroLevelUp &Hlu);
|
||||||
|
|
||||||
|
virtual void onRemoval(CGameHandler *gh, PlayerColor color) OVERRIDE;
|
||||||
|
|
||||||
|
HeroLevelUp hlu;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CCommanderLevelUpDialogQuery : public CDialogQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCommanderLevelUpDialogQuery(const CommanderLevelUp &Clu);
|
||||||
|
|
||||||
|
virtual void onRemoval(CGameHandler *gh, PlayerColor color) OVERRIDE;
|
||||||
|
|
||||||
|
CommanderLevelUp clu;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Queries
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void addQuery(PlayerColor player, QueryPtr query);
|
||||||
|
void popQuery(PlayerColor player, QueryPtr query);
|
||||||
|
|
||||||
|
std::map<PlayerColor, std::vector<QueryPtr>> queries; //player => stack of queries
|
||||||
|
|
||||||
|
public:
|
||||||
|
CGameHandler *gh;
|
||||||
|
static boost::mutex mx;
|
||||||
|
|
||||||
|
void addQuery(QueryPtr query);
|
||||||
|
void popQuery(const CQuery &query);
|
||||||
|
void popQuery(QueryPtr query);
|
||||||
|
void popIfTop(const CQuery &query); //removes this query if it is at the top (otherwise, do nothing)
|
||||||
|
void popIfTop(QueryPtr query); //removes this query if it is at the top (otherwise, do nothing)
|
||||||
|
|
||||||
|
QueryPtr topQuery(PlayerColor player);
|
||||||
|
|
||||||
|
std::vector<shared_ptr<const CQuery>> allQueries() const;
|
||||||
|
std::vector<shared_ptr<CQuery>> allQueries();
|
||||||
|
//void removeQuery
|
||||||
|
|
||||||
|
};
|
@ -69,8 +69,8 @@ bool EndTurn::applyGh( CGameHandler *gh )
|
|||||||
{
|
{
|
||||||
PlayerColor player = GS(gh)->currentPlayer;
|
PlayerColor player = GS(gh)->currentPlayer;
|
||||||
ERROR_IF_NOT(player);
|
ERROR_IF_NOT(player);
|
||||||
if(gh->states.checkFlag(player, &PlayerStatus::engagedIntoBattle))
|
if(gh->queries.topQuery(player))
|
||||||
COMPLAIN_AND_RETURN("Cannot end turn when in battle!");
|
COMPLAIN_AND_RETURN("Cannot end turn before resolving queries!");
|
||||||
|
|
||||||
gh->states.setFlag(GS(gh)->currentPlayer,&PlayerStatus::makingTurn,false);
|
gh->states.setFlag(GS(gh)->currentPlayer,&PlayerStatus::makingTurn,false);
|
||||||
return true;
|
return true;
|
||||||
|
@ -145,6 +145,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="CGameHandler.cpp" />
|
<ClCompile Include="CGameHandler.cpp" />
|
||||||
|
<ClCompile Include="CQuery.cpp" />
|
||||||
<ClCompile Include="CVCMIServer.cpp" />
|
<ClCompile Include="CVCMIServer.cpp" />
|
||||||
<ClCompile Include="NetPacksServer.cpp" />
|
<ClCompile Include="NetPacksServer.cpp" />
|
||||||
<ClCompile Include="StdInc.cpp">
|
<ClCompile Include="StdInc.cpp">
|
||||||
@ -158,6 +159,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\Global.h" />
|
<ClInclude Include="..\Global.h" />
|
||||||
<ClInclude Include="CGameHandler.h" />
|
<ClInclude Include="CGameHandler.h" />
|
||||||
|
<ClInclude Include="CQuery.h" />
|
||||||
<ClInclude Include="CVCMIServer.h" />
|
<ClInclude Include="CVCMIServer.h" />
|
||||||
<ClInclude Include="StdInc.h" />
|
<ClInclude Include="StdInc.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user