1
0
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:
AlexVinS 2014-11-12 05:50:51 +03:00
parent 24efb9b413
commit a49da360d2
6 changed files with 37 additions and 22 deletions

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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));
}); });

View File

@ -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;

View File

@ -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
}; };
} }