mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Use ESpellCastProblem inside SpellHandler
This commit is contained in:
parent
24efb9b413
commit
a49da360d2
@ -1621,12 +1621,12 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleIsImmune(const C
|
|||||||
|
|
||||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleStackIsImmune(const CGHeroInstance * caster, const CSpell * spell, ECastingMode::ECastingMode mode, const CStack * subject) const
|
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleStackIsImmune(const CGHeroInstance * caster, const CSpell * spell, ECastingMode::ECastingMode mode, const CStack * subject) const
|
||||||
{
|
{
|
||||||
if (spell->isPositive() && subject->hasBonusOfType(Bonus::RECEPTIVE)) //accept all positive spells
|
const auto immuneResult = spell->isImmuneBy(subject);
|
||||||
return ESpellCastProblem::OK;
|
|
||||||
|
|
||||||
if (spell->isImmuneBy(subject)) //TODO: move all logic to spellhandler
|
if (ESpellCastProblem::NOT_DECIDED != immuneResult)
|
||||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
return immuneResult;
|
||||||
|
|
||||||
|
//TODO: move all logic to spellhandler
|
||||||
switch (spell->id) //TODO: more general logic for new spells?
|
switch (spell->id) //TODO: more general logic for new spells?
|
||||||
{
|
{
|
||||||
case SpellID::CLONE:
|
case SpellID::CLONE:
|
||||||
|
@ -99,6 +99,14 @@ void CIdentifierStorage::requestIdentifier(std::string scope, std::string type,
|
|||||||
requestIdentifier(ObjectCallback(scope, pair.first, type, pair.second, callback, false));
|
requestIdentifier(ObjectCallback(scope, pair.first, type, pair.second, callback, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIdentifierStorage::requestIdentifier(std::string scope, std::string fullName, const std::function<void(si32)>& callback)
|
||||||
|
{
|
||||||
|
auto scopeAndFullName = splitString(fullName, ':');
|
||||||
|
auto typeAndName = splitString(scopeAndFullName.second, '.');
|
||||||
|
|
||||||
|
requestIdentifier(ObjectCallback(scope, scopeAndFullName.first, typeAndName.first, typeAndName.second, callback, false));
|
||||||
|
}
|
||||||
|
|
||||||
void CIdentifierStorage::requestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback)
|
void CIdentifierStorage::requestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback)
|
||||||
{
|
{
|
||||||
auto pair = splitString(name.String(), ':'); // remoteScope:name
|
auto pair = splitString(name.String(), ':'); // remoteScope:name
|
||||||
|
@ -72,6 +72,8 @@ public:
|
|||||||
/// request identifier for specific object name.
|
/// request identifier for specific object name.
|
||||||
/// Function callback will be called during ID resolution phase of loading
|
/// Function callback will be called during ID resolution phase of loading
|
||||||
void requestIdentifier(std::string scope, std::string type, std::string name, const std::function<void(si32)> & callback);
|
void requestIdentifier(std::string scope, std::string type, std::string name, const std::function<void(si32)> & callback);
|
||||||
|
///fullName = [remoteScope:]type.name
|
||||||
|
void requestIdentifier(std::string scope, std::string fullName, const std::function<void(si32)> & callback);
|
||||||
void requestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback);
|
void requestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback);
|
||||||
void requestIdentifier(const JsonNode & name, const std::function<void(si32)> & callback);
|
void requestIdentifier(const JsonNode & name, const std::function<void(si32)> & callback);
|
||||||
|
|
||||||
|
@ -408,33 +408,37 @@ void CSpell::getEffects(std::vector<Bonus>& lst, const int level) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSpell::isImmuneBy(const IBonusBearer* obj) const
|
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj) const
|
||||||
{
|
{
|
||||||
|
//0. check receptivity
|
||||||
|
if (isPositive() && obj->hasBonusOfType(Bonus::RECEPTIVE)) //accept all positive spells
|
||||||
|
return ESpellCastProblem::OK;
|
||||||
|
|
||||||
//todo: use new bonus API
|
//todo: use new bonus API
|
||||||
//1. Check absolute limiters
|
//1. Check absolute limiters
|
||||||
for(auto b : absoluteLimiters)
|
for(auto b : absoluteLimiters)
|
||||||
{
|
{
|
||||||
if (!obj->hasBonusOfType(b))
|
if (!obj->hasBonusOfType(b))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//2. Check absolute immunities
|
//2. Check absolute immunities
|
||||||
for(auto b : absoluteImmunities)
|
for(auto b : absoluteImmunities)
|
||||||
{
|
{
|
||||||
if (obj->hasBonusOfType(b))
|
if (obj->hasBonusOfType(b))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//3. Check negation
|
//3. Check negation
|
||||||
//FIXME: Orb of vulnerability mechanics is not such trivial
|
//FIXME: Orb of vulnerability mechanics is not such trivial
|
||||||
if(obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES)) //Orb of vulnerability
|
if(obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES)) //Orb of vulnerability
|
||||||
return false;
|
return ESpellCastProblem::NOT_DECIDED;
|
||||||
|
|
||||||
//4. Check negatable limit
|
//4. Check negatable limit
|
||||||
for(auto b : limiters)
|
for(auto b : limiters)
|
||||||
{
|
{
|
||||||
if (!obj->hasBonusOfType(b))
|
if (!obj->hasBonusOfType(b))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -442,42 +446,42 @@ bool CSpell::isImmuneBy(const IBonusBearer* obj) const
|
|||||||
for(auto b : immunities)
|
for(auto b : immunities)
|
||||||
{
|
{
|
||||||
if (obj->hasBonusOfType(b))
|
if (obj->hasBonusOfType(b))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto battleTestElementalImmunity = [&,this](Bonus::BonusType element) -> bool
|
auto battleTestElementalImmunity = [&,this](Bonus::BonusType element) -> bool
|
||||||
{
|
{
|
||||||
if(obj->hasBonusOfType(element, 0)) //always resist if immune to all spells altogether
|
if(obj->hasBonusOfType(element, 0)) //always resist if immune to all spells altogether
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
else if(!isPositive()) //negative or indifferent
|
else if(!isPositive()) //negative or indifferent
|
||||||
{
|
{
|
||||||
if((isDamageSpell() && obj->hasBonusOfType(element, 2)) || obj->hasBonusOfType(element, 1))
|
if((isDamageSpell() && obj->hasBonusOfType(element, 2)) || obj->hasBonusOfType(element, 1))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
return false;
|
return ESpellCastProblem::NOT_DECIDED;
|
||||||
};
|
};
|
||||||
|
|
||||||
//6. Check elemental immunities
|
//6. Check elemental immunities
|
||||||
if(fire)
|
if(fire)
|
||||||
{
|
{
|
||||||
if(battleTestElementalImmunity(Bonus::FIRE_IMMUNITY))
|
if(battleTestElementalImmunity(Bonus::FIRE_IMMUNITY))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
if(water)
|
if(water)
|
||||||
{
|
{
|
||||||
if(battleTestElementalImmunity(Bonus::WATER_IMMUNITY))
|
if(battleTestElementalImmunity(Bonus::WATER_IMMUNITY))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(earth)
|
if(earth)
|
||||||
{
|
{
|
||||||
if(battleTestElementalImmunity(Bonus::EARTH_IMMUNITY))
|
if(battleTestElementalImmunity(Bonus::EARTH_IMMUNITY))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
if(air)
|
if(air)
|
||||||
{
|
{
|
||||||
if(battleTestElementalImmunity(Bonus::AIR_IMMUNITY))
|
if(battleTestElementalImmunity(Bonus::AIR_IMMUNITY))
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TBonusListPtr levelImmunities = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
|
TBonusListPtr levelImmunities = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
|
||||||
@ -485,10 +489,10 @@ bool CSpell::isImmuneBy(const IBonusBearer* obj) const
|
|||||||
if(obj->hasBonusOfType(Bonus::SPELL_IMMUNITY, id)
|
if(obj->hasBonusOfType(Bonus::SPELL_IMMUNITY, id)
|
||||||
|| ( levelImmunities->size() > 0 && levelImmunities->totalValue() >= level && level))
|
|| ( levelImmunities->size() > 0 && levelImmunities->totalValue() >= level && level))
|
||||||
{
|
{
|
||||||
return true;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return ESpellCastProblem::NOT_DECIDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSpell::setIsOffensive(const bool val)
|
void CSpell::setIsOffensive(const bool val)
|
||||||
@ -719,7 +723,7 @@ CSpell * CSpellHandler::loadFromJson(const JsonNode& json)
|
|||||||
for(const auto & counteredSpell: json["counters"].Struct())
|
for(const auto & counteredSpell: json["counters"].Struct())
|
||||||
if (counteredSpell.second.Bool())
|
if (counteredSpell.second.Bool())
|
||||||
{
|
{
|
||||||
VLC->modh->identifiers.requestIdentifier(json.meta, "spell", counteredSpell.first, [=](si32 id)
|
VLC->modh->identifiers.requestIdentifier(json.meta, counteredSpell.first, [=](si32 id)
|
||||||
{
|
{
|
||||||
spell->counteredSpells.push_back(SpellID(id));
|
spell->counteredSpells.push_back(SpellID(id));
|
||||||
});
|
});
|
||||||
|
@ -108,7 +108,7 @@ public:
|
|||||||
bool hasEffects() const;
|
bool hasEffects() const;
|
||||||
void getEffects(std::vector<Bonus> &lst, const int level) const;
|
void getEffects(std::vector<Bonus> &lst, const int level) const;
|
||||||
|
|
||||||
bool isImmuneBy(const IBonusBearer *obj) const;
|
ESpellCastProblem::ESpellCastProblem isImmuneBy(const IBonusBearer *obj) const;
|
||||||
|
|
||||||
si32 getCost(const int skillLevel) const;
|
si32 getCost(const int skillLevel) const;
|
||||||
|
|
||||||
|
@ -395,6 +395,7 @@ namespace ESpellCastProblem
|
|||||||
SECOND_HEROS_SPELL_IMMUNITY, SPELL_LEVEL_LIMIT_EXCEEDED, NO_SPELLS_TO_DISPEL,
|
SECOND_HEROS_SPELL_IMMUNITY, SPELL_LEVEL_LIMIT_EXCEEDED, NO_SPELLS_TO_DISPEL,
|
||||||
NO_APPROPRIATE_TARGET, STACK_IMMUNE_TO_SPELL, WRONG_SPELL_TARGET, ONGOING_TACTIC_PHASE,
|
NO_APPROPRIATE_TARGET, STACK_IMMUNE_TO_SPELL, WRONG_SPELL_TARGET, ONGOING_TACTIC_PHASE,
|
||||||
MAGIC_IS_BLOCKED, //For Orb of Inhibition and similar - no casting at all
|
MAGIC_IS_BLOCKED, //For Orb of Inhibition and similar - no casting at all
|
||||||
|
NOT_DECIDED,
|
||||||
INVALID
|
INVALID
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user