mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Better handling of HYPNOTISED stacks in case of spellcasting
This commit is contained in:
parent
00bd1bd100
commit
f0713c1d36
@ -807,7 +807,7 @@ int CStack::getEffectValue(const CSpell * spell) const
|
|||||||
|
|
||||||
const PlayerColor CStack::getOwner() const
|
const PlayerColor CStack::getOwner() const
|
||||||
{
|
{
|
||||||
return owner;
|
return battle->battleGetOwner(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStack::getCasterName(MetaString & text) const
|
void CStack::getCasterName(MetaString & text) const
|
||||||
|
@ -360,8 +360,17 @@ bool CBattleInfoEssentials::battleMatchOwner(const CStack * attacker, const CSta
|
|||||||
return true;
|
return true;
|
||||||
else if(attacker == defender)
|
else if(attacker == defender)
|
||||||
return positivness;
|
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))
|
else if(defender->owner != battleGetOwner(defender))
|
||||||
return true; //mind controlled unit is attackable for both sides
|
return true; //mind controlled unit is attackable for both sides
|
||||||
else
|
else
|
||||||
return (battleGetOwner(attacker) == battleGetOwner(defender)) == positivness;
|
return (attacker == battleGetOwner(defender)) == positivness;
|
||||||
}
|
}
|
||||||
|
@ -101,4 +101,5 @@ public:
|
|||||||
///check that stacks are controlled by same|other player(s) depending on positiveness
|
///check that stacks are controlled by same|other player(s) depending on positiveness
|
||||||
///mind control included
|
///mind control included
|
||||||
bool battleMatchOwner(const CStack * attacker, const CStack * defender, const boost::logic::tribool positivness = false) const;
|
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;
|
||||||
};
|
};
|
||||||
|
@ -915,22 +915,23 @@ SpecialRisingSpellMechanics::SpecialRisingSpellMechanics(const CSpell * s):
|
|||||||
|
|
||||||
ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
|
ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
|
||||||
{
|
{
|
||||||
//find alive possible target
|
auto mainFilter = [cb, ctx, this](const CStack * s) -> bool
|
||||||
const CStack * stackToHeal = cb->getStackIf([ctx, this](const CStack * s)
|
|
||||||
{
|
{
|
||||||
const bool ownerMatches = !ctx.ti.smart || s->owner == ctx.caster->getOwner();
|
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);
|
||||||
return ownerMatches && s->isValidTarget(false) && s->coversPos(ctx.destination) && ESpellCastProblem::OK == owner->isImmuneByStack(ctx.caster, s);
|
};
|
||||||
|
//find alive possible target
|
||||||
|
const CStack * stackToHeal = cb->getStackIf([mainFilter](const CStack * s)
|
||||||
|
{
|
||||||
|
return s->isValidTarget(false) && mainFilter(s);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(nullptr == stackToHeal)
|
if(nullptr == stackToHeal)
|
||||||
{
|
{
|
||||||
//find dead possible target if there is no alive target
|
//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 s->isValidTarget(true) && mainFilter(s);
|
||||||
|
|
||||||
return ownerMatches && s->isValidTarget(true) && s->coversPos(ctx.destination) && ESpellCastProblem::OK == owner->isImmuneByStack(ctx.caster, s);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//we have found dead target
|
//we have found dead target
|
||||||
@ -940,7 +941,7 @@ ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCast(cons
|
|||||||
{
|
{
|
||||||
const CStack * other = cb->getStackIf([hex, stackToHeal](const CStack * s)
|
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)
|
if(nullptr != other)
|
||||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;//alive stack blocks resurrection
|
return ESpellCastProblem::NO_APPROPRIATE_TARGET;//alive stack blocks resurrection
|
||||||
|
@ -652,10 +652,9 @@ std::vector<const CStack *> DefaultSpellMechanics::calculateAffectedStacks(const
|
|||||||
|
|
||||||
auto mainFilter = [=](const CStack * s)
|
auto mainFilter = [=](const CStack * s)
|
||||||
{
|
{
|
||||||
const bool positiveToAlly = owner->isPositive() && s->owner == ctx.caster->getOwner();
|
const bool ownerMatches = cb->battleMatchOwner(ctx.caster->getOwner(), s, owner->getPositiveness());
|
||||||
const bool negativeToEnemy = owner->isNegative() && s->owner != ctx.caster->getOwner();
|
|
||||||
const bool validTarget = s->isValidTarget(!ctx.ti.onlyAlive); //todo: this should be handled by spell class
|
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;
|
return positivenessFlag && validTarget;
|
||||||
};
|
};
|
||||||
@ -719,28 +718,12 @@ ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBat
|
|||||||
{
|
{
|
||||||
std::vector<const CStack *> affected = getAffectedStacks(cb, ctx);
|
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;
|
bool targetExists = false;
|
||||||
|
|
||||||
for(const CStack * stack : affected)
|
for(const CStack * stack : affected)
|
||||||
{
|
{
|
||||||
bool casterStack = stack->owner == ctx.caster->getOwner();
|
targetExists = cb->battleMatchOwner(ctx.caster->getOwner(), stack, owner->getPositiveness());
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(targetExists)
|
if(targetExists)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -219,26 +219,9 @@ ESpellCastProblem::ESpellCastProblem CSpell::canBeCast(const CBattleInfoCallback
|
|||||||
|
|
||||||
for(const CStack * stack : cb->battleGetAllStacks())
|
for(const CStack * stack : cb->battleGetAllStacks())
|
||||||
{
|
{
|
||||||
bool immune = !(stack->isValidTarget(!tinfo.onlyAlive) && ESpellCastProblem::OK == isImmuneByStack(caster, stack));
|
const bool immune = !(stack->isValidTarget(!tinfo.onlyAlive) && ESpellCastProblem::OK == isImmuneByStack(caster, stack));
|
||||||
bool casterStack = stack->owner == caster->getOwner();
|
const bool ownerMatches = cb->battleMatchOwner(caster->getOwner(), stack, getPositiveness());
|
||||||
|
targetExists = !immune && ownerMatches;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(targetExists)
|
if(targetExists)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user