1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

[refactor] spell handling

* more config options for spells
  + mind immunity handled by config
  + direct damage immunity handled by config
  + immunity icon configurable
- removed mind_spell flag 
* more use of new spell identifacation
This commit is contained in:
alexvins
2013-02-13 19:35:43 +00:00
parent 6d06710684
commit ceea466f54
18 changed files with 282 additions and 217 deletions

View File

@@ -81,7 +81,7 @@ namespace SRSLPraserHelpers
return xy.first >=0 && xy.first < 17 && xy.second >= 0 && xy.second < 11;
}
//helper fonction for std::set<ui16> CSpell::rangeInHexes(unsigned int centralHex, ui8 schoolLvl ) const
//helper function for std::set<ui16> CSpell::rangeInHexes(unsigned int centralHex, ui8 schoolLvl ) const
static std::set<ui16> getInRange(unsigned int center, int low, int high)
{
std::set<ui16> ret;
@@ -123,14 +123,10 @@ namespace SRSLPraserHelpers
}
using namespace SRSLPraserHelpers;
CSpellHandler::CSpellHandler()
{
}
CSpell::CSpell()
{
isDamage = false;
isMind = false;
isRising = false;
isOffensive = false;
}
@@ -235,23 +231,12 @@ std::vector<BattleHex> CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl,
return ret;
}
CSpell::ETargetType CSpell::getTargetType() const //TODO: parse these at game launch
CSpell::ETargetType CSpell::getTargetType() const
{
if(attributes.find("CREATURE_TARGET_1") != std::string::npos
|| attributes.find("CREATURE_TARGET_2") != std::string::npos)
return CREATURE_EXPERT_MASSIVE;
if(attributes.find("CREATURE_TARGET") != std::string::npos)
return CREATURE;
if(attributes.find("OBSTACLE_TARGET") != std::string::npos)
return OBSTACLE;
return NO_TARGET;
return targetType;
}
void CSpell::getEffects(std::vector<Bonus>& lst, const int level) const
{
if (level < 0 || level>3)
@@ -270,6 +255,7 @@ void CSpell::getEffects(std::vector<Bonus>& lst, const int level) const
bool CSpell::isImmuneBy(const IBonusBearer* obj) const
{
//todo: use new bonus API
BOOST_FOREACH(auto b, limiters)
{
if (!obj->hasBonusOfType(b))
@@ -282,24 +268,18 @@ bool CSpell::isImmuneBy(const IBonusBearer* obj) const
return true;
}
if (isMindSpell() && obj->hasBonusOfType(Bonus::MIND_IMMUNITY))
return true;
if (isDamageSpell() && obj->hasBonusOfType(Bonus::DIRECT_DAMAGE_IMMUNITY))
return true;
auto battleTestElementalImmunity = [&,this](Bonus::BonusType element) -> bool
{
if (!isPositive()) //negative or indifferent
{
if ((isDamageSpell() && obj->hasBonusOfType(element, 2)) || obj->hasBonusOfType(element, 1))
return true;
}
else if (isPositive()) //positive
if (isPositive())
{
if (obj->hasBonusOfType(element, 0)) //must be immune to all spells
return true;
}
else //negative or indifferent
{
if ((isDamageSpell() && obj->hasBonusOfType(element, 2)) || obj->hasBonusOfType(element, 1))
return true;
}
return false;
};
@@ -325,14 +305,14 @@ bool CSpell::isImmuneBy(const IBonusBearer* obj) const
return true;
}
TBonusListPtr immunities = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
TBonusListPtr levelImmunities = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
if(obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES))
{
immunities->remove_if([](const Bonus* b){ return b->source == Bonus::CREATURE_ABILITY; });
levelImmunities->remove_if([](const Bonus* b){ return b->source == Bonus::CREATURE_ABILITY; });
}
if(obj->hasBonusOfType(Bonus::SPELL_IMMUNITY, id)
|| ( immunities->size() > 0 && immunities->totalValue() >= level && level))
|| ( levelImmunities->size() > 0 && levelImmunities->totalValue() >= level && level))
{
return true;
}
@@ -340,6 +320,20 @@ bool CSpell::isImmuneBy(const IBonusBearer* obj) const
return false;
}
void CSpell::setAttributes(const std::string& newValue)
{
attributes = newValue;
if(attributes.find("CREATURE_TARGET_1") != std::string::npos
|| attributes.find("CREATURE_TARGET_2") != std::string::npos)
targetType = CREATURE_EXPERT_MASSIVE;
else if(attributes.find("CREATURE_TARGET") != std::string::npos)
targetType = CREATURE;
else if(attributes.find("OBSTACLE_TARGET") != std::string::npos)
targetType = OBSTACLE;
else
targetType = NO_TARGET;
}
bool DLL_LINKAGE isInScreenRange(const int3 &center, const int3 &pos)
{
@@ -350,10 +344,16 @@ bool DLL_LINKAGE isInScreenRange(const int3 &center, const int3 &pos)
return false;
}
CSpell * CSpellHandler::loadSpell(CLegacyConfigParser & parser)
CSpellHandler::CSpellHandler()
{
}
CSpell * CSpellHandler::loadSpell(CLegacyConfigParser & parser, const SpellID id)
{
CSpell * spell = new CSpell; //new currently being read spell
spell->id = id;
spell->name = parser.readString();
spell->abbName = parser.readString();
spell->level = parser.readNumber();
@@ -375,7 +375,24 @@ CSpell * CSpellHandler::loadSpell(CLegacyConfigParser & parser)
for (int i = 0; i < 4 ; i++)
spell->descriptions.push_back(parser.readString());
spell->attributes = parser.readString();
std::string attributes = parser.readString();
//spell fixes
if (id == SpellID::FORGETFULNESS)
{
//forgetfulness needs to get targets automatically on expert level
boost::replace_first(attributes, "CREATURE_TARGET", "CREATURE_TARGET_2");
}
if (id == SpellID::DISRUPTING_RAY)
{
// disrupting ray will now affect single creature
boost::replace_first(attributes,"2", "");
}
spell->setAttributes(attributes);
spell->mainEffectAnim = -1;
return spell;
}
@@ -388,8 +405,8 @@ void CSpellHandler::loadSpells()
{
do
{
CSpell * spell = loadSpell(parser);
spell->id = SpellID(spells.size());
const SpellID id = SpellID(spells.size());
CSpell * spell = loadSpell(parser,id);
spell->combatSpell = combat;
spell->creatureAbility = alility;
spells.push_back(spell);
@@ -410,9 +427,6 @@ void CSpellHandler::loadSpells()
skip(3);
read(true,true);//read creature abilities
boost::replace_first (spells[SpellID::DISRUPTING_RAY]->attributes, "2", ""); // disrupting ray will now affect single creature
spells.push_back(spells[SpellID::ACID_BREATH_DEFENSE]); //clone Acid Breath attributes for Acid Breath damage effect
//loading of additional spell traits
@@ -452,10 +466,6 @@ void CSpellHandler::loadSpells()
{
s->isRising = true;
}
else if (flag == "mind")
{
s->isMind = true;
}
else if (flag == "offensive")
{
s->isOffensive = true;
@@ -519,12 +529,14 @@ void CSpellHandler::loadSpells()
read_node("immunity",s->immunities);
read_node("limit",s->limiters);
const JsonNode & graphicsNode = spell.second["graphics"];
if (!graphicsNode.isNull())
{
const JsonNode& iconImmune = graphicsNode["iconImmune"];
if (!iconImmune.isNull())
s->iconImmune = iconImmune.String();
}
}
//spell fixes
//forgetfulness needs to get targets automatically on expert level
boost::replace_first(spells[SpellID::FORGETFULNESS]->attributes, "CREATURE_TARGET", "CREATURE_TARGET_2"); //TODO: use flags instead?
}
std::vector<bool> CSpellHandler::getDefaultAllowedSpells() const