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

SpellSchool: use identifier instead of int

Needs redifinition of MAGIC_SCHOOL_SKILL in all mods
This commit is contained in:
Konstantin P 2023-05-05 21:28:07 +03:00 committed by Konstantin
parent 8600e3035a
commit 057a33c508
24 changed files with 93 additions and 65 deletions

View File

@ -82,11 +82,11 @@ public:
return false; 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; 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; return false;
} }
@ -320,7 +320,7 @@ void CSpellWindow::computeSpellsPerArea()
for(const CSpell * spell : mySpells) for(const CSpell * spell : mySpells)
{ {
if(spell->isCombat() ^ !battleSpellsOnly if(spell->isCombat() ^ !battleSpellsOnly
&& ((selectedTab == 4) || spell->school.at((ESpellSchool)selectedTab)) && ((selectedTab == 4) || spell->school.at(SpellSchool(selectedTab)))
) )
{ {
spellsCurSite.push_back(spell); spellsCurSite.push_back(spell);

View File

@ -1185,7 +1185,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : 0, "subtype" : "spellSchool.air",
"val" : 50, "val" : 50,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -1198,7 +1198,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : 3, "subtype" : "spellSchool.earth",
"val" : 50, "val" : 50,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -1211,7 +1211,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : 1, "subtype" : "spellSchool.fire",
"val" : 50, "val" : 50,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -1224,7 +1224,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : 2, "subtype" : "spellSchool.water",
"val" : 50, "val" : 50,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }

View File

@ -13,7 +13,7 @@
"bonuses": [ "bonuses": [
{ {
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"subtype" : 0, "subtype" : "spellSchool.any",
"val" : 3, "val" : 3,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -29,7 +29,7 @@
"bonuses": [ "bonuses": [
{ {
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"subtype" : 2, "subtype" : "spellSchool.fire",
"val" : 3, "val" : 3,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -41,7 +41,7 @@
"bonuses": [ "bonuses": [
{ {
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"subtype" : 8, "subtype" : "spellSchool.earth",
"val" : 3, "val" : 3,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -53,7 +53,7 @@
"bonuses": [ "bonuses": [
{ {
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"subtype" : 1, "subtype" : "spellSchool.air",
"val" : 3, "val" : 3,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -65,7 +65,7 @@
"bonuses": [ "bonuses": [
{ {
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"subtype" : 4, "subtype" : "spellSchool.water",
"val" : 3, "val" : 3,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }

View File

@ -10,7 +10,7 @@
"magicResistance" : "magicResistance" :
{ {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1, "subtype" : "spellSchool.any",
"val" : 85 "val" : 85
}, },
"nonliving" : "nonliving" :
@ -41,7 +41,7 @@
"magicResistance" : "magicResistance" :
{ {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1, "subtype" : "spellSchool.any",
"val" : 95 "val" : 95
}, },
"nonliving" : "nonliving" :

View File

@ -105,7 +105,7 @@
"magicResistance" : "magicResistance" :
{ {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1, "subtype" : "spellSchool.any",
"val" : 50 "val" : 50
}, },
"nonliving" : "nonliving" :
@ -137,7 +137,7 @@
"magicResistance" : "magicResistance" :
{ {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1, "subtype" : "spellSchool.any",
"val" : 75 "val" : 75
}, },
"nonliving" : "nonliving" :

View File

@ -215,6 +215,7 @@
"spellDamage" : "spellDamage" :
{ {
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"val" : 100, "val" : 100,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
}, },

View File

@ -186,6 +186,7 @@
"sorcery" : { "sorcery" : {
"targetSourceType" : "SECONDARY_SKILL", "targetSourceType" : "SECONDARY_SKILL",
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"updater" : "TIMES_HERO_LEVEL", "updater" : "TIMES_HERO_LEVEL",
"val" : 5, "val" : 5,
"valueType" : "PERCENT_TO_TARGET_TYPE" "valueType" : "PERCENT_TO_TARGET_TYPE"

View File

@ -262,6 +262,7 @@
"sorcery" : { "sorcery" : {
"targetSourceType" : "SECONDARY_SKILL", "targetSourceType" : "SECONDARY_SKILL",
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"updater" : "TIMES_HERO_LEVEL", "updater" : "TIMES_HERO_LEVEL",
"val" : 5, "val" : 5,
"valueType" : "PERCENT_TO_TARGET_TYPE" "valueType" : "PERCENT_TO_TARGET_TYPE"

View File

@ -261,6 +261,7 @@
"sorcery" : { "sorcery" : {
"targetSourceType" : "SECONDARY_SKILL", "targetSourceType" : "SECONDARY_SKILL",
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"updater" : "TIMES_HERO_LEVEL", "updater" : "TIMES_HERO_LEVEL",
"val" : 5, "val" : 5,
"valueType" : "PERCENT_TO_TARGET_TYPE" "valueType" : "PERCENT_TO_TARGET_TYPE"

View File

@ -192,6 +192,7 @@
"sorcery" : { "sorcery" : {
"targetSourceType" : "SECONDARY_SKILL", "targetSourceType" : "SECONDARY_SKILL",
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"updater" : "TIMES_HERO_LEVEL", "updater" : "TIMES_HERO_LEVEL",
"val" : 5, "val" : 5,
"valueType" : "PERCENT_TO_TARGET_TYPE" "valueType" : "PERCENT_TO_TARGET_TYPE"

View File

@ -135,6 +135,7 @@
"sorcery" : { "sorcery" : {
"targetSourceType" : "SECONDARY_SKILL", "targetSourceType" : "SECONDARY_SKILL",
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"updater" : "TIMES_HERO_LEVEL", "updater" : "TIMES_HERO_LEVEL",
"val" : 5, "val" : 5,
"valueType" : "PERCENT_TO_TARGET_TYPE" "valueType" : "PERCENT_TO_TARGET_TYPE"
@ -239,6 +240,7 @@
"sorcery" : { "sorcery" : {
"targetSourceType" : "SECONDARY_SKILL", "targetSourceType" : "SECONDARY_SKILL",
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"updater" : "TIMES_HERO_LEVEL", "updater" : "TIMES_HERO_LEVEL",
"val" : 5, "val" : 5,
"valueType" : "PERCENT_TO_TARGET_TYPE" "valueType" : "PERCENT_TO_TARGET_TYPE"

View File

@ -406,7 +406,7 @@
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
"subtype" : 2, "subtype" : "spellSchool.fire",
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -434,7 +434,7 @@
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
"subtype" : 1, "subtype" : "spellSchool.air",
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -462,7 +462,7 @@
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
"subtype" : 4, "subtype" : "spellSchool.water",
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -490,7 +490,7 @@
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
"subtype" : 8, "subtype" : "spellSchool.earth",
"type" : "MAGIC_SCHOOL_SKILL", "type" : "MAGIC_SCHOOL_SKILL",
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
@ -737,6 +737,7 @@
"effects" : { "effects" : {
"main" : { "main" : {
"type" : "SPELL_DAMAGE", "type" : "SPELL_DAMAGE",
"subtype" : "spellSchool.any",
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
} }
} }

View File

@ -104,7 +104,7 @@
"effects" : { "effects" : {
"spellDamageReduction" : { "spellDamageReduction" : {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : 0, "subtype" : "spellSchool.air",
"duration" : "N_TURNS", "duration" : "N_TURNS",
"val" : 30 "val" : 30
} }
@ -147,7 +147,7 @@
"effects" : { "effects" : {
"spellDamageReduction" : { "spellDamageReduction" : {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : 1, "subtype" : "spellSchool.fire",
"duration" : "N_TURNS", "duration" : "N_TURNS",
"val" : 30 "val" : 30
} }
@ -190,7 +190,7 @@
"effects" : { "effects" : {
"spellDamageReduction" : { "spellDamageReduction" : {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : 2, "subtype" : "spellSchool.water",
"duration" : "N_TURNS", "duration" : "N_TURNS",
"val" : 30 "val" : 30
} }
@ -233,7 +233,7 @@
"effects" : { "effects" : {
"spellDamageReduction" : { "spellDamageReduction" : {
"type" : "SPELL_DAMAGE_REDUCTION", "type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : 3, "subtype" : "spellSchool.earth",
"duration" : "N_TURNS", "duration" : "N_TURNS",
"val" : 30 "val" : 30
} }

View File

@ -1059,7 +1059,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
b.type = BonusType::FEAR; break; b.type = BonusType::FEAR; break;
case 'g': case 'g':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = -1; //all magic schools b.subtype = SpellSchool(ESpellSchool::ANY);
break; break;
case 'P': case 'P':
b.type = BonusType::CASTS; break; b.type = BonusType::CASTS; break;
@ -1179,7 +1179,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'O': case 'O':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = 1; //Fire school b.subtype = SpellSchool(ESpellSchool::FIRE);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'f': case 'f':
@ -1192,7 +1192,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'W': case 'W':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = 2; //Water school b.subtype = SpellSchool(ESpellSchool::WATER);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'w': case 'w':
@ -1201,7 +1201,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'E': case 'E':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = 3; //Earth school b.subtype = SpellSchool(ESpellSchool::EARTH);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'e': case 'e':
@ -1210,7 +1210,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'A': case 'A':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = 0; //Air school b.subtype = SpellSchool(ESpellSchool::AIR);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'a': case 'a':
@ -1219,7 +1219,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'D': case 'D':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = -1; //all b.subtype = SpellSchool(ESpellSchool::ANY);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case '0': case '0':

View File

@ -7,6 +7,7 @@
* Full text of license available in license.txt file, in main folder * Full text of license available in license.txt file, in main folder
* *
*/ */
#include "GameConstants.h"
#include "StdInc.h" #include "StdInc.h"
#include "CModHandler.h" #include "CModHandler.h"
#include "mapObjects/CObjectClassesHandler.h" #include "mapObjects/CObjectClassesHandler.h"
@ -745,6 +746,12 @@ void CModInfo::setEnabled(bool on)
CModHandler::CModHandler() : content(std::make_shared<CContentHandler>()) CModHandler::CModHandler() : content(std::make_shared<CContentHandler>())
{ {
//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) for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i)
{ {
identifiers.registerObject(CModHandler::scopeBuiltin(), "resource", GameConstants::RESOURCE_NAMES[i], i); identifiers.registerObject(CModHandler::scopeBuiltin(), "resource", GameConstants::RESOURCE_NAMES[i], i);

View File

@ -50,6 +50,7 @@ namespace GameConstants
constexpr int CREATURES_PER_TOWN = 7; //without upgrades constexpr int CREATURES_PER_TOWN = 7; //without upgrades
constexpr int SPELL_LEVELS = 5; constexpr int SPELL_LEVELS = 5;
constexpr int SPELL_SCHOOL_LEVELS = 4; constexpr int SPELL_SCHOOL_LEVELS = 4;
constexpr int DEFAULT_SCHOOLS = 4;
constexpr int CRE_LEVELS = 10; // number of creature experience levels constexpr int CRE_LEVELS = 10; // number of creature experience levels
constexpr int HERO_GOLD_COST = 2500; constexpr int HERO_GOLD_COST = 2500;
@ -1296,14 +1297,17 @@ class Obstacle : public BaseForID<Obstacle, si32>
DLL_LINKAGE static Obstacle fromString(const std::string & identifier); DLL_LINKAGE static Obstacle fromString(const std::string & identifier);
}; };
enum class ESpellSchool: ui8 enum class ESpellSchool: int8_t
{ {
ANY = -1,
AIR = 0, AIR = 0,
FIRE = 1, FIRE = 1,
WATER = 2, WATER = 2,
EARTH = 3 EARTH = 3,
}; };
using SpellSchool = Identifier<ESpellSchool>;
enum class EMetaclass: ui8 enum class EMetaclass: ui8
{ {
INVALID = 0, INVALID = 0,

View File

@ -74,7 +74,10 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
valueType = BonusValueType::PERCENT_TO_BASE; valueType = BonusValueType::PERCENT_TO_BASE;
} }
else if(deprecatedSubtype == SecondarySkill::SORCERY || deprecatedSubtypeStr == "skill.sorcery") else if(deprecatedSubtype == SecondarySkill::SORCERY || deprecatedSubtypeStr == "skill.sorcery")
{
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = SpellSchool(ESpellSchool::ANY);
}
else if(deprecatedSubtype == SecondarySkill::SCHOLAR || deprecatedSubtypeStr == "skill.scholar") else if(deprecatedSubtype == SecondarySkill::SCHOLAR || deprecatedSubtypeStr == "skill.scholar")
type = BonusType::LEARN_MEETING_SPELL_LIMIT; type = BonusType::LEARN_MEETING_SPELL_LIMIT;
else if(deprecatedSubtype == SecondarySkill::ARCHERY|| deprecatedSubtypeStr == "skill.archery") 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") else if(deprecatedSubtype == SecondarySkill::AIR_MAGIC || deprecatedSubtypeStr == "skill.airMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = 4; subtype = SpellSchool(ESpellSchool::AIR);
} }
else if(deprecatedSubtype == SecondarySkill::WATER_MAGIC || deprecatedSubtypeStr == "skill.waterMagic") else if(deprecatedSubtype == SecondarySkill::WATER_MAGIC || deprecatedSubtypeStr == "skill.waterMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = 1; subtype = SpellSchool(ESpellSchool::WATER);
} }
else if(deprecatedSubtype == SecondarySkill::FIRE_MAGIC || deprecatedSubtypeStr == "skill.fireMagic") else if(deprecatedSubtype == SecondarySkill::FIRE_MAGIC || deprecatedSubtypeStr == "skill.fireMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = 2; subtype = SpellSchool(ESpellSchool::FIRE);
} }
else if(deprecatedSubtype == SecondarySkill::EARTH_MAGIC || deprecatedSubtypeStr == "skill.earthMagic") else if(deprecatedSubtype == SecondarySkill::EARTH_MAGIC || deprecatedSubtypeStr == "skill.earthMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = 8; subtype = SpellSchool(ESpellSchool::EARTH);
} }
else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery") 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") else if (deprecatedTypeStr == "DIRECT_DAMAGE_IMMUNITY")
{ {
type = BonusType::SPELL_DAMAGE_REDUCTION; type = BonusType::SPELL_DAMAGE_REDUCTION;
subtype = SpellSchool(ESpellSchool::ANY);
val = 100; val = 100;
} }
else if (deprecatedTypeStr == "AIR_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "AIR_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = 0; subtype = SpellSchool(ESpellSchool::AIR);
} }
else if (deprecatedTypeStr == "FIRE_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "FIRE_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = 1; subtype = SpellSchool(ESpellSchool::FIRE);
} }
else if (deprecatedTypeStr == "WATER_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "WATER_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = 2; subtype = SpellSchool(ESpellSchool::WATER);
} }
else if (deprecatedTypeStr == "EARTH_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "EARTH_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = 3; subtype = SpellSchool(ESpellSchool::EARTH);
} }
else if (deprecatedTypeStr == "AIR_SPELLS") else if (deprecatedTypeStr == "AIR_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = 0; subtype = SpellSchool(ESpellSchool::AIR);
} }
else if (deprecatedTypeStr == "FIRE_SPELLS") else if (deprecatedTypeStr == "FIRE_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = 1; subtype = SpellSchool(ESpellSchool::FIRE);
} }
else if (deprecatedTypeStr == "WATER_SPELLS") else if (deprecatedTypeStr == "WATER_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = 2; subtype = SpellSchool(ESpellSchool::WATER);
} }
else if (deprecatedTypeStr == "EARTH_SPELLS") else if (deprecatedTypeStr == "EARTH_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = 3; subtype = SpellSchool(ESpellSchool::EARTH);
} }
else else
isConverted = false; isConverted = false;

View File

@ -589,7 +589,7 @@ int32_t CGHeroInstance::getSpellSchoolLevel(const spells::Spell * spell, int32_t
spell->forEachSchool([&, this](const spells::SchoolInfo & cnf, bool & stop) spell->forEachSchool([&, this](const spells::SchoolInfo & cnf, bool & stop)
{ {
int32_t thisSchool = valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, 1 << (static_cast<ui8>(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) if(thisSchool > skill)
{ {
skill = thisSchool; 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, valOfBonuses(BonusType::SPELL, spell->getIndex())); //given by artifact or other effect
vstd::amax(skill, 0); //in case we don't know any school 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 //applying sorcery secondary skill
if(spell->isMagical()) if(spell->isMagical())
base = static_cast<int64_t>(base * (valOfBonuses(BonusType::SPELL_DAMAGE)) / 100.0); base = static_cast<int64_t>(base * (valOfBonuses(BonusType::SPELL_DAMAGE, SpellSchool(ESpellSchool::ANY))) / 100.0);
base = static_cast<int64_t>(base * (100 + valOfBonuses(BonusType::SPECIFIC_SPELL_DAMAGE, spell->getIndex())) / 100.0); base = static_cast<int64_t>(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) 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<int64_t>(base * (100 + maxSchoolBonus) / 100.0); base = static_cast<int64_t>(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) 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; schoolBonus = stop = true;
} }

View File

@ -343,7 +343,7 @@ void TreasurePlacer::addAllPossibleObjects()
std::vector <CSpell *> spells; std::vector <CSpell *> spells;
for(auto spell : VLC->spellh->objects) for(auto spell : VLC->spellh->objects)
{ {
if(map.isAllowedSpell(spell->id) && spell->school[static_cast<ESpellSchool>(i)]) if(map.isAllowedSpell(spell->id) && spell->school[SpellSchool(i)])
spells.push_back(spell); spells.push_back(spell);
} }

View File

@ -35,7 +35,7 @@ int32_t AbilityCaster::getSpellSchoolLevel(const Spell * spell, int32_t * outSel
if(spell->getLevel() > 0) 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); vstd::amax(skill, 0);

View File

@ -38,7 +38,7 @@ namespace SpellConfig
{ {
static const std::string LEVEL_NAMES[] = {"none", "basic", "advanced", "expert"}; static const std::string LEVEL_NAMES[] = {"none", "basic", "advanced", "expert"};
static const spells::SchoolInfo SCHOOL[4] = const spells::SchoolInfo SCHOOL[4] =
{ {
{ {
ESpellSchool::AIR, ESpellSchool::AIR,
@ -63,7 +63,7 @@ static const spells::SchoolInfo SCHOOL[4] =
}; };
//order as described in http://bugs.vcmi.eu/view.php?id=91 //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::AIR, //=0
ESpellSchool::FIRE, //=1 ESpellSchool::FIRE, //=1
@ -150,9 +150,9 @@ spells::AimType CSpell::getTargetType() const
void CSpell::forEachSchool(const std::function<void(const spells::SchoolInfo &, bool &)>& cb) const void CSpell::forEachSchool(const std::function<void(const spells::SchoolInfo &, bool &)>& cb) const
{ {
bool stop = false; bool stop = false;
for(ESpellSchool iter : SpellConfig::SCHOOL_ORDER) for(auto iter : SpellConfig::SCHOOL_ORDER)
{ {
const spells::SchoolInfo & cnf = SpellConfig::SCHOOL[static_cast<ui8>(iter)]; const spells::SchoolInfo & cnf = SpellConfig::SCHOOL[iter];
if(school.at(cnf.id)) if(school.at(cnf.id))
{ {
cb(cnf, stop); 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) //applying protections - when spell has more then one elements, only one protection should be applied (I think)
forEachSchool([&](const spells::SchoolInfo & cnf, bool & stop) forEachSchool([&](const spells::SchoolInfo & cnf, bool & stop)
{ {
if(bearer->hasBonusOfType(BonusType::SPELL_DAMAGE_REDUCTION, static_cast<ui8>(cnf.id))) if(bearer->hasBonusOfType(BonusType::SPELL_DAMAGE_REDUCTION, cnf.id))
{ {
ret *= 100 - bearer->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, static_cast<ui8>(cnf.id)); ret *= 100 - bearer->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, cnf.id);
ret /= 100; ret /= 100;
stop = true; //only bonus from one school is used 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 //general spell dmg reduction, works only on magical effects
if(bearer->hasBonus(selector) && isMagical()) if(bearer->hasBonus(selector) && isMagical())

View File

@ -43,13 +43,18 @@ class IBattleCast;
struct SchoolInfo struct SchoolInfo
{ {
ESpellSchool id; //backlink SpellSchool id; //backlink
BonusType immunityBonus; BonusType immunityBonus;
std::string jsonName; std::string jsonName;
}; };
} }
namespace SpellConfig
{
extern const spells::SchoolInfo SCHOOL[4];
}
enum class VerticalPosition : ui8{TOP, CENTER, BOTTOM}; enum class VerticalPosition : ui8{TOP, CENTER, BOTTOM};
class DLL_LINKAGE CSpell : public spells::Spell class DLL_LINKAGE CSpell : public spells::Spell
@ -185,7 +190,7 @@ public:
si32 level; si32 level;
std::map<ESpellSchool, bool> school; std::map<SpellSchool, bool> school;
si32 power; //spell's power si32 power; //spell's power

View File

@ -85,11 +85,11 @@ bool Damage::isReceptive(const Mechanics * m, const battle::Unit * unit) const
if(!UnitEffect::isReceptive(m, unit)) if(!UnitEffect::isReceptive(m, unit))
return false; 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 //elemental immunity for damage
m->getSpell()->forEachSchool([&](const SchoolInfo & cnf, bool & stop) m->getSpell()->forEachSchool([&](const SchoolInfo & cnf, bool & stop)
{ {
isImmune |= (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, static_cast<ui8>(cnf.id)) >= 100); //100% reduction is immunity isImmune |= (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, cnf.id) >= 100); //100% reduction is immunity
}); });
return !isImmune; return !isImmune;

View File

@ -56,7 +56,7 @@ TEST_F(AbilityCasterTest, MagicAbilityAffectedByGenericBonus)
{ {
EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1)); EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1));
casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, 0)); casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, SpellSchool(ESpellSchool::ANY)));
EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1)); EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1));
EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0)); EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0));
@ -70,7 +70,7 @@ TEST_F(AbilityCasterTest, MagicAbilityIngoresSchoolBonus)
{ {
EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1)); EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1));
casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, 1)); casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, 0, SpellSchool(ESpellSchool::AIR)));
EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1)); EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1));
EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0)); EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0));