Bläddra i källkod

Better handling of HYPNOTISED stacks in case of spellcasting

AlexVinS 8 år sedan
förälder
incheckning
f0713c1d36

+ 1 - 1
lib/CStack.cpp

@@ -807,7 +807,7 @@ int CStack::getEffectValue(const CSpell * spell) const
 
 const PlayerColor CStack::getOwner() const
 {
-	return owner;
+	return battle->battleGetOwner(this);
 }
 
 void CStack::getCasterName(MetaString & text) const

+ 10 - 1
lib/battle/CBattleInfoEssentials.cpp

@@ -360,8 +360,17 @@ bool CBattleInfoEssentials::battleMatchOwner(const CStack * attacker, const CSta
 		return true;
 	else if(attacker == defender)
 		return positivness;
+	else
+		return battleMatchOwner(battleGetOwner(attacker), defender, positivness);
+}
+
+bool CBattleInfoEssentials::battleMatchOwner(const PlayerColor & attacker, const CStack * defender, const boost::logic::tribool positivness /* = false*/) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	if(boost::logic::indeterminate(positivness))
+		return true;
 	else if(defender->owner != battleGetOwner(defender))
 		return true; //mind controlled unit is attackable for both sides
 	else
-		return (battleGetOwner(attacker) == battleGetOwner(defender)) == positivness;
+		return (attacker == battleGetOwner(defender)) == positivness;
 }

+ 1 - 0
lib/battle/CBattleInfoEssentials.h

@@ -101,4 +101,5 @@ public:
 	///check that stacks are controlled by same|other player(s) depending on positiveness
 	///mind control included
 	bool battleMatchOwner(const CStack * attacker, const CStack * defender, const boost::logic::tribool positivness = false) const;
+	bool battleMatchOwner(const PlayerColor & attacker, const CStack * defender, const boost::logic::tribool positivness = false) const;
 };

+ 10 - 9
lib/spells/BattleSpellMechanics.cpp

@@ -915,22 +915,23 @@ SpecialRisingSpellMechanics::SpecialRisingSpellMechanics(const CSpell * s):
 
 ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
 {
+	auto mainFilter = [cb, ctx, this](const CStack * s) -> bool
+	{
+		const bool ownerMatches = !ctx.ti.smart || cb->battleMatchOwner(ctx.caster->getOwner(), s, owner->getPositiveness());
+		return ownerMatches && s->coversPos(ctx.destination) && ESpellCastProblem::OK == owner->isImmuneByStack(ctx.caster, s);
+	};
 	//find alive possible target
-	const CStack * stackToHeal = cb->getStackIf([ctx, this](const CStack * s)
+	const CStack * stackToHeal = cb->getStackIf([mainFilter](const CStack * s)
 	{
-		const bool ownerMatches = !ctx.ti.smart || s->owner == ctx.caster->getOwner();
-
-		return ownerMatches && s->isValidTarget(false) && s->coversPos(ctx.destination) && ESpellCastProblem::OK == owner->isImmuneByStack(ctx.caster, s);
+		return s->isValidTarget(false) && mainFilter(s);
 	});
 
 	if(nullptr == stackToHeal)
 	{
 		//find dead possible target if there is no alive target
-		stackToHeal = cb->getStackIf([ctx, this](const CStack * s)
+		stackToHeal = cb->getStackIf([mainFilter](const CStack * s)
 		{
-			const bool ownerMatches = !ctx.ti.smart || s->owner == ctx.caster->getOwner();
-
-			return ownerMatches && s->isValidTarget(true) && s->coversPos(ctx.destination) && ESpellCastProblem::OK == owner->isImmuneByStack(ctx.caster, s);
+			return s->isValidTarget(true) && mainFilter(s);
 		});
 
 		//we have found dead target
@@ -940,7 +941,7 @@ ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCast(cons
 			{
 				const CStack * other = cb->getStackIf([hex, stackToHeal](const CStack * s)
 				{
-					return s->isValidTarget(false) && s->coversPos(hex) && s != stackToHeal;
+					return s->isValidTarget(true) && s->coversPos(hex) && s != stackToHeal;
 				});
 				if(nullptr != other)
 					return ESpellCastProblem::NO_APPROPRIATE_TARGET;//alive stack blocks resurrection

+ 4 - 21
lib/spells/CDefaultSpellMechanics.cpp

@@ -652,10 +652,9 @@ std::vector<const CStack *> DefaultSpellMechanics::calculateAffectedStacks(const
 
 	auto mainFilter = [=](const CStack * s)
 	{
-		const bool positiveToAlly = owner->isPositive() && s->owner == ctx.caster->getOwner();
-		const bool negativeToEnemy = owner->isNegative() && s->owner != ctx.caster->getOwner();
+		const bool ownerMatches = cb->battleMatchOwner(ctx.caster->getOwner(), s, owner->getPositiveness());
 		const bool validTarget = s->isValidTarget(!ctx.ti.onlyAlive); //todo: this should be handled by spell class
-		const bool positivenessFlag = !ctx.ti.smart || owner->isNeutral() || positiveToAlly || negativeToEnemy;
+		const bool positivenessFlag = !ctx.ti.smart || ownerMatches;
 
 		return positivenessFlag && validTarget;
 	};
@@ -719,28 +718,12 @@ ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBat
 	{
 		std::vector<const CStack *> affected = getAffectedStacks(cb, ctx);
 
-		//allow to cast spell if affects is at least one smart target
+		//allow to cast spell if it affects at least one smart target
 		bool targetExists = false;
 
 		for(const CStack * stack : affected)
 		{
-			bool casterStack = stack->owner == ctx.caster->getOwner();
-
-			switch (owner->positiveness)
-			{
-			case CSpell::POSITIVE:
-				if(casterStack)
-					targetExists = true;
-				break;
-			case CSpell::NEUTRAL:
-				targetExists = true;
-				break;
-			case CSpell::NEGATIVE:
-				if(!casterStack)
-					targetExists = true;
-				break;
-			}
-
+			targetExists = cb->battleMatchOwner(ctx.caster->getOwner(), stack, owner->getPositiveness());
 			if(targetExists)
 				break;
 		}

+ 3 - 20
lib/spells/CSpellHandler.cpp

@@ -219,26 +219,9 @@ ESpellCastProblem::ESpellCastProblem CSpell::canBeCast(const CBattleInfoCallback
 
 				for(const CStack * stack : cb->battleGetAllStacks())
 				{
-					bool immune = !(stack->isValidTarget(!tinfo.onlyAlive) && ESpellCastProblem::OK == isImmuneByStack(caster, stack));
-					bool casterStack = stack->owner == caster->getOwner();
-
-					if(!immune)
-					{
-						switch (positiveness)
-						{
-						case CSpell::POSITIVE:
-							if(casterStack)
-								targetExists = true;
-							break;
-						case CSpell::NEUTRAL:
-								targetExists = true;
-								break;
-						case CSpell::NEGATIVE:
-							if(!casterStack)
-								targetExists = true;
-							break;
-						}
-					}
+					const bool immune = !(stack->isValidTarget(!tinfo.onlyAlive) && ESpellCastProblem::OK == isImmuneByStack(caster, stack));
+					const bool ownerMatches = cb->battleMatchOwner(caster->getOwner(), stack, getPositiveness());
+					targetExists = !immune && ownerMatches;
 					if(targetExists)
 						break;
 				}