1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Partial fix for 1791

This commit is contained in:
AlexVinS 2015-09-17 13:23:13 +03:00
parent a44c606277
commit 253b850ac3
5 changed files with 32 additions and 7 deletions

View File

@ -1324,10 +1324,17 @@
"bonuses" : [
{
"type" : "NEGATE_ALL_NATURAL_IMMUNITIES",
"subtype" : 0,
"val" : 0,
"valueType" : "BASE_NUMBER",
"propagator": "BATTLE_WIDE"
}
},
{
"type" : "NEGATE_ALL_NATURAL_IMMUNITIES",
"subtype" : 1,
"val" : 0,
"valueType" : "BASE_NUMBER"
}
],
"index" : 93,
"type" : ["HERO"]

View File

@ -13,6 +13,7 @@
#include "../NetPacks.h"
#include "../BattleState.h"
#include "../mapObjects/CGHeroInstance.h"
///HealingSpellMechanics
void HealingSpellMechanics::applyBattleEffects(const SpellCastEnvironment* env, BattleSpellCastParameters& parameters, SpellCastContext& ctx) const
@ -505,13 +506,18 @@ ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCasted(const CBatt
bool targetExists = false;
bool targetToSacrificeExists = false;
const CGHeroInstance * caster = nullptr; //todo: use ISpellCaster
if(cb->battleHasHero(cb->playerToSide(player)))
caster = cb->battleGetFightingHero(cb->playerToSide(player));
for(const CStack * stack : cb->battleGetAllStacks())
{
//using isImmuneBy directly as this mechanics does not have overridden immunity check
//therefore we do not need to check caster and casting mode
//TODO: check that we really should check immunity for both stacks
ESpellCastProblem::ESpellCastProblem res = owner->isImmuneBy(stack);
ESpellCastProblem::ESpellCastProblem res = owner->internalIsImmune(caster, stack);
const bool immune = ESpellCastProblem::OK != res && ESpellCastProblem::NOT_DECIDED != res;
const bool casterStack = stack->owner == player;

View File

@ -746,7 +746,7 @@ ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCasted(const CB
ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
{
//by default use general algorithm
return owner->isImmuneBy(obj);
return owner->internalIsImmune(caster, obj);
}
void DefaultSpellMechanics::doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const

View File

@ -402,7 +402,7 @@ int CSpell::calculateRawEffectValue(int effectLevel, int effectPower) const
return effectPower * power + getPower(effectLevel);
}
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj) const
ESpellCastProblem::ESpellCastProblem CSpell::internalIsImmune(const ISpellCaster * caster, const CStack *obj) const
{
//todo: use new bonus API
//1. Check absolute limiters
@ -435,9 +435,21 @@ ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj)
return ESpellCastProblem::OK;
//3. Check negation
//FIXME: Orb of vulnerability mechanics is not such trivial
if(obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES)) //Orb of vulnerability
//Orb of vulnerability
//FIXME: Orb of vulnerability mechanics is not such trivial (issue 1791)
const bool battleWideNegation = obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES, 0);
const bool heroNegation = obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES, 1);
//anyone can cast on artifact holder`s stacks
if(heroNegation)
return ESpellCastProblem::NOT_DECIDED;
//this stack is from other player
//todo: check that caster is always present (not trivial is this case)
//todo: NEGATE_ALL_NATURAL_IMMUNITIES special cases: dispell, chain lightning
else if(battleWideNegation && caster)
{
if(obj->owner != caster->getOwner())
return ESpellCastProblem::NOT_DECIDED;
}
//4. Check negatable limit
for(auto b : limiters)

View File

@ -298,7 +298,7 @@ public://internal, for use only by Mechanics classes
///returns raw damage or healed HP
int calculateRawEffectValue(int effectLevel, int effectPower) const;
///generic immunity calculation
ESpellCastProblem::ESpellCastProblem isImmuneBy(const IBonusBearer *obj) const;
ESpellCastProblem::ESpellCastProblem internalIsImmune(const ISpellCaster * caster, const CStack *obj) const;
private:
void setIsOffensive(const bool val);