Kaynağa Gözat

It is possible to set on visit query that object is to be removed after visit is over.
Fixes #1263.

Michał W. Urbańczyk 12 yıl önce
ebeveyn
işleme
f95e6c233b

+ 3 - 1
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<void()> &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 {};

+ 2 - 2
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

+ 3 - 1
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<void()> &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;

+ 24 - 11
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<void()> 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<void()> &cb )
+void CGameHandler::showGarrisonDialog( ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits)
 {
 	//PlayerColor player = getOwner(hid);
 	auto upperArmy = dynamic_cast<const CArmedInstance*>(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<void()> 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<CObjectVisitQuery>(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();

+ 3 - 1
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<void()> &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;

+ 6 - 1
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)

+ 1 - 0
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);