mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-15 00:05:02 +02:00
Basic Configuration for bonus types
* introduced new handler BonusTypeHandler * config\bonusnames.json converted to common format and splitted info main and localizable parts * hanlders initialization refactored
This commit is contained in:
@ -10,6 +10,7 @@
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
#include "CHeroHandler.h"
|
||||
#include "IBonusTypeHandler.h"
|
||||
|
||||
/*
|
||||
* CCreatureSet.cpp, part of VCMI engine
|
||||
@ -561,341 +562,20 @@ void CStackInstance::setType(const CCreature *c)
|
||||
}
|
||||
std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
|
||||
{
|
||||
std::map<Bonus::BonusType, std::pair<std::string, std::string> >::iterator it = VLC->creh->stackBonuses.find(bonus->type);
|
||||
if (it != VLC->creh->stackBonuses.end())
|
||||
if(Bonus::MAGIC_RESISTANCE == bonus->type)
|
||||
{
|
||||
std::string text;
|
||||
if (description) //long ability description
|
||||
{
|
||||
text = it->second.second;
|
||||
switch (bonus->type)
|
||||
{
|
||||
//no additional modifiers needed
|
||||
case Bonus::FLYING:
|
||||
case Bonus::UNLIMITED_RETALIATIONS:
|
||||
case Bonus::SHOOTER:
|
||||
case Bonus::FREE_SHOOTING:
|
||||
case Bonus::NO_MELEE_PENALTY:
|
||||
case Bonus::NO_DISTANCE_PENALTY:
|
||||
case Bonus::NO_WALL_PENALTY:
|
||||
case Bonus::JOUSTING: //TODO: percent bonus?
|
||||
case Bonus::RETURN_AFTER_STRIKE:
|
||||
case Bonus::BLOCKS_RETALIATION:
|
||||
case Bonus::TWO_HEX_ATTACK_BREATH:
|
||||
case Bonus::THREE_HEADED_ATTACK:
|
||||
case Bonus::ATTACKS_ALL_ADJACENT:
|
||||
case Bonus::ADDITIONAL_ATTACK: //TODO: what with more than one attack? Axe of Ferocity for example
|
||||
case Bonus::FULL_HP_REGENERATION:
|
||||
case Bonus::MANA_DRAIN:
|
||||
case Bonus::LIFE_DRAIN:
|
||||
case Bonus::REBIRTH:
|
||||
case Bonus::SELF_MORALE:
|
||||
case Bonus::SELF_LUCK:
|
||||
case Bonus::FEAR:
|
||||
case Bonus::FEARLESS:
|
||||
case Bonus::CHARGE_IMMUNITY:
|
||||
case Bonus::HEALER:
|
||||
case Bonus::CATAPULT:
|
||||
case Bonus::DRAGON_NATURE:
|
||||
case Bonus::NON_LIVING:
|
||||
case Bonus::UNDEAD:
|
||||
case Bonus::FIRE_IMMUNITY:
|
||||
case Bonus::WATER_IMMUNITY:
|
||||
case Bonus::AIR_IMMUNITY:
|
||||
case Bonus::EARTH_IMMUNITY:
|
||||
case Bonus::RECEPTIVE:
|
||||
case Bonus::DIRECT_DAMAGE_IMMUNITY:
|
||||
break;
|
||||
//One numeric value. magic resistance handled separately
|
||||
case Bonus::SPELL_RESISTANCE_AURA:
|
||||
case Bonus::SPELL_DAMAGE_REDUCTION:
|
||||
case Bonus::LEVEL_SPELL_IMMUNITY:
|
||||
case Bonus::HP_REGENERATION:
|
||||
case Bonus::ADDITIONAL_RETALIATION:
|
||||
case Bonus::DEFENSIVE_STANCE:
|
||||
case Bonus::DOUBLE_DAMAGE_CHANCE:
|
||||
case Bonus::DARKNESS: //Darkness Dragons any1?
|
||||
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))));
|
||||
break;
|
||||
//Complex descriptions
|
||||
//case Bonus::SECONDARY_SKILL_PREMY: //only if there's no simple MR
|
||||
// if (bonus->subtype == CGHeroInstance::RESISTANCE)
|
||||
// {
|
||||
// if (!hasBonusOfType(Bonus::MAGIC_RESISTANCE))
|
||||
// boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>( magicResistance() ));
|
||||
// }
|
||||
// break;
|
||||
//case Bonus::MAGIC_RESISTANCE:
|
||||
// boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>( magicResistance() ));
|
||||
// break;
|
||||
case Bonus::HATE:
|
||||
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))));
|
||||
boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl);
|
||||
break;
|
||||
case Bonus::SPELL_AFTER_ATTACK:
|
||||
case Bonus::SPELL_BEFORE_ATTACK:
|
||||
{
|
||||
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))));
|
||||
boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name);
|
||||
break;
|
||||
}
|
||||
case Bonus::SPELL_LIKE_ATTACK:
|
||||
{
|
||||
boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{}//TODO: allow custom bonus types... someday, somehow
|
||||
}
|
||||
}
|
||||
else //short name
|
||||
{
|
||||
text = it->second.first;
|
||||
switch (bonus->type)
|
||||
{
|
||||
case Bonus::MANA_CHANNELING:
|
||||
case Bonus::MAGIC_MIRROR:
|
||||
case Bonus::CHANGES_SPELL_COST_FOR_ALLY:
|
||||
case Bonus::CHANGES_SPELL_COST_FOR_ENEMY:
|
||||
case Bonus::ENEMY_DEFENCE_REDUCTION:
|
||||
case Bonus::REBIRTH:
|
||||
case Bonus::DEATH_STARE:
|
||||
case Bonus::LIFE_DRAIN:
|
||||
case Bonus::FIRE_SHIELD:
|
||||
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))));
|
||||
break;
|
||||
case Bonus::HATE:
|
||||
case Bonus::DAEMON_SUMMONING:
|
||||
boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl);
|
||||
break;
|
||||
case Bonus::LEVEL_SPELL_IMMUNITY:
|
||||
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bonus->val));
|
||||
break;
|
||||
case Bonus::SPELL_AFTER_ATTACK:
|
||||
case Bonus::SPELL_BEFORE_ATTACK:
|
||||
case Bonus::SPELL_IMMUNITY:
|
||||
case Bonus::SPELLCASTER:
|
||||
case Bonus::ENCHANTER:
|
||||
case Bonus::ENCHANTED:
|
||||
boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name);
|
||||
break;
|
||||
case Bonus::MAGIC_RESISTANCE:
|
||||
text = ""; //handled separately
|
||||
break;
|
||||
//case Bonus::SECONDARY_SKILL_PREMY:
|
||||
// if (bonus->subtype != CGHeroInstance::RESISTANCE || hasBonusOfType(Bonus::MAGIC_RESISTANCE)) //handle it there
|
||||
// text = "";
|
||||
// break;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
return "";
|
||||
}
|
||||
else
|
||||
return "";
|
||||
{
|
||||
return VLC->getBth()->bonusToString(bonus, this, description);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string CStackInstance::bonusToGraphics(Bonus *bonus) const
|
||||
{
|
||||
std::string fileName;
|
||||
bool fullPath = false;
|
||||
switch (bonus->type)
|
||||
{
|
||||
//"E_ALIVE.bmp"
|
||||
//"E_ART.bmp"
|
||||
case Bonus::ENCHANTED:
|
||||
fileName = "E_BLESS.bmp"; break;
|
||||
//"E_BLOCK.bmp"
|
||||
//"E_BLOCK1.bmp"
|
||||
//"E_BLOCK2.bmp"
|
||||
case Bonus::TWO_HEX_ATTACK_BREATH:
|
||||
fileName = "E_BREATH.bmp"; break;
|
||||
case Bonus::SPELL_AFTER_ATTACK:
|
||||
fileName = "E_CAST.bmp"; break;
|
||||
case Bonus::ENCHANTER:
|
||||
fileName = "E_CAST1.bmp"; break;
|
||||
case Bonus::RANDOM_SPELLCASTER:
|
||||
fileName = "RandomBoost.bmp"; break;
|
||||
case Bonus::SPELL_BEFORE_ATTACK:
|
||||
fileName ="E_CAST2.bmp"; break;
|
||||
case Bonus::SPELLCASTER:
|
||||
fileName = "E_CASTER.bmp"; break;
|
||||
case Bonus::JOUSTING:
|
||||
fileName = "E_CHAMP.bmp"; break;
|
||||
case Bonus::DOUBLE_DAMAGE_CHANCE:
|
||||
fileName = "E_DBLOW.bmp"; break;
|
||||
case Bonus::DEATH_STARE:
|
||||
fileName = "E_DEATH.bmp"; break;
|
||||
case Bonus::DEFENSIVE_STANCE:
|
||||
fileName = "E_DEFBON.bmp"; break;
|
||||
case Bonus::NO_DISTANCE_PENALTY:
|
||||
fileName = "E_DIST.bmp"; break;
|
||||
case Bonus::ADDITIONAL_ATTACK:
|
||||
fileName = "E_DOUBLE.bmp"; break;
|
||||
case Bonus::DRAGON_NATURE:
|
||||
fileName = "E_DRAGON.bmp"; break;
|
||||
case Bonus::MAGIC_RESISTANCE:
|
||||
fileName = "E_DWARF.bmp"; break;
|
||||
case Bonus::SECONDARY_SKILL_PREMY:
|
||||
if (bonus->subtype == SecondarySkill::RESISTANCE)
|
||||
{
|
||||
fileName = "E_DWARF.bmp";
|
||||
}
|
||||
break;
|
||||
case Bonus::FEAR:
|
||||
fileName = "E_FEAR.bmp"; break;
|
||||
case Bonus::FEARLESS:
|
||||
fileName = "E_FEARL.bmp"; break;
|
||||
case Bonus::FLYING:
|
||||
fileName = "E_FLY.bmp"; break;
|
||||
case Bonus::SPELL_DAMAGE_REDUCTION:
|
||||
fileName = "E_GOLEM.bmp"; break;
|
||||
case Bonus::RETURN_AFTER_STRIKE:
|
||||
fileName = "E_HARPY.bmp"; break;
|
||||
case Bonus::HATE:
|
||||
fileName = "E_HATE.bmp"; break;
|
||||
case Bonus::KING1:
|
||||
fileName = "E_KING1.bmp"; break;
|
||||
case Bonus::KING2:
|
||||
fileName = "E_KING2.bmp"; break;
|
||||
case Bonus::KING3:
|
||||
fileName = "E_KING3.bmp"; break;
|
||||
case Bonus::CHANGES_SPELL_COST_FOR_ALLY:
|
||||
fileName = "E_MANA.bmp"; break;
|
||||
case Bonus::CHANGES_SPELL_COST_FOR_ENEMY:
|
||||
fileName = "MagicDamper.bpm"; break;
|
||||
case Bonus::NO_MELEE_PENALTY:
|
||||
fileName = "E_MELEE.bmp"; break;
|
||||
case Bonus::MIND_IMMUNITY:
|
||||
fileName = "E_MIND.bmp"; break;
|
||||
case Bonus::SELF_MORALE:
|
||||
fileName = "E_MINOT.bmp"; break;
|
||||
case Bonus::NO_MORALE:
|
||||
fileName = "E_MORAL.bmp"; break;
|
||||
case Bonus::RECEPTIVE:
|
||||
fileName = "E_NOFRIM.bmp"; break;
|
||||
case Bonus::NO_WALL_PENALTY:
|
||||
fileName = "E_OBST.bmp"; break;
|
||||
case Bonus::ENEMY_DEFENCE_REDUCTION:
|
||||
fileName = "E_RDEF.bmp"; break;
|
||||
case Bonus::REBIRTH:
|
||||
fileName = "E_REBIRTH.bmp"; break;
|
||||
case Bonus::BLOCKS_RETALIATION:
|
||||
fileName = "E_RETAIL.bmp"; break;
|
||||
case Bonus::UNLIMITED_RETALIATIONS:
|
||||
case Bonus::ADDITIONAL_RETALIATION:
|
||||
fileName = "E_RETAIL1.bmp"; break;
|
||||
case Bonus::ATTACKS_ALL_ADJACENT:
|
||||
fileName = "E_ROUND.bmp"; break;
|
||||
//"E_SGNUM.bmp"
|
||||
//"E_SGTYPE.bmp"
|
||||
case Bonus::SHOOTER:
|
||||
fileName = "E_SHOOT.bmp"; break;
|
||||
case Bonus::FREE_SHOOTING: //shooter is not blocked by enemy
|
||||
fileName = "E_SHOOTA.bmp"; break;
|
||||
//"E_SHOOTN.bmp"
|
||||
case Bonus::SPELL_IMMUNITY:
|
||||
{
|
||||
fullPath = true;
|
||||
const CSpell * sp = SpellID(bonus->subtype).toSpell();
|
||||
fileName = sp->getIconImmune();
|
||||
break;
|
||||
}
|
||||
//"E_SPAWILL.bmp"
|
||||
case Bonus::DIRECT_DAMAGE_IMMUNITY:
|
||||
fileName = "E_SPDIR.bmp"; break;
|
||||
//"E_SPDISB.bmp"
|
||||
//"E_SPDISP.bmp"
|
||||
//"E_SPEATH.bmp"
|
||||
//"E_SPEATH1.bmp"
|
||||
case Bonus::FIRE_IMMUNITY:
|
||||
switch (bonus->subtype)
|
||||
{
|
||||
case 0:
|
||||
fileName = "E_SPFIRE.bmp"; break; //all
|
||||
case 1:
|
||||
fileName = "E_SPFIRE1.bmp"; break; //not positive
|
||||
case 2:
|
||||
fileName = "E_FIRE.bmp"; break; //direct damage
|
||||
}
|
||||
break;
|
||||
case Bonus::WATER_IMMUNITY:
|
||||
switch (bonus->subtype)
|
||||
{
|
||||
case 0:
|
||||
fileName = "E_SPWATER.bmp"; break; //all
|
||||
case 1:
|
||||
fileName = "E_SPWATER1.bmp"; break; //not positive
|
||||
case 2:
|
||||
fileName = "E_SPCOLD.bmp"; break; //direct damage
|
||||
}
|
||||
break;
|
||||
case Bonus::AIR_IMMUNITY:
|
||||
switch (bonus->subtype)
|
||||
{
|
||||
case 0:
|
||||
fileName = "E_SPAIR.bmp"; break; //all
|
||||
case 1:
|
||||
fileName = "E_SPAIR1.bmp"; break; //not positive
|
||||
case 2:
|
||||
fileName = "E_LIGHT.bmp"; break;//direct damage
|
||||
}
|
||||
break;
|
||||
case Bonus::EARTH_IMMUNITY:
|
||||
switch (bonus->subtype)
|
||||
{
|
||||
case 0:
|
||||
fileName = "E_SPEATH.bmp"; break; //all
|
||||
case 1:
|
||||
case 2: //no specific icon for direct damage immunity
|
||||
fileName = "E_SPEATH1.bmp"; break; //not positive
|
||||
}
|
||||
break;
|
||||
case Bonus::LEVEL_SPELL_IMMUNITY:
|
||||
{
|
||||
if (vstd::iswithin(bonus->val, 1 , 5))
|
||||
{
|
||||
fileName = "E_SPLVL" + boost::lexical_cast<std::string>(bonus->val) + ".bmp";
|
||||
}
|
||||
break;
|
||||
}
|
||||
//"E_SUMMON.bmp"
|
||||
//"E_SUMMON1.bmp"
|
||||
//"E_SUMMON2.bmp"
|
||||
case Bonus::FULL_HP_REGENERATION:
|
||||
case Bonus::HP_REGENERATION:
|
||||
fileName = "E_TROLL.bmp"; break;
|
||||
case Bonus::UNDEAD:
|
||||
fileName = "E_UNDEAD.bmp"; break;
|
||||
case Bonus::SPELL_RESISTANCE_AURA:
|
||||
fileName = "E_UNIC.bmp"; break;
|
||||
case Bonus::THREE_HEADED_ATTACK:
|
||||
fileName = "ThreeHeaded.bmp"; break;
|
||||
case Bonus::DAEMON_SUMMONING:
|
||||
fileName = "RiseDemons.bmp"; break;
|
||||
case Bonus::CHARGE_IMMUNITY:
|
||||
fileName = "ChargeImmune.bmp"; break;
|
||||
case Bonus::HEALER:
|
||||
fileName = "Healer.bmp"; break;
|
||||
case Bonus::CATAPULT:
|
||||
fileName = "Catapult.bmp"; break;
|
||||
case Bonus::MANA_CHANNELING:
|
||||
fileName = "ManaChannel.bmp"; break;
|
||||
case Bonus::MANA_DRAIN:
|
||||
fileName = "ManaDrain.bmp"; break;
|
||||
case Bonus::LIFE_DRAIN:
|
||||
fileName = "DrainLife.bmp"; break;
|
||||
case Bonus::FIRE_SHIELD:
|
||||
fileName = "FireShield.bmp"; break;
|
||||
case Bonus::MAGIC_MIRROR:
|
||||
fileName = "MagicMirror.bmp"; break;
|
||||
case Bonus::NON_LIVING:
|
||||
fileName = "NonLiving.bmp"; break;
|
||||
case Bonus::SPELL_LIKE_ATTACK:
|
||||
fileName = "SpellLikeAttack.bmp"; break;
|
||||
}
|
||||
if(!fileName.empty() && !fullPath)
|
||||
fileName = "zvs/Lib1.res/" + fileName;
|
||||
return fileName;
|
||||
return VLC->getBth()->bonusToGraphics(bonus);
|
||||
}
|
||||
|
||||
void CStackInstance::setArmyObj(const CArmedInstance *ArmyObj)
|
||||
|
Reference in New Issue
Block a user