mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
More general spell school handling
This commit is contained in:
parent
d7800b834e
commit
22178151aa
@ -337,15 +337,15 @@ ui32 CSpell::calculateBonus(ui32 baseDamage, const CGHeroInstance* caster, const
|
||||
{
|
||||
ret *= (100.0 + caster->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::SORCERY)) / 100.0;
|
||||
ret *= (100.0 + caster->valOfBonuses(Bonus::SPELL_DAMAGE) + caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, id.toEnum())) / 100.0;
|
||||
|
||||
if(air)
|
||||
ret *= (100.0 + caster->valOfBonuses(Bonus::AIR_SPELL_DMG_PREMY)) / 100.0;
|
||||
else if(fire) //only one type of bonus for Magic Arrow
|
||||
ret *= (100.0 + caster->valOfBonuses(Bonus::FIRE_SPELL_DMG_PREMY)) / 100.0;
|
||||
else if(water)
|
||||
ret *= (100.0 + caster->valOfBonuses(Bonus::WATER_SPELL_DMG_PREMY)) / 100.0;
|
||||
else if(earth)
|
||||
ret *= (100.0 + caster->valOfBonuses(Bonus::EARTH_SPELL_DMG_PREMY)) / 100.0;
|
||||
|
||||
for(const SpellSchoolInfo & cnf : spellSchoolConfig)
|
||||
{
|
||||
if(school.at(cnf.id))
|
||||
{
|
||||
ret *= (100.0 + caster->valOfBonuses(cnf.damagePremyBonus)) / 100.0;
|
||||
break; //only bonus from one school is used
|
||||
}
|
||||
}
|
||||
|
||||
if (affectedCreature && affectedCreature->getCreature()->level) //Hero specials like Solmyr, Deemer
|
||||
ret *= (100. + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, id.toEnum()) * caster->level) / affectedCreature->getCreature()->level)) / 100.0;
|
||||
@ -368,26 +368,17 @@ ui32 CSpell::calculateDamage(const CGHeroInstance * caster, const CStack * affec
|
||||
if(nullptr != affectedCreature)
|
||||
{
|
||||
//applying protections - when spell has more then one elements, only one protection should be applied (I think)
|
||||
if(air && affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, 0)) //air spell & protection from air
|
||||
|
||||
for(const SpellSchoolInfo & cnf : spellSchoolConfig)
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, 0);
|
||||
ret /= 100;
|
||||
}
|
||||
else if(fire && affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, 1)) //fire spell & protection from fire
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, 1);
|
||||
ret /= 100;
|
||||
}
|
||||
else if(water && affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, 2)) //water spell & protection from water
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, 2);
|
||||
ret /= 100;
|
||||
}
|
||||
else if (earth && affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, 3)) //earth spell & protection from earth
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, 3);
|
||||
ret /= 100;
|
||||
}
|
||||
if(school.at(cnf.id) && affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, (ui8)cnf.id))
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, (ui8)cnf.id);
|
||||
ret /= 100;
|
||||
break; //only bonus from one school is used
|
||||
}
|
||||
}
|
||||
|
||||
//general spell dmg reduction
|
||||
//FIXME?
|
||||
if(air && affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, -1))
|
||||
@ -727,27 +718,14 @@ ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj)
|
||||
};
|
||||
|
||||
//6. Check elemental immunities
|
||||
if(fire)
|
||||
|
||||
for(const SpellSchoolInfo & cnf : spellSchoolConfig)
|
||||
{
|
||||
if(battleTestElementalImmunity(Bonus::FIRE_IMMUNITY))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
if(water)
|
||||
{
|
||||
if(battleTestElementalImmunity(Bonus::WATER_IMMUNITY))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
if(school.at(cnf.id))
|
||||
if(battleTestElementalImmunity(cnf.immunityBonus))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
|
||||
if(earth)
|
||||
{
|
||||
if(battleTestElementalImmunity(Bonus::EARTH_IMMUNITY))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
if(air)
|
||||
{
|
||||
if(battleTestElementalImmunity(Bonus::AIR_IMMUNITY))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
|
||||
TBonusListPtr levelImmunities = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
|
||||
|
||||
@ -791,6 +769,17 @@ void CSpell::setIsRising(const bool val)
|
||||
}
|
||||
}
|
||||
|
||||
void CSpell::setup()
|
||||
{
|
||||
setupMechanics();
|
||||
|
||||
school[ESpellSchool::AIR] = air;
|
||||
school[ESpellSchool::FIRE] = fire;
|
||||
school[ESpellSchool::WATER] = water;
|
||||
school[ESpellSchool::EARTH] = earth;
|
||||
}
|
||||
|
||||
|
||||
void CSpell::setupMechanics()
|
||||
{
|
||||
if(nullptr != mechanics)
|
||||
@ -1164,7 +1153,7 @@ void CSpellHandler::afterLoadFinalization()
|
||||
for(auto & level: spell->levels)
|
||||
for(auto & bonus: level.effects)
|
||||
bonus.sid = spell->id;
|
||||
spell->setupMechanics();
|
||||
spell->setup();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,44 @@ class CSpell;
|
||||
class CGHeroInstance;
|
||||
class CStack;
|
||||
|
||||
struct SpellSchoolInfo
|
||||
{
|
||||
ESpellSchool id; //backlink
|
||||
Bonus::BonusType damagePremyBonus;
|
||||
Bonus::BonusType immunityBonus;
|
||||
std::string jsonName;
|
||||
};
|
||||
|
||||
static SpellSchoolInfo spellSchoolConfig[4] =
|
||||
{
|
||||
{
|
||||
ESpellSchool::AIR,
|
||||
Bonus::AIR_SPELL_DMG_PREMY,
|
||||
Bonus::AIR_IMMUNITY,
|
||||
"air"
|
||||
},
|
||||
{
|
||||
ESpellSchool::FIRE,
|
||||
Bonus::FIRE_SPELL_DMG_PREMY,
|
||||
Bonus::FIRE_IMMUNITY,
|
||||
"fire"
|
||||
},
|
||||
{
|
||||
ESpellSchool::WATER,
|
||||
Bonus::WATER_SPELL_DMG_PREMY,
|
||||
Bonus::WATER_IMMUNITY,
|
||||
"water"
|
||||
},
|
||||
{
|
||||
ESpellSchool::EARTH,
|
||||
Bonus::EARTH_SPELL_DMG_PREMY,
|
||||
Bonus::EARTH_IMMUNITY,
|
||||
"earth"
|
||||
}
|
||||
};
|
||||
|
||||
class CPackForClient;
|
||||
|
||||
class DLL_LINKAGE CSpellMechanics
|
||||
{
|
||||
public:
|
||||
@ -82,10 +120,13 @@ public:
|
||||
std::string name;
|
||||
|
||||
si32 level;
|
||||
bool earth;
|
||||
bool water;
|
||||
bool fire;
|
||||
bool air;
|
||||
bool earth; //deprecated
|
||||
bool water; //deprecated
|
||||
bool fire; //deprecated
|
||||
bool air; //deprecated
|
||||
|
||||
std::map<ESpellSchool, bool> school; //todo: use this instead of separate boolean fields
|
||||
|
||||
si32 power; //spell's power
|
||||
|
||||
std::map<TFaction, si32> probabilities; //% chance to gain for castles
|
||||
@ -178,7 +219,7 @@ public:
|
||||
h & levels;
|
||||
|
||||
if(!h.saving)
|
||||
setupMechanics();
|
||||
setup();
|
||||
}
|
||||
friend class CSpellHandler;
|
||||
friend class Graphics;
|
||||
@ -188,6 +229,7 @@ private:
|
||||
void setIsRising(const bool val);
|
||||
|
||||
//call this after load or deserialization. cant be done in constructor.
|
||||
void setup();
|
||||
void setupMechanics();
|
||||
private:
|
||||
si32 defaultProbability;
|
||||
|
@ -890,6 +890,14 @@ public:
|
||||
ESpellID num;
|
||||
};
|
||||
|
||||
enum class ESpellSchool: ui8
|
||||
{
|
||||
AIR = 0,
|
||||
FIRE = 1,
|
||||
WATER = 2,
|
||||
EARTH = 3
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(SpellID, SpellID::ESpellID)
|
||||
|
||||
// Typedef declarations
|
||||
|
Loading…
x
Reference in New Issue
Block a user