From a639bd2606b6ff2410d4a7bc8ca5bf685ca806a7 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Tue, 21 Mar 2023 12:18:31 +0300 Subject: [PATCH] spells: rework isMagical() Now it is a flag of a spell, and not a target condition. This fixes resistance to bind effect --- config/schemas/spell.json | 6 +++++- config/spells/ability.json | 1 + config/spells/moats.json | 23 +++++++++++++++-------- config/spells/vcmiAbility.json | 10 +++------- include/vcmi/spells/Spell.h | 1 + lib/spells/BattleSpellMechanics.cpp | 2 +- lib/spells/CSpellHandler.cpp | 8 ++++++++ lib/spells/CSpellHandler.h | 3 +++ lib/spells/ISpellMechanics.cpp | 5 +++++ lib/spells/ISpellMechanics.h | 2 ++ lib/spells/TargetCondition.cpp | 24 ++++++++++++------------ 11 files changed, 56 insertions(+), 29 deletions(-) diff --git a/config/schemas/spell.json b/config/schemas/spell.json index b8f2db0ad..7a368e1b6 100644 --- a/config/schemas/spell.json +++ b/config/schemas/spell.json @@ -233,7 +233,11 @@ "special":{ "type": "boolean", "description": "Special spell. Can be given only by Bonus::SPELL" - } + }, + "nonMagical":{ + "type": "boolean", + "description": "Non-magical ability. Usually used by some creatures. Should not be affected by sorcery and generic magic resistance. School resistances apply. Examples: dendroid bind, efreet fire shield." + } } }, "immunity":{ diff --git a/config/spells/ability.json b/config/spells/ability.json index abb661bff..05b53f71b 100644 --- a/config/spells/ability.json +++ b/config/spells/ability.json @@ -119,6 +119,7 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true } }, diff --git a/config/spells/moats.json b/config/spells/moats.json index 673de9dd3..ed12f7df3 100644 --- a/config/spells/moats.json +++ b/config/spells/moats.json @@ -34,6 +34,7 @@ "flags" : { "damage": true, "negative": true, + "nonMagical" : true, "special": true }, "targetCondition" : { @@ -82,10 +83,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } }, "rampartMoatTrigger" : @@ -123,6 +124,7 @@ "flags" : { "damage": true, "negative": true, + "nonMagical" : true, "special": true }, "targetCondition" : { @@ -171,10 +173,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } }, "towerMoat": { @@ -223,10 +225,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } }, "infernoMoatTrigger" : @@ -264,6 +266,7 @@ "flags" : { "damage": true, "negative": true, + "nonMagical" : true, "special": true }, "targetCondition" : { @@ -312,10 +315,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } }, "necropolisMoatTrigger" : @@ -353,6 +356,7 @@ "flags" : { "damage": true, "negative": true, + "nonMagical" : true, "special": true }, "targetCondition" : { @@ -401,10 +405,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } }, "dungeonMoatTrigger" : @@ -442,6 +446,7 @@ "flags" : { "damage": true, "negative": true, + "nonMagical" : true, "special": true }, "targetCondition" : { @@ -490,10 +495,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } }, "strongholdMoatTrigger" : @@ -531,6 +536,7 @@ "flags" : { "damage": true, "negative": true, + "nonMagical" : true, "special": true }, "targetCondition" : { @@ -579,10 +585,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } }, "fortressMoatTrigger" : @@ -620,6 +626,7 @@ "flags" : { "damage": true, "negative": true, + "nonMagical" : true, "special": true }, "targetCondition" : { @@ -668,10 +675,10 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true }, "targetCondition" : { - "nonMagical" : true } } } \ No newline at end of file diff --git a/config/spells/vcmiAbility.json b/config/spells/vcmiAbility.json index 8f54942d7..e16054a23 100644 --- a/config/spells/vcmiAbility.json +++ b/config/spells/vcmiAbility.json @@ -93,10 +93,10 @@ } }, "flags" : { + "nonMagical" : true, "positive": true }, "targetCondition" : { - "nonMagical" : true, "noneOf" : { "bonus.SIEGE_WEAPON" : "absolute" } @@ -179,10 +179,8 @@ } }, "flags" : { + "nonMagical" : true, "indifferent": true - }, - "targetCondition" : { - "nonMagical" : true } }, "cyclopsShot" : { @@ -227,10 +225,8 @@ "expert" : {} }, "flags" : { + "nonMagical" : true, "indifferent": true - }, - "targetCondition" : { - "nonMagical" : true } } } diff --git a/include/vcmi/spells/Spell.h b/include/vcmi/spells/Spell.h index 453187e00..c0da7cbf3 100644 --- a/include/vcmi/spells/Spell.h +++ b/include/vcmi/spells/Spell.h @@ -41,6 +41,7 @@ public: virtual bool isDamage() const = 0; virtual bool isOffensive() const = 0; virtual bool isSpecial() const = 0; + virtual bool isMagical() const = 0; //Should this spell considered as magical effect or as ability (like dendroid's bind) virtual void forEachSchool(const SchoolCallback & cb) const = 0; virtual const std::string & getCastSound() const = 0; diff --git a/lib/spells/BattleSpellMechanics.cpp b/lib/spells/BattleSpellMechanics.cpp index ee24016cd..0e56a5493 100644 --- a/lib/spells/BattleSpellMechanics.cpp +++ b/lib/spells/BattleSpellMechanics.cpp @@ -360,7 +360,7 @@ void BattleSpellMechanics::beforeCast(BattleSpellCast & sc, vstd::RNG & rng, con auto filterResisted = [&, this](const battle::Unit * unit) -> bool { - if(isNegativeSpell()) + if(isNegativeSpell() && isMagicalEffect()) { //magic resistance const int prob = std::min(unit->magicResistance(), 100); //probability of resistance in % diff --git a/lib/spells/CSpellHandler.cpp b/lib/spells/CSpellHandler.cpp index e069e86c1..7abe261d6 100644 --- a/lib/spells/CSpellHandler.cpp +++ b/lib/spells/CSpellHandler.cpp @@ -97,6 +97,7 @@ CSpell::CSpell(): damage(false), offensive(false), special(true), + nonMagical(false), targetType(spells::AimType::NO_TARGET) { levels.resize(GameConstants::SPELL_SCHOOL_LEVELS); @@ -236,6 +237,11 @@ bool CSpell::isCreatureAbility() const return creatureAbility; } +bool CSpell::isMagical() const +{ + return !nonMagical; +} + bool CSpell::isPositive() const { return positiveness == POSITIVE; @@ -751,6 +757,8 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode & spell->damage = flags["damage"].Bool(); //do this before "offensive" + spell->nonMagical = flags["nonMagical"].Bool(); + if(flags["offensive"].Bool()) { spell->setIsOffensive(true); diff --git a/lib/spells/CSpellHandler.h b/lib/spells/CSpellHandler.h index c00e40559..d86b819df 100644 --- a/lib/spells/CSpellHandler.h +++ b/lib/spells/CSpellHandler.h @@ -246,6 +246,7 @@ public: bool isPositive() const override; bool isNegative() const override; bool isNeutral() const override; + bool isMagical() const override; bool isDamage() const override; bool isOffensive() const override; @@ -297,6 +298,7 @@ public: h & levels; h & school; h & animationInfo; + h & nonMagical; } friend class CSpellHandler; friend class Graphics; @@ -338,6 +340,7 @@ private: bool damage; bool offensive; bool special; + bool nonMagical; //For creature abilities like bind std::string attributes; //reference only attributes //todo: remove or include in configuration format, currently unused diff --git a/lib/spells/ISpellMechanics.cpp b/lib/spells/ISpellMechanics.cpp index 3f70615f5..fc7a27d9f 100644 --- a/lib/spells/ISpellMechanics.cpp +++ b/lib/spells/ISpellMechanics.cpp @@ -617,6 +617,11 @@ bool BaseMechanics::isPositiveSpell() const return owner->isPositive(); } +bool BaseMechanics::isMagicalEffect() const +{ + return owner->isMagical(); +} + int64_t BaseMechanics::adjustEffectValue(const battle::Unit * target) const { return owner->adjustRawDamage(caster, target, getEffectValue()); diff --git a/lib/spells/ISpellMechanics.h b/lib/spells/ISpellMechanics.h index 17cdb684d..851653254 100644 --- a/lib/spells/ISpellMechanics.h +++ b/lib/spells/ISpellMechanics.h @@ -228,6 +228,7 @@ public: virtual bool isNegativeSpell() const = 0; virtual bool isPositiveSpell() const = 0; + virtual bool isMagicalEffect() const = 0; virtual int64_t adjustEffectValue(const battle::Unit * target) const = 0; virtual int64_t applySpellBonus(int64_t value, const battle::Unit * target) const = 0; @@ -288,6 +289,7 @@ public: bool isNegativeSpell() const override; bool isPositiveSpell() const override; + bool isMagicalEffect() const override; int64_t adjustEffectValue(const battle::Unit * target) const override; int64_t applySpellBonus(int64_t value, const battle::Unit * target) const override; diff --git a/lib/spells/TargetCondition.cpp b/lib/spells/TargetCondition.cpp index ff3b5e9c0..3f2d638e4 100644 --- a/lib/spells/TargetCondition.cpp +++ b/lib/spells/TargetCondition.cpp @@ -114,6 +114,10 @@ public: protected: bool check(const Mechanics * m, const battle::Unit * target) const override { + + if(!m->isMagicalEffect()) //Always pass on non-magical + return true; + std::stringstream cachingStr; cachingStr << "type_" << Bonus::LEVEL_SPELL_IMMUNITY << "addInfo_1"; @@ -189,6 +193,8 @@ public: protected: bool check(const Mechanics * m, const battle::Unit * target) const override { + if(!m->isMagicalEffect()) //Always pass on non-magical + return true; TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type()(Bonus::LEVEL_SPELL_IMMUNITY)); return levelImmunities->size() == 0 || levelImmunities->totalValue() < m->getSpellLevel() || @@ -426,7 +432,6 @@ bool TargetCondition::isReceptive(const Mechanics * m, const battle::Unit * targ void TargetCondition::serializeJson(JsonSerializeFormat & handler, const ItemFactory * itemFactory) { - bool isNonMagical = false; if(handler.saving) { logGlobal->error("Spell target condition saving is not supported"); @@ -438,17 +443,12 @@ void TargetCondition::serializeJson(JsonSerializeFormat & handler, const ItemFac negation.clear(); absolute.push_back(itemFactory->createAbsoluteSpell()); - - handler.serializeBool("nonMagical", isNonMagical); - if(!isNonMagical) - { - absolute.push_back(itemFactory->createAbsoluteLevel()); - normal.push_back(itemFactory->createElemental()); - normal.push_back(itemFactory->createNormalLevel()); - normal.push_back(itemFactory->createNormalSpell()); - negation.push_back(itemFactory->createReceptiveFeature()); - negation.push_back(itemFactory->createImmunityNegation()); - } + absolute.push_back(itemFactory->createAbsoluteLevel()); + normal.push_back(itemFactory->createElemental()); + normal.push_back(itemFactory->createNormalLevel()); + normal.push_back(itemFactory->createNormalSpell()); + negation.push_back(itemFactory->createReceptiveFeature()); + negation.push_back(itemFactory->createImmunityNegation()); { auto anyOf = handler.enterStruct("anyOf");