From 057a33c508feb853dbc765587d60ab5900afc9ff Mon Sep 17 00:00:00 2001 From: Konstantin P Date: Fri, 5 May 2023 21:28:07 +0300 Subject: [PATCH] SpellSchool: use identifier instead of int Needs redifinition of MAGIC_SCHOOL_SKILL in all mods --- client/windows/CSpellWindow.cpp | 8 ++++---- config/artifacts.json | 8 ++++---- config/battlefields.json | 10 +++++----- config/creatures/neutral.json | 4 ++-- config/creatures/tower.json | 4 ++-- config/gameConfig.json | 1 + config/heroes/dungeon.json | 1 + config/heroes/fortress.json | 1 + config/heroes/inferno.json | 1 + config/heroes/necropolis.json | 1 + config/heroes/stronghold.json | 2 ++ config/skills.json | 9 +++++---- config/spells/timed.json | 8 ++++---- lib/CCreatureHandler.cpp | 12 ++++++------ lib/CModHandler.cpp | 7 +++++++ lib/GameConstants.h | 8 ++++++-- lib/bonuses/BonusParams.cpp | 28 ++++++++++++++++------------ lib/mapObjects/CGHeroInstance.cpp | 10 +++++----- lib/rmg/TreasurePlacer.cpp | 2 +- lib/spells/AbilityCaster.cpp | 2 +- lib/spells/CSpellHandler.cpp | 14 +++++++------- lib/spells/CSpellHandler.h | 9 +++++++-- lib/spells/effects/Damage.cpp | 4 ++-- test/spells/AbilityCasterTest.cpp | 4 ++-- 24 files changed, 93 insertions(+), 65 deletions(-) diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index 3c5cd0224..953be95c8 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -82,11 +82,11 @@ public: return false; - for(ui8 schoolId = 0; schoolId < 4; schoolId++) + for(auto schoolId = 0; schoolId < GameConstants::DEFAULT_SCHOOLS; schoolId++) { - if(A->school.at((ESpellSchool)schoolId) && !B->school.at((ESpellSchool)schoolId)) + if(A->school.at(SpellSchool(schoolId)) && !B->school.at(SpellSchool(schoolId))) return true; - if(!A->school.at((ESpellSchool)schoolId) && B->school.at((ESpellSchool)schoolId)) + if(!A->school.at(SpellSchool(schoolId)) && B->school.at(SpellSchool(schoolId))) return false; } @@ -320,7 +320,7 @@ void CSpellWindow::computeSpellsPerArea() for(const CSpell * spell : mySpells) { if(spell->isCombat() ^ !battleSpellsOnly - && ((selectedTab == 4) || spell->school.at((ESpellSchool)selectedTab)) + && ((selectedTab == 4) || spell->school.at(SpellSchool(selectedTab))) ) { spellsCurSite.push_back(spell); diff --git a/config/artifacts.json b/config/artifacts.json index 316ed5346..3ea52075d 100644 --- a/config/artifacts.json +++ b/config/artifacts.json @@ -1185,7 +1185,7 @@ "bonuses" : [ { "type" : "SPELL_DAMAGE", - "subtype" : 0, + "subtype" : "spellSchool.air", "val" : 50, "valueType" : "BASE_NUMBER" } @@ -1198,7 +1198,7 @@ "bonuses" : [ { "type" : "SPELL_DAMAGE", - "subtype" : 3, + "subtype" : "spellSchool.earth", "val" : 50, "valueType" : "BASE_NUMBER" } @@ -1211,7 +1211,7 @@ "bonuses" : [ { "type" : "SPELL_DAMAGE", - "subtype" : 1, + "subtype" : "spellSchool.fire", "val" : 50, "valueType" : "BASE_NUMBER" } @@ -1224,7 +1224,7 @@ "bonuses" : [ { "type" : "SPELL_DAMAGE", - "subtype" : 2, + "subtype" : "spellSchool.water", "val" : 50, "valueType" : "BASE_NUMBER" } diff --git a/config/battlefields.json b/config/battlefields.json index 8296c9236..b79f705a3 100644 --- a/config/battlefields.json +++ b/config/battlefields.json @@ -13,7 +13,7 @@ "bonuses": [ { "type" : "MAGIC_SCHOOL_SKILL", - "subtype" : 0, + "subtype" : "spellSchool.any", "val" : 3, "valueType" : "BASE_NUMBER" } @@ -29,7 +29,7 @@ "bonuses": [ { "type" : "MAGIC_SCHOOL_SKILL", - "subtype" : 2, + "subtype" : "spellSchool.fire", "val" : 3, "valueType" : "BASE_NUMBER" } @@ -41,7 +41,7 @@ "bonuses": [ { "type" : "MAGIC_SCHOOL_SKILL", - "subtype" : 8, + "subtype" : "spellSchool.earth", "val" : 3, "valueType" : "BASE_NUMBER" } @@ -53,7 +53,7 @@ "bonuses": [ { "type" : "MAGIC_SCHOOL_SKILL", - "subtype" : 1, + "subtype" : "spellSchool.air", "val" : 3, "valueType" : "BASE_NUMBER" } @@ -65,7 +65,7 @@ "bonuses": [ { "type" : "MAGIC_SCHOOL_SKILL", - "subtype" : 4, + "subtype" : "spellSchool.water", "val" : 3, "valueType" : "BASE_NUMBER" } diff --git a/config/creatures/neutral.json b/config/creatures/neutral.json index 8948f3b34..a5f073ba6 100644 --- a/config/creatures/neutral.json +++ b/config/creatures/neutral.json @@ -10,7 +10,7 @@ "magicResistance" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : -1, + "subtype" : "spellSchool.any", "val" : 85 }, "nonliving" : @@ -41,7 +41,7 @@ "magicResistance" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : -1, + "subtype" : "spellSchool.any", "val" : 95 }, "nonliving" : diff --git a/config/creatures/tower.json b/config/creatures/tower.json index 8557127a1..2c5c10f7c 100644 --- a/config/creatures/tower.json +++ b/config/creatures/tower.json @@ -105,7 +105,7 @@ "magicResistance" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : -1, + "subtype" : "spellSchool.any", "val" : 50 }, "nonliving" : @@ -137,7 +137,7 @@ "magicResistance" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : -1, + "subtype" : "spellSchool.any", "val" : 75 }, "nonliving" : diff --git a/config/gameConfig.json b/config/gameConfig.json index dd039fe04..9a282f946 100644 --- a/config/gameConfig.json +++ b/config/gameConfig.json @@ -215,6 +215,7 @@ "spellDamage" : { "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "val" : 100, "valueType" : "BASE_NUMBER" }, diff --git a/config/heroes/dungeon.json b/config/heroes/dungeon.json index 44752a81e..60de72575 100644 --- a/config/heroes/dungeon.json +++ b/config/heroes/dungeon.json @@ -186,6 +186,7 @@ "sorcery" : { "targetSourceType" : "SECONDARY_SKILL", "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "updater" : "TIMES_HERO_LEVEL", "val" : 5, "valueType" : "PERCENT_TO_TARGET_TYPE" diff --git a/config/heroes/fortress.json b/config/heroes/fortress.json index 02e26a329..206164ff3 100644 --- a/config/heroes/fortress.json +++ b/config/heroes/fortress.json @@ -262,6 +262,7 @@ "sorcery" : { "targetSourceType" : "SECONDARY_SKILL", "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "updater" : "TIMES_HERO_LEVEL", "val" : 5, "valueType" : "PERCENT_TO_TARGET_TYPE" diff --git a/config/heroes/inferno.json b/config/heroes/inferno.json index b6c9bdcb5..7b67505fc 100644 --- a/config/heroes/inferno.json +++ b/config/heroes/inferno.json @@ -261,6 +261,7 @@ "sorcery" : { "targetSourceType" : "SECONDARY_SKILL", "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "updater" : "TIMES_HERO_LEVEL", "val" : 5, "valueType" : "PERCENT_TO_TARGET_TYPE" diff --git a/config/heroes/necropolis.json b/config/heroes/necropolis.json index 3cc272494..f738b387e 100644 --- a/config/heroes/necropolis.json +++ b/config/heroes/necropolis.json @@ -192,6 +192,7 @@ "sorcery" : { "targetSourceType" : "SECONDARY_SKILL", "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "updater" : "TIMES_HERO_LEVEL", "val" : 5, "valueType" : "PERCENT_TO_TARGET_TYPE" diff --git a/config/heroes/stronghold.json b/config/heroes/stronghold.json index 7747bea88..6f08653b6 100644 --- a/config/heroes/stronghold.json +++ b/config/heroes/stronghold.json @@ -135,6 +135,7 @@ "sorcery" : { "targetSourceType" : "SECONDARY_SKILL", "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "updater" : "TIMES_HERO_LEVEL", "val" : 5, "valueType" : "PERCENT_TO_TARGET_TYPE" @@ -239,6 +240,7 @@ "sorcery" : { "targetSourceType" : "SECONDARY_SKILL", "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "updater" : "TIMES_HERO_LEVEL", "val" : 5, "valueType" : "PERCENT_TO_TARGET_TYPE" diff --git a/config/skills.json b/config/skills.json index db15461c5..528b6f381 100644 --- a/config/skills.json +++ b/config/skills.json @@ -406,7 +406,7 @@ "base" : { "effects" : { "main" : { - "subtype" : 2, + "subtype" : "spellSchool.fire", "type" : "MAGIC_SCHOOL_SKILL", "valueType" : "BASE_NUMBER" } @@ -434,7 +434,7 @@ "base" : { "effects" : { "main" : { - "subtype" : 1, + "subtype" : "spellSchool.air", "type" : "MAGIC_SCHOOL_SKILL", "valueType" : "BASE_NUMBER" } @@ -462,7 +462,7 @@ "base" : { "effects" : { "main" : { - "subtype" : 4, + "subtype" : "spellSchool.water", "type" : "MAGIC_SCHOOL_SKILL", "valueType" : "BASE_NUMBER" } @@ -490,7 +490,7 @@ "base" : { "effects" : { "main" : { - "subtype" : 8, + "subtype" : "spellSchool.earth", "type" : "MAGIC_SCHOOL_SKILL", "valueType" : "BASE_NUMBER" } @@ -737,6 +737,7 @@ "effects" : { "main" : { "type" : "SPELL_DAMAGE", + "subtype" : "spellSchool.any", "valueType" : "BASE_NUMBER" } } diff --git a/config/spells/timed.json b/config/spells/timed.json index a30b58cf5..758e28abb 100644 --- a/config/spells/timed.json +++ b/config/spells/timed.json @@ -104,7 +104,7 @@ "effects" : { "spellDamageReduction" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : 0, + "subtype" : "spellSchool.air", "duration" : "N_TURNS", "val" : 30 } @@ -147,7 +147,7 @@ "effects" : { "spellDamageReduction" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : 1, + "subtype" : "spellSchool.fire", "duration" : "N_TURNS", "val" : 30 } @@ -190,7 +190,7 @@ "effects" : { "spellDamageReduction" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : 2, + "subtype" : "spellSchool.water", "duration" : "N_TURNS", "val" : 30 } @@ -233,7 +233,7 @@ "effects" : { "spellDamageReduction" : { "type" : "SPELL_DAMAGE_REDUCTION", - "subtype" : 3, + "subtype" : "spellSchool.earth", "duration" : "N_TURNS", "val" : 30 } diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index f7c81d49a..4d6ccbe94 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -1059,7 +1059,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars b.type = BonusType::FEAR; break; case 'g': b.type = BonusType::SPELL_DAMAGE_REDUCTION; - b.subtype = -1; //all magic schools + b.subtype = SpellSchool(ESpellSchool::ANY); break; case 'P': b.type = BonusType::CASTS; break; @@ -1179,7 +1179,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars break; case 'O': b.type = BonusType::SPELL_DAMAGE_REDUCTION; - b.subtype = 1; //Fire school + b.subtype = SpellSchool(ESpellSchool::FIRE); b.val = 100; //Full damage immunity break; case 'f': @@ -1192,7 +1192,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars break; case 'W': b.type = BonusType::SPELL_DAMAGE_REDUCTION; - b.subtype = 2; //Water school + b.subtype = SpellSchool(ESpellSchool::WATER); b.val = 100; //Full damage immunity break; case 'w': @@ -1201,7 +1201,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars break; case 'E': b.type = BonusType::SPELL_DAMAGE_REDUCTION; - b.subtype = 3; //Earth school + b.subtype = SpellSchool(ESpellSchool::EARTH); b.val = 100; //Full damage immunity break; case 'e': @@ -1210,7 +1210,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars break; case 'A': b.type = BonusType::SPELL_DAMAGE_REDUCTION; - b.subtype = 0; //Air school + b.subtype = SpellSchool(ESpellSchool::AIR); b.val = 100; //Full damage immunity break; case 'a': @@ -1219,7 +1219,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars break; case 'D': b.type = BonusType::SPELL_DAMAGE_REDUCTION; - b.subtype = -1; //all + b.subtype = SpellSchool(ESpellSchool::ANY); b.val = 100; //Full damage immunity break; case '0': diff --git a/lib/CModHandler.cpp b/lib/CModHandler.cpp index 410e0ac47..0f301efe7 100644 --- a/lib/CModHandler.cpp +++ b/lib/CModHandler.cpp @@ -7,6 +7,7 @@ * Full text of license available in license.txt file, in main folder * */ +#include "GameConstants.h" #include "StdInc.h" #include "CModHandler.h" #include "mapObjects/CObjectClassesHandler.h" @@ -745,6 +746,12 @@ void CModInfo::setEnabled(bool on) CModHandler::CModHandler() : content(std::make_shared()) { + //TODO: moddable spell schools + for (auto i = 0; i < GameConstants::DEFAULT_SCHOOLS; ++i) + identifiers.registerObject(CModHandler::scopeBuiltin(), "spellSchool", SpellConfig::SCHOOL[i].jsonName, SpellConfig::SCHOOL[i].id); + + identifiers.registerObject(CModHandler::scopeBuiltin(), "spellSchool", "any", SpellSchool(ESpellSchool::ANY)); + for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i) { identifiers.registerObject(CModHandler::scopeBuiltin(), "resource", GameConstants::RESOURCE_NAMES[i], i); diff --git a/lib/GameConstants.h b/lib/GameConstants.h index ea58db8c8..77679241f 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -50,6 +50,7 @@ namespace GameConstants constexpr int CREATURES_PER_TOWN = 7; //without upgrades constexpr int SPELL_LEVELS = 5; constexpr int SPELL_SCHOOL_LEVELS = 4; + constexpr int DEFAULT_SCHOOLS = 4; constexpr int CRE_LEVELS = 10; // number of creature experience levels constexpr int HERO_GOLD_COST = 2500; @@ -1296,14 +1297,17 @@ class Obstacle : public BaseForID DLL_LINKAGE static Obstacle fromString(const std::string & identifier); }; -enum class ESpellSchool: ui8 +enum class ESpellSchool: int8_t { + ANY = -1, AIR = 0, FIRE = 1, WATER = 2, - EARTH = 3 + EARTH = 3, }; +using SpellSchool = Identifier; + enum class EMetaclass: ui8 { INVALID = 0, diff --git a/lib/bonuses/BonusParams.cpp b/lib/bonuses/BonusParams.cpp index 7ad93d44f..64c5a2eeb 100644 --- a/lib/bonuses/BonusParams.cpp +++ b/lib/bonuses/BonusParams.cpp @@ -74,7 +74,10 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu valueType = BonusValueType::PERCENT_TO_BASE; } else if(deprecatedSubtype == SecondarySkill::SORCERY || deprecatedSubtypeStr == "skill.sorcery") + { type = BonusType::SPELL_DAMAGE; + subtype = SpellSchool(ESpellSchool::ANY); + } else if(deprecatedSubtype == SecondarySkill::SCHOLAR || deprecatedSubtypeStr == "skill.scholar") type = BonusType::LEARN_MEETING_SPELL_LIMIT; else if(deprecatedSubtype == SecondarySkill::ARCHERY|| deprecatedSubtypeStr == "skill.archery") @@ -112,22 +115,22 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu else if(deprecatedSubtype == SecondarySkill::AIR_MAGIC || deprecatedSubtypeStr == "skill.airMagic") { type = BonusType::MAGIC_SCHOOL_SKILL; - subtype = 4; + subtype = SpellSchool(ESpellSchool::AIR); } else if(deprecatedSubtype == SecondarySkill::WATER_MAGIC || deprecatedSubtypeStr == "skill.waterMagic") { type = BonusType::MAGIC_SCHOOL_SKILL; - subtype = 1; + subtype = SpellSchool(ESpellSchool::WATER); } else if(deprecatedSubtype == SecondarySkill::FIRE_MAGIC || deprecatedSubtypeStr == "skill.fireMagic") { type = BonusType::MAGIC_SCHOOL_SKILL; - subtype = 2; + subtype = SpellSchool(ESpellSchool::FIRE); } else if(deprecatedSubtype == SecondarySkill::EARTH_MAGIC || deprecatedSubtypeStr == "skill.earthMagic") { type = BonusType::MAGIC_SCHOOL_SKILL; - subtype = 8; + subtype = SpellSchool(ESpellSchool::EARTH); } else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery") { @@ -215,47 +218,48 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu else if (deprecatedTypeStr == "DIRECT_DAMAGE_IMMUNITY") { type = BonusType::SPELL_DAMAGE_REDUCTION; + subtype = SpellSchool(ESpellSchool::ANY); val = 100; } else if (deprecatedTypeStr == "AIR_SPELL_DMG_PREMY") { type = BonusType::SPELL_DAMAGE; - subtype = 0; + subtype = SpellSchool(ESpellSchool::AIR); } else if (deprecatedTypeStr == "FIRE_SPELL_DMG_PREMY") { type = BonusType::SPELL_DAMAGE; - subtype = 1; + subtype = SpellSchool(ESpellSchool::FIRE); } else if (deprecatedTypeStr == "WATER_SPELL_DMG_PREMY") { type = BonusType::SPELL_DAMAGE; - subtype = 2; + subtype = SpellSchool(ESpellSchool::WATER); } else if (deprecatedTypeStr == "EARTH_SPELL_DMG_PREMY") { type = BonusType::SPELL_DAMAGE; - subtype = 3; + subtype = SpellSchool(ESpellSchool::EARTH); } else if (deprecatedTypeStr == "AIR_SPELLS") { type = BonusType::SPELLS_OF_SCHOOL; - subtype = 0; + subtype = SpellSchool(ESpellSchool::AIR); } else if (deprecatedTypeStr == "FIRE_SPELLS") { type = BonusType::SPELLS_OF_SCHOOL; - subtype = 1; + subtype = SpellSchool(ESpellSchool::FIRE); } else if (deprecatedTypeStr == "WATER_SPELLS") { type = BonusType::SPELLS_OF_SCHOOL; - subtype = 2; + subtype = SpellSchool(ESpellSchool::WATER); } else if (deprecatedTypeStr == "EARTH_SPELLS") { type = BonusType::SPELLS_OF_SCHOOL; - subtype = 3; + subtype = SpellSchool(ESpellSchool::EARTH); } else isConverted = false; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 423f5bcc0..cdc8bed93 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -589,7 +589,7 @@ int32_t CGHeroInstance::getSpellSchoolLevel(const spells::Spell * spell, int32_t spell->forEachSchool([&, this](const spells::SchoolInfo & cnf, bool & stop) { - int32_t thisSchool = valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, 1 << (static_cast(cnf.id))); //FIXME: Bonus shouldn't be additive (Witchking Artifacts : Crown of Skies) + int32_t thisSchool = valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, cnf.id); //FIXME: Bonus shouldn't be additive (Witchking Artifacts : Crown of Skies) if(thisSchool > skill) { skill = thisSchool; @@ -598,7 +598,7 @@ int32_t CGHeroInstance::getSpellSchoolLevel(const spells::Spell * spell, int32_t } }); - vstd::amax(skill, valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, 0)); //any school bonus + vstd::amax(skill, valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, SpellSchool(ESpellSchool::ANY))); //any school bonus vstd::amax(skill, valOfBonuses(BonusType::SPELL, spell->getIndex())); //given by artifact or other effect vstd::amax(skill, 0); //in case we don't know any school @@ -611,7 +611,7 @@ int64_t CGHeroInstance::getSpellBonus(const spells::Spell * spell, int64_t base, //applying sorcery secondary skill if(spell->isMagical()) - base = static_cast(base * (valOfBonuses(BonusType::SPELL_DAMAGE)) / 100.0); + base = static_cast(base * (valOfBonuses(BonusType::SPELL_DAMAGE, SpellSchool(ESpellSchool::ANY))) / 100.0); base = static_cast(base * (100 + valOfBonuses(BonusType::SPECIFIC_SPELL_DAMAGE, spell->getIndex())) / 100.0); @@ -619,7 +619,7 @@ int64_t CGHeroInstance::getSpellBonus(const spells::Spell * spell, int64_t base, spell->forEachSchool([&maxSchoolBonus, this](const spells::SchoolInfo & cnf, bool & stop) { - vstd::amax(maxSchoolBonus, valOfBonuses(BonusType::SPELL_DAMAGE, vstd::to_underlying(cnf.id))); + vstd::amax(maxSchoolBonus, valOfBonuses(BonusType::SPELL_DAMAGE, cnf.id)); }); base = static_cast(base * (100 + maxSchoolBonus) / 100.0); @@ -708,7 +708,7 @@ bool CGHeroInstance::canCastThisSpell(const spells::Spell * spell) const spell->forEachSchool([this, &schoolBonus](const spells::SchoolInfo & cnf, bool & stop) { - if(hasBonusOfType(BonusType::SPELLS_OF_SCHOOL, vstd::to_underlying(cnf.id))) + if(hasBonusOfType(BonusType::SPELLS_OF_SCHOOL, cnf.id)) { schoolBonus = stop = true; } diff --git a/lib/rmg/TreasurePlacer.cpp b/lib/rmg/TreasurePlacer.cpp index 87b767f33..122b80855 100644 --- a/lib/rmg/TreasurePlacer.cpp +++ b/lib/rmg/TreasurePlacer.cpp @@ -343,7 +343,7 @@ void TreasurePlacer::addAllPossibleObjects() std::vector spells; for(auto spell : VLC->spellh->objects) { - if(map.isAllowedSpell(spell->id) && spell->school[static_cast(i)]) + if(map.isAllowedSpell(spell->id) && spell->school[SpellSchool(i)]) spells.push_back(spell); } diff --git a/lib/spells/AbilityCaster.cpp b/lib/spells/AbilityCaster.cpp index 20bb76600..d7e138d11 100644 --- a/lib/spells/AbilityCaster.cpp +++ b/lib/spells/AbilityCaster.cpp @@ -35,7 +35,7 @@ int32_t AbilityCaster::getSpellSchoolLevel(const Spell * spell, int32_t * outSel if(spell->getLevel() > 0) { - vstd::amax(skill, unit->valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, 0)); + vstd::amax(skill, unit->valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, SpellSchool(ESpellSchool::ANY))); } vstd::amax(skill, 0); diff --git a/lib/spells/CSpellHandler.cpp b/lib/spells/CSpellHandler.cpp index 15ec74200..75da3ad99 100644 --- a/lib/spells/CSpellHandler.cpp +++ b/lib/spells/CSpellHandler.cpp @@ -38,7 +38,7 @@ namespace SpellConfig { static const std::string LEVEL_NAMES[] = {"none", "basic", "advanced", "expert"}; -static const spells::SchoolInfo SCHOOL[4] = +const spells::SchoolInfo SCHOOL[4] = { { ESpellSchool::AIR, @@ -63,7 +63,7 @@ static const spells::SchoolInfo SCHOOL[4] = }; //order as described in http://bugs.vcmi.eu/view.php?id=91 -static const ESpellSchool SCHOOL_ORDER[4] = +static const SpellSchool SCHOOL_ORDER[4] = { ESpellSchool::AIR, //=0 ESpellSchool::FIRE, //=1 @@ -150,9 +150,9 @@ spells::AimType CSpell::getTargetType() const void CSpell::forEachSchool(const std::function& cb) const { bool stop = false; - for(ESpellSchool iter : SpellConfig::SCHOOL_ORDER) + for(auto iter : SpellConfig::SCHOOL_ORDER) { - const spells::SchoolInfo & cnf = SpellConfig::SCHOOL[static_cast(iter)]; + const spells::SchoolInfo & cnf = SpellConfig::SCHOOL[iter]; if(school.at(cnf.id)) { cb(cnf, stop); @@ -381,15 +381,15 @@ int64_t CSpell::adjustRawDamage(const spells::Caster * caster, const battle::Uni //applying protections - when spell has more then one elements, only one protection should be applied (I think) forEachSchool([&](const spells::SchoolInfo & cnf, bool & stop) { - if(bearer->hasBonusOfType(BonusType::SPELL_DAMAGE_REDUCTION, static_cast(cnf.id))) + if(bearer->hasBonusOfType(BonusType::SPELL_DAMAGE_REDUCTION, cnf.id)) { - ret *= 100 - bearer->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, static_cast(cnf.id)); + ret *= 100 - bearer->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, cnf.id); ret /= 100; stop = true; //only bonus from one school is used } }); - CSelector selector = Selector::type()(BonusType::SPELL_DAMAGE_REDUCTION).And(Selector::subtype()(-1)); + CSelector selector = Selector::typeSubtype(BonusType::SPELL_DAMAGE_REDUCTION, SpellSchool(ESpellSchool::ANY)); //general spell dmg reduction, works only on magical effects if(bearer->hasBonus(selector) && isMagical()) diff --git a/lib/spells/CSpellHandler.h b/lib/spells/CSpellHandler.h index 3653950ab..90966df1f 100644 --- a/lib/spells/CSpellHandler.h +++ b/lib/spells/CSpellHandler.h @@ -43,13 +43,18 @@ class IBattleCast; struct SchoolInfo { - ESpellSchool id; //backlink + SpellSchool id; //backlink BonusType immunityBonus; std::string jsonName; }; } +namespace SpellConfig +{ + extern const spells::SchoolInfo SCHOOL[4]; +} + enum class VerticalPosition : ui8{TOP, CENTER, BOTTOM}; class DLL_LINKAGE CSpell : public spells::Spell @@ -185,7 +190,7 @@ public: si32 level; - std::map school; + std::map school; si32 power; //spell's power diff --git a/lib/spells/effects/Damage.cpp b/lib/spells/effects/Damage.cpp index 8715eb5f9..0659452ce 100644 --- a/lib/spells/effects/Damage.cpp +++ b/lib/spells/effects/Damage.cpp @@ -85,11 +85,11 @@ bool Damage::isReceptive(const Mechanics * m, const battle::Unit * unit) const if(!UnitEffect::isReceptive(m, unit)) return false; - bool isImmune = m->getSpell()->isMagical() && (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, -1) >= 100); //General spell damage immunity + bool isImmune = m->getSpell()->isMagical() && (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, SpellSchool(ESpellSchool::ANY)) >= 100); //General spell damage immunity //elemental immunity for damage m->getSpell()->forEachSchool([&](const SchoolInfo & cnf, bool & stop) { - isImmune |= (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, static_cast(cnf.id)) >= 100); //100% reduction is immunity + isImmune |= (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, cnf.id) >= 100); //100% reduction is immunity }); return !isImmune; diff --git a/test/spells/AbilityCasterTest.cpp b/test/spells/AbilityCasterTest.cpp index 9b22a16fa..e9f9a47e7 100644 --- a/test/spells/AbilityCasterTest.cpp +++ b/test/spells/AbilityCasterTest.cpp @@ -56,7 +56,7 @@ TEST_F(AbilityCasterTest, MagicAbilityAffectedByGenericBonus) { EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1)); - casterBonuses.addNewBonus(std::make_shared(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, 0)); + casterBonuses.addNewBonus(std::make_shared(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, SpellSchool(ESpellSchool::ANY))); EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1)); EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0)); @@ -70,7 +70,7 @@ TEST_F(AbilityCasterTest, MagicAbilityIngoresSchoolBonus) { EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1)); - casterBonuses.addNewBonus(std::make_shared(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, 1)); + casterBonuses.addNewBonus(std::make_shared(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, SpellSchool(ESpellSchool::AIR))); EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1)); EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0));