Browse Source

Update low level battle stacks accessor for ghost selection support.

AlexVinS 9 years ago
parent
commit
5df8d1cbd0

+ 17 - 2
lib/BattleState.cpp

@@ -1139,9 +1139,24 @@ std::string CStack::getName() const
 	return (count > 1) ? type->namePl : type->nameSing; //War machines can't use base
 }
 
-bool CStack::isValidTarget(bool allowDead/* = false*/) const /*alive non-turret stacks (can be attacked or be object of magic effect) */
+bool CStack::isValidTarget(bool allowDead/* = false*/) const
 {
-	return !isGhost() && (alive() || allowDead) && position.isValid();
+	return (alive() || (allowDead && isDead())) && position.isValid() && !isTurret();
+}
+
+bool CStack::isDead() const
+{
+	return !alive() && !isGhost();
+}
+
+bool CStack::isGhost() const
+{
+	return vstd::contains(state,EBattleStackState::GHOST);
+}
+
+bool CStack::isTurret() const
+{
+	return type->idNumber == CreatureID::ARROW_TOWERS;
 }
 
 bool CStack::canBeHealed() const

+ 5 - 5
lib/BattleState.h

@@ -289,11 +289,11 @@ public:
 	{
 		return vstd::contains(state,EBattleStackState::ALIVE);
 	}
-	bool isGhost() const //determines if stack was removed
-	{
-		return vstd::contains(state,EBattleStackState::GHOST);
-	}
-	bool isValidTarget(bool allowDead = false) const; //alive non-turret stacks (can be attacked or be object of magic effect)
+
+	bool isDead() const;
+	bool isGhost() const; //determines if stack was removed
+	bool isValidTarget(bool allowDead = false) const; //non-turret non-ghost stacks (can be attacked or be object of magic effect)
+	bool isTurret() const;
 };
 
 class DLL_LINKAGE CMP_stack

+ 12 - 12
lib/CBattleCallback.cpp

@@ -180,33 +180,33 @@ bool CBattleInfoEssentials::battleHasNativeStack(ui8 side) const
 
 TStacks CBattleInfoEssentials::battleGetAllStacks(bool includeTurrets /*= false*/) const
 {
-	return battleGetStacksIf([](const CStack * s){return true;},includeTurrets);
+	return battleGetStacksIf([=](const CStack * s)
+	{
+		return !s->isGhost() && (includeTurrets || !s->isTurret());
+	});
 }
 
-TStacks CBattleInfoEssentials::battleGetStacksIf(TStackFilter predicate, bool includeTurrets /*= false*/) const
+TStacks CBattleInfoEssentials::battleGetStacksIf(TStackFilter predicate) const
 {
 	TStacks ret;
 	RETURN_IF_NOT_BATTLE(ret);
 
-	vstd::copy_if(getBattle()->stacks, std::back_inserter(ret), [=](const CStack * s){
-		return predicate(s) && (!s->isGhost()) && (includeTurrets || !(s->type->idNumber == CreatureID::ARROW_TOWERS));
-	});
+	vstd::copy_if(getBattle()->stacks, std::back_inserter(ret), predicate);
 
 	return ret;
 }
 
-
 TStacks CBattleInfoEssentials::battleAliveStacks() const
 {
 	return battleGetStacksIf([](const CStack * s){
-		return s->alive();
+		return s->isValidTarget(false);
 	});
 }
 
 TStacks CBattleInfoEssentials::battleAliveStacks(ui8 side) const
 {
 	return battleGetStacksIf([=](const CStack * s){
-		return s->alive() && s->attackerOwned == !side;
+		return s->isValidTarget(false) && s->attackerOwned == !side;
 	});
 }
 
@@ -1304,8 +1304,8 @@ std::pair<const CStack *, BattleHex> CBattleInfoCallback::getNearestStack(const
 
 	std::vector<const CStack *> possibleStacks = battleGetStacksIf([=](const CStack * s)
 	{
-		return s != closest && s->alive() && (boost::logic::indeterminate(attackerOwned) || s->attackerOwned == attackerOwned);
-	}, false);
+		return s->isValidTarget(false) && s != closest && (boost::logic::indeterminate(attackerOwned) || s->attackerOwned == attackerOwned);
+	});
 
 	for(const CStack * st : possibleStacks)
 		for(BattleHex hex : avHexes)
@@ -2225,8 +2225,8 @@ TStacks CPlayerBattleCallback::battleGetStacks(EStackOwnership whose /*= MINE_AN
 		const bool ownerMatches = (whose == MINE_AND_ENEMY)
 			|| (whose == ONLY_MINE && s->owner == player)
 			|| (whose == ONLY_ENEMY && s->owner != player);
-		const bool alivenessMatches = s->alive()  ||  !onlyAlive;
-		return ownerMatches && alivenessMatches;
+
+		return ownerMatches && s->isValidTarget(!onlyAlive);
 	});
 }
 

+ 13 - 13
lib/CBattleCallback.h

@@ -56,7 +56,7 @@ protected:
 	CCallbackBase()
 		: battle(nullptr), gs(nullptr)
 	{}
-	
+
 	void setBattle(const BattleInfo *B);
 	bool duringBattle() const;
 
@@ -83,8 +83,8 @@ namespace EAccessibility
 {
 	enum EAccessibility
 	{
-		ACCESSIBLE, 
-		ALIVE_STACK, 
+		ACCESSIBLE,
+		ALIVE_STACK,
 		OBSTACLE,
 		DESTRUCTIBLE_WALL,
 		GATE, //sieges -> gate opens only for defender stacks
@@ -125,7 +125,7 @@ struct DLL_LINKAGE ReachabilityInfo
 	struct DLL_LINKAGE Parameters
 	{
 		const CStack *stack; //stack for which calculation is mage => not required (kept for debugging mostly), following variables are enough
-		
+
 		bool attackerOwned;
 		bool doubleWide;
 		bool flying;
@@ -171,15 +171,15 @@ public:
 	ETerrainType battleTerrainType() const;
 	BFieldType battleGetBattlefieldType() const;
 	std::vector<std::shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
-    
+
     /** @brief Main method for getting battle stacks
      *
      * @param predicate Functor that shall return true for desired stack
      * @return filtered stacks
      *
-     */                             	
-	TStacks battleGetStacksIf(TStackFilter predicate, bool includeTurrets = false) const;
-	
+     */
+	TStacks battleGetStacksIf(TStackFilter predicate) const;
+
 	bool battleHasNativeStack(ui8 side) const;
 	int battleGetMoatDmg() const; //what dmg unit will suffer if ending turn in the moat
 	const CGTownInstance * battleGetDefendedTown() const; //returns defended town if current battle is a siege, nullptr instead
@@ -193,7 +193,7 @@ public:
 	bool battleHasHero(ui8 side) const;
 	int battleCastSpells(ui8 side) const; //how many spells has given side cast
 	const CGHeroInstance * battleGetFightingHero(ui8 side) const; //depracated for players callback, easy to get wrong
-	const CArmedInstance * battleGetArmyObject(ui8 side) const; 
+	const CArmedInstance * battleGetArmyObject(ui8 side) const;
 	InfoAboutHero battleGetHeroInfo(ui8 side) const;
 
 	// for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall,
@@ -204,7 +204,7 @@ public:
 	//helpers
 	///returns all stacks, alive or dead or undead or mechanical :)
 	TStacks battleGetAllStacks(bool includeTurrets = false) const;
-	
+
 	///returns all alive stacks excluding turrets
 	TStacks battleAliveStacks() const;
 	///returns all alive stacks from particular side excluding turrets
@@ -255,12 +255,12 @@ public:
 	int battleGetSurrenderCost(PlayerColor Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible
 	ReachabilityInfo::TDistances battleGetDistances(const CStack * stack, BattleHex hex = BattleHex::INVALID, BattleHex * predecessors = nullptr) const; //returns vector of distances to [dest hex number]
 	std::set<BattleHex> battleGetAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const;
-	
+
 	bool battleCanAttack(const CStack * stack, const CStack * target, BattleHex dest) const; //determines if stack with given ID can attack target at the selected destination
 	bool battleCanShoot(const CStack * stack, BattleHex dest) const; //determines if stack with given ID shoot at the selected destination
 	bool battleIsStackBlocked(const CStack * stack) const; //returns true if there is neighboring enemy stack
 	std::set<const CStack*>  batteAdjacentCreatures (const CStack * stack) const;
-	
+
 	TDmgRange calculateDmgRange(const BattleAttackInfo &info) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
 	TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, TQuantity attackerCount, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
 	TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
@@ -278,7 +278,7 @@ public:
 	bool isWallPartPotentiallyAttackable(EWallPart::EWallPart wallPart) const; // returns true if the wall part is potentially attackable (independent of wall state), false if not
 	std::vector<BattleHex> getAttackableBattleHexes() const;
 
-	//*** MAGIC 
+	//*** MAGIC
 	si8 battleMaxSpellLevel(ui8 side) const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
 	ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
 	ESpellCastProblem::ESpellCastProblem battleCanCastSpell(PlayerColor player, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell

+ 2 - 4
lib/spells/CDefaultSpellMechanics.cpp

@@ -360,9 +360,8 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 		TStacks mirrorTargets = parameters.cb->battleGetStacksIf([this, parameters](const CStack * battleStack)
 		{
 			//Get all enemy stacks. Magic mirror can reflect to immune creature (with no effect)
-			return battleStack->owner == parameters.casterColor;
-		},
-		true);//turrets included
+			return battleStack->owner == parameters.casterColor && battleStack->isValidTarget(false);
+		});
 
 		if(!mirrorTargets.empty())
 		{
@@ -711,7 +710,6 @@ std::set<const CStack *> DefaultSpellMechanics::getAffectedStacks(SpellTargeting
 			//for massive spells add all targets
 			for (auto stack : stacks)
 				attackedCres.insert(stack);
-
 		}
 		else
 		{

+ 3 - 2
lib/spells/CSpellHandler.cpp

@@ -309,8 +309,9 @@ void CSpell::getEffects(std::vector<Bonus> & lst, const int level) const
 ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const
 {
 	// Get all stacks at destination hex. only alive if not rising spell
-	TStacks stacks = cb->battleGetStacksIf([=](const CStack * s){
-		return s->coversPos(destination) && (isRisingSpell() || s->alive());
+	TStacks stacks = cb->battleGetStacksIf([=](const CStack * s)
+	{
+		return s->coversPos(destination) && s->isValidTarget(isRisingSpell());
 	});
 
 	if(!stacks.empty())

+ 3 - 2
server/CGameHandler.cpp

@@ -5703,8 +5703,9 @@ void CGameHandler::runBattle()
 
 			if(next->getCreature()->idNumber == CreatureID::FIRST_AID_TENT)
 			{
-				TStacks possibleStacks = battleGetStacksIf([&](const CStack * s){
-					return s->owner == next->owner  &&  s->canBeHealed();
+				TStacks possibleStacks = battleGetStacksIf([=](const CStack * s)
+				{
+					return s->owner == next->owner && s->canBeHealed();
 				});
 
 				if(!possibleStacks.size())