From f95e6c233b91cc203e5b340be055fd57bacdb059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Tue, 14 May 2013 13:42:52 +0000 Subject: [PATCH] It is possible to set on visit query that object is to be removed after visit is over. Fixes #1263. --- client/Client.h | 4 +++- lib/CObjectHandler.cpp | 4 ++-- lib/IGameCallback.h | 4 +++- server/CGameHandler.cpp | 35 ++++++++++++++++++++++++----------- server/CGameHandler.h | 4 +++- server/CQuery.cpp | 7 ++++++- server/CQuery.h | 1 + 7 files changed, 42 insertions(+), 17 deletions(-) diff --git a/client/Client.h b/client/Client.h index 5ce6ec1c2..9d3563689 100644 --- a/client/Client.h +++ b/client/Client.h @@ -170,7 +170,7 @@ public: void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) OVERRIDE {}; void showBlockingDialog(BlockingDialog *iw) OVERRIDE {}; - void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function &cb) OVERRIDE {}; + void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) OVERRIDE {}; void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE {}; void giveResource(PlayerColor player, Res::ERes which, int val) OVERRIDE {}; virtual void giveResources(PlayerColor player, TResources resources) OVERRIDE {}; @@ -185,6 +185,8 @@ public: bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE {return false;} void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) OVERRIDE {} bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1) OVERRIDE {return false;} + + void removeAfterVisit(const CGObjectInstance *object) OVERRIDE {}; void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) OVERRIDE {}; void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) OVERRIDE {}; diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index bd333e776..ef1d97249 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -3556,7 +3556,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const if(relations == 2) //we're visiting our mine { - cb->showGarrisonDialog(id,h->id,true,0); + cb->showGarrisonDialog(id,h->id,true); return; } else if (relations == 1)//ally @@ -5833,7 +5833,7 @@ void CGGarrison::onHeroVisit (const CGHeroInstance *h) const if (!ally) cb->setOwner(this, h->tempOwner); - cb->showGarrisonDialog(id, h->id, removableUnits, 0); + cb->showGarrisonDialog(id, h->id, removableUnits); } ui8 CGGarrison::getPassableness() const diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 96e2e4565..6c537dd39 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -221,7 +221,7 @@ public: 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 showBlockingDialog(BlockingDialog *iw) =0; - virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function &cb) =0; //cb will be called when player closes garrison window + virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) =0; //cb will be called when player closes garrison window virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0; virtual void giveResource(PlayerColor player, Res::ERes which, int val)=0; virtual void giveResources(PlayerColor player, TResources resources)=0; @@ -237,6 +237,8 @@ public: virtual void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) =0; //merges army from src do dst or opens a garrison window virtual bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count) = 0; + virtual void removeAfterVisit(const CGObjectInstance *object) = 0; //object will be destroyed when interaction is over. Do not call when interaction is not ongoing! + virtual void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) = 0; virtual void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index dc36e1207..a8a58b5c0 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1853,10 +1853,6 @@ void CGameHandler::giveResources(PlayerColor player, TResources resources) void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) { - boost::function removeOrNot = 0; - if(remove) - removeOrNot = boost::bind(&CGameHandler::removeObject, this, obj); - COMPLAIN_RET_IF(!creatures.stacksCount(), "Strange, giveCreatures called without args!"); COMPLAIN_RET_IF(obj->stacksCount(), "Cannot give creatures from not-cleared object!"); COMPLAIN_RET_IF(creatures.stacksCount() > GameConstants::ARMY_SIZE, "Too many stacks to give!"); @@ -4743,7 +4739,7 @@ bool CGameHandler::complain( const std::string &problem ) return true; } -void CGameHandler::showGarrisonDialog( ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function &cb ) +void CGameHandler::showGarrisonDialog( ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) { //PlayerColor player = getOwner(hid); auto upperArmy = dynamic_cast(getObj(upobj)); @@ -5639,6 +5635,9 @@ bool CGameHandler::addToSlot(const StackLocation &sl, const CCreature *c, TQuant void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) { + if(removeObjWhenFinished) + removeAfterVisit(src); + if(!src->canBeMergedWith(*dst, allowMerging)) { if (allowMerging) //do that, add all matching creatures. @@ -5659,16 +5658,11 @@ void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstanc } } } - boost::function removeOrNot = 0; - if(removeObjWhenFinished) - removeOrNot = boost::bind(&IGameCallback::removeObject,this,src); - showGarrisonDialog(src->id, dst->id, true, removeOrNot); //show garrison window and optionally remove ourselves from map when player ends + showGarrisonDialog(src->id, dst->id, true); //show garrison window and optionally remove ourselves from map when player ends } else //merge { moveArmy(src, dst, allowMerging); - if(removeObjWhenFinished) - removeObject(src); } } @@ -6094,6 +6088,25 @@ bool CGameHandler::isBlockedByQueries(const CPack *pack, PlayerColor player) return false; } +void CGameHandler::removeAfterVisit(const CGObjectInstance *object) +{ + //If the object is being visited, there must be a matching query + BOOST_FOREACH(const auto &query, queries.allQueries()) + { + if(auto someVistQuery = std::dynamic_pointer_cast(query)) + { + if(someVistQuery->visitedObject == object) + { + someVistQuery->removeObjectAfterVisit = true; + return; + } + } + }; + + //If we haven't returned so far, there is no query and no visit, call was wrong + assert("This function needs to be called during the object visit!"); +} + CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat) { heroWithDeadCommander = ObjectInstanceID(); diff --git a/server/CGameHandler.h b/server/CGameHandler.h index c674adcef..e8b591389 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -138,7 +138,7 @@ public: //void showInfoDialog(InfoWindow *iw) OVERRIDE; void showBlockingDialog(BlockingDialog *iw) OVERRIDE; - void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function &cb) OVERRIDE; + void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) OVERRIDE; void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE; void giveResource(PlayerColor player, Res::ERes which, int val) OVERRIDE; void giveResources(PlayerColor player, TResources resources) OVERRIDE; @@ -153,6 +153,8 @@ public: bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE; void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) OVERRIDE; bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1) OVERRIDE; + + void removeAfterVisit(const CGObjectInstance *object) OVERRIDE; void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) OVERRIDE; void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) OVERRIDE; diff --git a/server/CQuery.cpp b/server/CQuery.cpp index ffcf38b39..b9e0503a9 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -87,7 +87,7 @@ void CQuery::onExposure(CGameHandler *gh, QueryPtr topQuery) } CObjectVisitQuery::CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroInstance *Hero, int3 Tile) - : visitedObject(Obj), visitingHero(Hero), tile(Tile) + : visitedObject(Obj), visitingHero(Hero), tile(Tile), removeObjectAfterVisit(false) { addPlayer(Hero->tempOwner); } @@ -102,6 +102,11 @@ bool CObjectVisitQuery::blocksPack(const CPack *pack) const void CObjectVisitQuery::onRemoval(CGameHandler *gh, PlayerColor color) { gh->objectVisitEnded(*this); + + //TODO or should it be destructor? + //Can object visit affect 2 players and what would be desired behavior? + if(removeObjectAfterVisit) + gh->removeObject(visitedObject); } void CObjectVisitQuery::onExposure(CGameHandler *gh, QueryPtr topQuery) diff --git a/server/CQuery.h b/server/CQuery.h index a32122617..f9d125a4c 100644 --- a/server/CQuery.h +++ b/server/CQuery.h @@ -63,6 +63,7 @@ public: const CGObjectInstance *visitedObject; const CGHeroInstance *visitingHero; int3 tile; //may be different than hero pos -> eg. visit via teleport + bool removeObjectAfterVisit; CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroInstance *Hero, int3 Tile);