1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Moved bonus names to translation

This commit is contained in:
Ivan Savenko 2023-01-17 12:42:43 +02:00
parent 39131eba3e
commit 35775b90f8
7 changed files with 203 additions and 643 deletions

View File

@ -82,5 +82,162 @@
"vcmi.stackExperience.rank.8" : "Expert", "vcmi.stackExperience.rank.8" : "Expert",
"vcmi.stackExperience.rank.9" : "Elite", "vcmi.stackExperience.rank.9" : "Elite",
"vcmi.stackExperience.rank.10" : "Master", "vcmi.stackExperience.rank.10" : "Master",
"vcmi.stackExperience.rank.11" : "Ace" "vcmi.stackExperience.rank.11" : "Ace",
"core.bonus.ADDITIONAL_ATTACK.name": "Double Strike",
"core.bonus.ADDITIONAL_ATTACK.description": "Attacks twice",
"core.bonus.ADDITIONAL_RETALIATION.name": "Additional retaliations",
"core.bonus.ADDITIONAL_RETALIATION.description": "May Retaliate ${val} extra times",
"core.bonus.AIR_IMMUNITY.name": "Air immunity",
"core.bonus.AIR_IMMUNITY.description": "Immune to all Air school spells",
"core.bonus.ATTACKS_ALL_ADJACENT.name": "Attack all around",
"core.bonus.ATTACKS_ALL_ADJACENT.description": "Attacks all adjacent enemies",
"core.bonus.BLOCKS_RETALIATION.name": "No retaliation",
"core.bonus.BLOCKS_RETALIATION.description": "Enemy cannot Retaliate",
"core.bonus.BLOCKS_RANGED_RETALIATION.name": "No ranged retaliation",
"core.bonus.BLOCKS_RANGED_RETALIATION.description": "Enemy cannot Retaliate by shooting",
"core.bonus.CATAPULT.name": "Catapult",
"core.bonus.CATAPULT.description": "Attacks siege walls",
"core.bonus.CATAPULT_EXTRA_SHOTS.name": "Additional siege attacks",
"core.bonus.CATAPULT_EXTRA_SHOTS.description": "Can hit siege walls ${val} extra times per attack",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.name": "Reduce Casting Cost (${val})",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description": "Reduces spell cost for hero",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.name": "Magic Damper (${val})",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description": "Increases Cost of enemy spells",
"core.bonus.CHARGE_IMMUNITY.name": "Immune to Charge",
"core.bonus.CHARGE_IMMUNITY.description": "Immune to Champion charge",
"core.bonus.DARKNESS.name": "Darkness cover",
"core.bonus.DARKNESS.description": "Adds ${val} darkness radius",
"core.bonus.DEATH_STARE.name": "Death Stare (${val}%)",
"core.bonus.DEATH_STARE.description": "${val}% chance to kill single creature",
"core.bonus.DEFENSIVE_STANCE.name": "Defense Bonus",
"core.bonus.DEFENSIVE_STANCE.description": "+${val} Defense when defending",
"core.bonus.DESTRUCTION.name": "Destruction",
"core.bonus.DESTRUCTION.description": "Has ${val}% chance to kill extra units after attack",
"core.bonus.DOUBLE_DAMAGE_CHANCE.name": "Death Blow",
"core.bonus.DOUBLE_DAMAGE_CHANCE.description": "${val}% chance for double damage",
"core.bonus.DRAGON_NATURE.name": "Dragon",
"core.bonus.DRAGON_NATURE.description": "Creature has a Dragon Nature",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.name": "Direct Damage Immunity",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.description": "Immune to direct damage spells",
"core.bonus.EARTH_IMMUNITY.name": "Earth immunity",
"core.bonus.EARTH_IMMUNITY.description": "Immune to all Earth school spells",
"core.bonus.ENCHANTER.name": "Enchanter",
"core.bonus.ENCHANTER.description": "Can cast mass ${subtype.spell} every turn",
"core.bonus.ENCHANTED.name": "Enchanted",
"core.bonus.ENCHANTED.description": "Affected by permanent ${subtype.spell}",
"core.bonus.ENEMY_DEFENCE_REDUCTION.name": "Ignore Defense (${val}%)",
"core.bonus.ENEMY_DEFENCE_REDUCTION.description": "Ignores part of Defence for the attack",
"core.bonus.FIRE_IMMUNITY.name": "Fire immunity",
"core.bonus.FIRE_IMMUNITY.description": "Immune to all Fire school spells",
"core.bonus.FIRE_SHIELD.name": "Fire Shield (${val}%)",
"core.bonus.FIRE_SHIELD.description": "Reflects part of melee damage",
"core.bonus.FIRST_STRIKE.name": "First Strike",
"core.bonus.FIRST_STRIKE.description": "This creature attacks first instead of retaliating",
"core.bonus.FEAR.name": "Fear",
"core.bonus.FEAR.description": "Causes Fear on an enemy stack",
"core.bonus.FEARLESS.name": "Fearless",
"core.bonus.FEARLESS.description": "Immune to Fear ability",
"core.bonus.FLYING.name": "Fly",
"core.bonus.FLYING.description": "Can Fly (ignores obstacles)",
"core.bonus.FREE_SHOOTING.name": "Shoot Close",
"core.bonus.FREE_SHOOTING.description": "Can shoot in Close Combat",
"core.bonus.FULL_HP_REGENERATION.name": "Regeneration",
"core.bonus.FULL_HP_REGENERATION.description": "May Regenerate to full Health",
"core.bonus.GARGOYLE.name": "Gargoyle",
"core.bonus.GARGOYLE.description": "Cannot be rised or healed",
"core.bonus.GENERAL_DAMAGE_REDUCTION.name": "Reduce Damage (${val}%)",
"core.bonus.GENERAL_DAMAGE_REDUCTION.description": "Reduces physical damage from ranged or melee",
"core.bonus.HATE.name": "Hates ${subtype.creature}",
"core.bonus.HATE.description": "Does ${val}% more damage",
"core.bonus.HEALER.name": "Healer",
"core.bonus.HEALER.description": "Heals allied units",
"core.bonus.HP_REGENERATION.name": "Regeneration",
"core.bonus.HP_REGENERATION.description": "Heals ${val} hit points every round",
"core.bonus.JOUSTING.name": "Champion Charge",
"core.bonus.JOUSTING.description": "+5% damage per hex travelled",
"core.bonus.KING1.name": "King 1",
"core.bonus.KING1.description": "Vulnerable to basic SLAYER",
"core.bonus.KING2.name": "King 2",
"core.bonus.KING2.description": "Vulnerable to advanced SLAYER",
"core.bonus.KING3.name": "King 3",
"core.bonus.KING3.description":"Vulnerable to expert SLAYER",
"core.bonus.LEVEL_SPELL_IMMUNITY.name": "Spell immunity 1-${val}",
"core.bonus.LEVEL_SPELL_IMMUNITY.description": "Immune to spells of levels 1-${val}",
"core.bonus.LIMITED_SHOOTING_RANGE.name" : "Limited shooting range",
"core.bonus.LIMITED_SHOOTING_RANGE.description" : "",
"core.bonus.LIFE_DRAIN.name": "Drain life (${val}%)",
"core.bonus.LIFE_DRAIN.description": "Drains ${val}% of damage dealt",
"core.bonus.MANA_CHANNELING.name": "Magic Channel ${val}%",
"core.bonus.MANA_CHANNELING.description": "Gives your hero mana spent by enemy",
"core.bonus.MANA_DRAIN.name": "Mana Drain",
"core.bonus.MANA_DRAIN.description": "Drains ${val} mana every turn",
"core.bonus.MAGIC_MIRROR.name": "Magic Mirror (${val}%)",
"core.bonus.MAGIC_MIRROR.description": "${val}% chance to redirects an offensive spell to enemy",
"core.bonus.MAGIC_RESISTANCE.name": "Magic Resistance(${MR}%)",
"core.bonus.MAGIC_RESISTANCE.description": "${MR}% chance to resist enemy spell",
"core.bonus.MIND_IMMUNITY.name": "Mind Spell Immunity",
"core.bonus.MIND_IMMUNITY.description": "Immune to Mind-type spells",
"core.bonus.NO_DISTANCE_PENALTY.name": "No distance penalty",
"core.bonus.NO_DISTANCE_PENALTY.description": "Full damage from any distance",
"core.bonus.NO_MELEE_PENALTY.name": "No melee penalty",
"core.bonus.NO_MELEE_PENALTY.description": "Creature has no Melee Penalty",
"core.bonus.NO_MORALE.name": "Neutral Morale",
"core.bonus.NO_MORALE.description": "Creature is immune to morale effects",
"core.bonus.NO_WALL_PENALTY.name": "No wall penalty",
"core.bonus.NO_WALL_PENALTY.description": "Full damage during siege",
"core.bonus.NON_LIVING.name": "Non living",
"core.bonus.NON_LIVING.description": "Immunity to many effects",
"core.bonus.RANDOM_SPELLCASTER.name": "Random spellcaster",
"core.bonus.RANDOM_SPELLCASTER.description": "Can cast random spell",
"core.bonus.RANGED_RETALIATION.name": "Ranged retaliation",
"core.bonus.RANGED_RETALIATION.description": "Can perform ranged counterattack",
"core.bonus.RECEPTIVE.name": "Receptive",
"core.bonus.RECEPTIVE.description": "No Immunity to Friendly Spells",
"core.bonus.REBIRTH.name": "Rebirth (${val}%)",
"core.bonus.REBIRTH.description": "${val}% of stack will rise after death",
"core.bonus.RETURN_AFTER_STRIKE.name": "Attack and Return",
"core.bonus.RETURN_AFTER_STRIKE.description": "Returns after melee attack",
"core.bonus.SELF_LUCK.name": "Positive luck",
"core.bonus.SELF_LUCK.description": "Always has Positive Luck",
"core.bonus.SELF_MORALE.name": "Positive morale",
"core.bonus.SELF_MORALE.description": "Always has Positive Morale",
"core.bonus.SHOOTER.name": "Ranged",
"core.bonus.SHOOTER.description": "Creature can shoot",
"core.bonus.SHOOTS_ALL_ADJACENT.name": "Shoot all around",
"core.bonus.SHOOTS_ALL_ADJACENT.description": "This creature's ranged attacks strike all targets in a small area",
"core.bonus.SOUL_STEAL.name": "Soul Steal",
"core.bonus.SOUL_STEAL.description": "Gains ${val} new creatures for each enemy killed",
"core.bonus.SPELLCASTER.name": "Spellcaster",
"core.bonus.SPELLCASTER.description": "Can cast ${subtype.spell}",
"core.bonus.SPELL_AFTER_ATTACK.name": "Cast After Attack",
"core.bonus.SPELL_AFTER_ATTACK.description": "${val}% to cast ${subtype.spell} after attack",
"core.bonus.SPELL_BEFORE_ATTACK.name": "Cast Before Attack",
"core.bonus.SPELL_BEFORE_ATTACK.description": "${val}% to cast ${subtype.spell} before attack",
"core.bonus.SPELL_DAMAGE_REDUCTION.name": "Spell Resistance",
"core.bonus.SPELL_DAMAGE_REDUCTION.description": "Damage from spells reduced ${val}%.",
"core.bonus.SPELL_IMMUNITY.name": "Spell immunity",
"core.bonus.SPELL_IMMUNITY.description": "Immune to ${subtype.spell}",
"core.bonus.SPELL_LIKE_ATTACK.name": "Spell-like attack",
"core.bonus.SPELL_LIKE_ATTACK.description": "Attacks with ${subtype.spell}",
"core.bonus.SPELL_RESISTANCE_AURA.name": "Aura of Resistance",
"core.bonus.SPELL_RESISTANCE_AURA.description": "Nearby stacks get ${val}% resistance",
"core.bonus.SUMMON_GUARDIANS.name": "Summon guardians",
"core.bonus.SUMMON_GUARDIANS.description": "At battle start summons ${subtype.creature} (${val}%)",
"core.bonus.SYNERGY_TARGET.name": "Synergizable",
"core.bonus.SYNERGY_TARGET.description": "This creature is vulnerable to synergy effect",
"core.bonus.TWO_HEX_ATTACK_BREATH.name": "Breath",
"core.bonus.TWO_HEX_ATTACK_BREATH.description": "Breath Attack (2-hex range)",
"core.bonus.THREE_HEADED_ATTACK.name": "Three-headed attack",
"core.bonus.THREE_HEADED_ATTACK.description": "Attacks three adjacent units",
"core.bonus.TRANSMUTATION.name": "Transmutation",
"core.bonus.TRANSMUTATION.description": "${val}% chance to transform attacked unit to other type",
"core.bonus.UNDEAD.name": "Undead",
"core.bonus.UNDEAD.description": "Creature is Undead",
"core.bonus.UNLIMITED_RETALIATIONS.name": "Unlimited retaliations",
"core.bonus.UNLIMITED_RETALIATIONS.description": "Retaliates any number of attacks",
"core.bonus.WATER_IMMUNITY.name": "Water immunity",
"core.bonus.WATER_IMMUNITY.description": "Immune to all Water school spells",
"core.bonus.WIDE_BREATH.name": "Wide breath",
"core.bonus.WIDE_BREATH.description": "Wide breath attack (multiple hexes)"
} }

View File

@ -1,476 +0,0 @@
// macros:
// ${val} - value of bonuses; Selector: type,subtype
// ${subtype.creature} - creature name
// ${subtype.spell} - spell name
// ${MR} - magic resistance of bearer
{
"ADDITIONAL_ATTACK":
{
"name": "Double Strike",
"description": "Attacks twice"
},
"ADDITIONAL_RETALIATION":
{
"name": "Additional retaliations",
"description": "May Retaliate ${val} extra times"
},
"AIR_IMMUNITY":
{
"name": "Air immunity",
"description": "Immune to all Air school spells"
},
"ATTACKS_ALL_ADJACENT":
{
"name": "Attack all around",
"description": "Attacks all adjacent enemies"
},
"BLOCKS_RETALIATION":
{
"name": "No retaliation",
"description": "Enemy cannot Retaliate"
},
"BLOCKS_RANGED_RETALIATION":
{
"name": "No ranged retaliation",
"description": "Enemy cannot Retaliate by shooting"
},
"CATAPULT":
{
"name": "Catapult",
"description": "Attacks siege walls"
},
"CATAPULT_EXTRA_SHOTS":
{
"name": "Additional siege attacks",
"description": "Can hit siege walls ${val} extra times per attack"
},
"CHANGES_SPELL_COST_FOR_ALLY":
{
"name": "Reduce Casting Cost (${val})",
"description": "Reduces spell cost for hero"
},
"CHANGES_SPELL_COST_FOR_ENEMY":
{
"name": "Magic Damper (${val})",
"description": "Increases Cost of enemy spells"
},
"CHARGE_IMMUNITY":
{
"name": "Immune to Charge",
"description": "Immune to Champion charge"
},
"DARKNESS":
{
"name": "Darkness cover",
"description": "Adds ${val} darkness radius"
},
"DEATH_STARE":
{
"name": "Death Stare (${val}%)",
"description": "${val}% chance to kill single creature"
},
"DEFENSIVE_STANCE":
{
"name": "Defense Bonus",
"description": "+${val} Defense when defending"
},
"DESTRUCTION":
{
"name": "Destruction",
"description": "Has ${val}% chance to kill extra units after attack"
},
"DOUBLE_DAMAGE_CHANCE":
{
"name": "Death Blow",
"description": "${val}% chance for double damage"
},
"DRAGON_NATURE":
{
"name": "Dragon",
"description": "Creature has a Dragon Nature"
},
"DIRECT_DAMAGE_IMMUNITY":
{
"name": "Direct Damage Immunity",
"description": "Immune to direct damage spells"
},
"EARTH_IMMUNITY":
{
"name": "Earth immunity",
"description": "Immune to all Earth school spells"
},
"ENCHANTER":
{
"name": "Enchanter",
"description": "Can cast mass ${subtype.spell} every turn"
},
"ENCHANTED":
{
"name": "Enchanted",
"description": "Affected by permanent ${subtype.spell}"
},
"ENEMY_DEFENCE_REDUCTION":
{
"name": "Ignore Defense (${val}%)",
"description": "Ignores part of Defence for the attack"
},
"FIRE_IMMUNITY":
{
"name": "Fire immunity",
"description": "Immune to all Fire school spells"
},
"FIRE_SHIELD":
{
"name": "Fire Shield (${val}%)",
"description": "Reflects part of melee damage"
},
"FIRST_STRIKE":
{
"name": "First Strike",
"description": "This creature attacks first instead of retaliating"
},
"FEAR":
{
"name": "Fear",
"description": "Causes Fear on an enemy stack"
},
"FEARLESS":
{
"name": "Fearless",
"description": "Immune to Fear ability"
},
"FLYING":
{
"name": "Fly",
"description": "Can Fly (ignores obstacles)"
},
"FREE_SHOOTING":
{
"name": "Shoot Close",
"description": "Can shoot in Close Combat"
},
"FULL_HP_REGENERATION":
{
"name": "Regeneration",
"description": "May Regenerate to full Health"
},
"GARGOYLE":
{
"name": "Gargoyle",
"description": "Cannot be rised or healed"
},
"GENERAL_DAMAGE_REDUCTION":
{
"name": "Reduce Damage (${val}%)",
"description": "Reduces physical damage from ranged or melee"
},
"HATE":
{
"name": "Hates ${subtype.creature}",
"description": "Does ${val}% more damage"
},
"HEALER":
{
"name": "Healer",
"description": "Heals allied units"
},
"HP_REGENERATION":
{
"name": "Regeneration",
"description": "Heals ${val} hit points every round"
},
"JOUSTING":
{
"name": "Champion Charge",
"description": "+5% damage per hex travelled"
},
"KING1":
{
"name": "King 1",
"description": "Vulnerable to basic SLAYER"
},
"KING2":
{
"name": "King 2",
"description": "Vulnerable to advanced SLAYER"
},
"KING3":
{
"name": "King 3",
"description":"Vulnerable to expert SLAYER"
},
"LEVEL_SPELL_IMMUNITY":
{
"name": "Spell immunity 1-${val}",
"description": "Immune to spells of levels 1-${val}"
},
"LIFE_DRAIN":
{
"name": "Drain life (${val}%)",
"description": "Drains ${val}% of damage dealt"
},
"LIMITED_SHOOTING_RANGE":
{
"name": "Limited shooting range",
"description": "Cannot shoot targets beyond ${val} hexes away"
},
"MANA_CHANNELING":
{
"name": "Magic Channel ${val}%",
"description": "Gives your hero mana spent by enemy"
},
"MANA_DRAIN":
{
"name": "Mana Drain",
"description": "Drains ${val} mana every turn"
},
"MAGIC_MIRROR":
{
"name": "Magic Mirror (${val}%)",
"description": "${val}% chance to redirects an offensive spell to enemy"
},
"MAGIC_RESISTANCE":
{
"name": "Magic Resistance(${MR}%)",
"description": "${MR}% chance to resist enemy spell"
},
"MIND_IMMUNITY":
{
"name": "Mind Spell Immunity",
"description": "Immune to Mind-type spells"
},
"NO_DISTANCE_PENALTY":
{
"name": "No distance penalty",
"description": "Full damage from any distance"
},
"NO_MELEE_PENALTY":
{
"name": "No melee penalty",
"description": "Creature has no Melee Penalty"
},
"NO_MORALE":
{
"name": "Neutral Morale",
"description": "Creature is immune to morale effects"
},
"NO_WALL_PENALTY":
{
"name": "No wall penalty",
"description": "Full damage during siege"
},
"NON_LIVING":
{
"name": "Non living",
"description": "Immunity to many effects"
},
"RANDOM_SPELLCASTER":
{
"name": "Random spellcaster",
"description": "Can cast random spell"
},
"RANGED_RETALIATION":
{
"name": "Ranged retaliation",
"description": "Can perform ranged counterattack"
},
"RECEPTIVE":
{
"name": "Receptive",
"description": "No Immunity to Friendly Spells"
},
"REBIRTH":
{
"name": "Rebirth (${val}%)",
"description": "${val}% of stack will rise after death"
},
"RETURN_AFTER_STRIKE":
{
"name": "Attack and Return",
"description": "Returns after melee attack"
},
"SELF_LUCK":
{
"name": "Positive luck",
"description": "Always has Positive Luck"
},
"SELF_MORALE":
{
"name": "Positive morale",
"description": "Always has Positive Morale"
},
"SHOOTER":
{
"name": "Ranged",
"description": "Creature can shoot"
},
"SHOOTS_ALL_ADJACENT":
{
"name": "Shoot all around",
"description": "This creature's ranged attacks strike all targets in a small area"
},
"SOUL_STEAL":
{
"name": "Soul Steal",
"description": "Gains ${val} new creatures for each enemy killed"
},
"SPELLCASTER":
{
"name": "Spellcaster",
"description": "Can cast ${subtype.spell}"
},
"SPELL_AFTER_ATTACK":
{
"name": "Cast After Attack",
"description": "${val}% to cast ${subtype.spell} after attack"
},
"SPELL_BEFORE_ATTACK":
{
"name": "Cast Before Attack",
"description": "${val}% to cast ${subtype.spell} before attack"
},
"SPELL_DAMAGE_REDUCTION":
{
"name": "Spell Resistance",
"description": "Damage from spells reduced ${val}%."
},
"SPELL_IMMUNITY":
{
"name": "Spell immunity",
"description": "Immune to ${subtype.spell}"
},
"SPELL_LIKE_ATTACK":
{
"name": "Spell-like attack",
"description": "Attacks with ${subtype.spell}"
},
"SPELL_RESISTANCE_AURA":
{
"name": "Aura of Resistance",
"description": "Nearby stacks get ${val}% resistance"
},
"SUMMON_GUARDIANS":
{
"name": "Summon guardians",
"description": "At battle start summons ${subtype.creature} (${val}%)"
},
"SYNERGY_TARGET":
{
"name": "Synergizable",
"description": "This creature is vulnerable to synergy effect"
},
"TWO_HEX_ATTACK_BREATH":
{
"name": "Breath",
"description": "Breath Attack (2-hex range)"
},
"THREE_HEADED_ATTACK":
{
"name": "Three-headed attack",
"description": "Attacks three adjacent units"
},
"TRANSMUTATION":
{
"name": "Transmutation",
"description": "${val}% chance to transform attacked unit to other type"
},
"UNDEAD":
{
"name": "Undead",
"description": "Creature is Undead"
},
"UNLIMITED_RETALIATIONS":
{
"name": "Unlimited retaliations",
"description": "Retaliates any number of attacks"
},
"WATER_IMMUNITY":
{
"name": "Water immunity",
"description": "Immune to all Water school spells"
},
"WIDE_BREATH":
{
"name": "Wide breath",
"description": "Wide breath attack (multiple hexes)"
}
}

View File

@ -66,8 +66,7 @@
"bonuses" : "bonuses" :
[ [
"config/bonuses.json", "config/bonuses.json"
"config/bonuses_texts.json"
], ],
"spells" : "spells" :
[ [

View File

@ -1,13 +0,0 @@
// Several probably missing sounds of creature abilities
// ACID.WAV Acid breath Rust Dragons
// DEATHBLO.WAV Deathblow Death knigts
// DRAINLIF.WAV Drain life Vampires
// FEAR.WAV Fear Azure dragons
// MAGCHDRN.WAV Steal mana Imps
// MAGCHFIL.WAV Steal mana Either for upgrades or for receiving mana by hero
// MAGICRES.WAV Magic resist Dwarves
// MANADRAI.WAV Mana drain Ghosts
// REGENER.WAV Regeneration Ghosts, Trolls
// RESURECT.WAV Resurrection Both archangels and Demons
// SPONTCOMB.WAV Fireball Magogs

View File

@ -18,99 +18,29 @@
#include "GameConstants.h" #include "GameConstants.h"
#include "CCreatureHandler.h" #include "CCreatureHandler.h"
#include "CGeneralTextHandler.h"
#include "spells/CSpellHandler.h" #include "spells/CSpellHandler.h"
template class std::vector<VCMI_LIB_WRAP_NAMESPACE(CBonusType)>; template class std::vector<VCMI_LIB_WRAP_NAMESPACE(CBonusType)>;
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
///MacroString
MacroString::MacroString(const std::string & format)
{
static const std::string MACRO_START = "${";
static const std::string MACRO_END = "}";
static const size_t MACRO_START_L = 2;
static const size_t MACRO_END_L = 1;
size_t end_pos = 0;
size_t start_pos = std::string::npos;
do
{
start_pos = format.find(MACRO_START, end_pos);
if(!(start_pos == std::string::npos))
{
//chunk before macro
items.push_back(Item(Item::STRING, format.substr(end_pos, start_pos - end_pos)));
start_pos += MACRO_START_L;
end_pos = format.find(MACRO_END, start_pos);
if(end_pos == std::string::npos)
{
logBonus->warn("Format error in: %s", format);
end_pos = start_pos;
break;
}
else
{
items.push_back(Item(Item::MACRO, format.substr(start_pos, end_pos - start_pos)));
end_pos += MACRO_END_L;
}
}
}
while(start_pos != std::string::npos);
//no more macros
items.push_back(Item(Item::STRING, format.substr(end_pos)));
}
std::string MacroString::build(const GetValue & getValue) const
{
std::string result;
for(const Item & i : items)
{
switch(i.type)
{
case Item::MACRO:
{
result += getValue(i.value);
break;
}
case Item::STRING:
{
result += i.value;
break;
}
}
}
return result;
}
///CBonusType ///CBonusType
CBonusType::CBonusType() CBonusType::CBonusType():
hidden(true)
{}
std::string CBonusType::getNameTextID() const
{ {
hidden = true; return TextIdentifier( "core", "bonus", identifier, "name").get();
icon.clear();
nameTemplate.clear();
descriptionTemplate.clear();
} }
CBonusType::~CBonusType() std::string CBonusType::getDescriptionTextID() const
{ {
return TextIdentifier( "core", "bonus", identifier, "description").get();
} }
void CBonusType::buildMacros()
{
name = MacroString(nameTemplate);
description = MacroString(descriptionTemplate);
}
///CBonusTypeHandler ///CBonusTypeHandler
CBonusTypeHandler::CBonusTypeHandler() CBonusTypeHandler::CBonusTypeHandler()
@ -136,39 +66,26 @@ CBonusTypeHandler::~CBonusTypeHandler()
std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonus, const IBonusBearer * bearer, bool description) const std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonus, const IBonusBearer * bearer, bool description) const
{ {
auto getValue = [=](const std::string & name) -> std::string
{
if(name == "val")
{
return boost::lexical_cast<std::string>(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype)));
}
else if(name == "subtype.creature")
{
const CreatureID cre(bonus->subtype);
return cre.toCreature()->getNamePluralTranslated();
}
else if(name == "subtype.spell")
{
const SpellID sp(bonus->subtype);
return sp.toSpell()->getNameTranslated();
}
else if(name == "MR")
{
return boost::lexical_cast<std::string>(bearer->magicResistance());
}
else
{
logBonus->warn("Unknown macro in bonus config: %s", name);
return "[error]";
}
};
const CBonusType & bt = bonusTypes[bonus->type]; const CBonusType & bt = bonusTypes[bonus->type];
if(bt.hidden) if(bt.hidden)
return ""; return "";
const MacroString & macro = description ? bt.description : bt.name;
return macro.build(getValue); std::string textID = description ? bt.getDescriptionTextID() : bt.getNameTextID();
std::string text = VLC->generaltexth->translate(textID);
if (text.find("${val}") != std::string::npos)
boost::algorithm::replace_all(text, "${val}", std::to_string(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))));
if (text.find("${subtype.creature}") != std::string::npos)
boost::algorithm::replace_all(text, "${subtype.creature}", CreatureID(bonus->subtype).toCreature()->getNamePluralTranslated());
if (text.find("${subtype.spell}") != std::string::npos)
boost::algorithm::replace_all(text, "${subtype.spell}", SpellID(bonus->subtype).toSpell()->getNameTranslated());
if (text.find("${MR}") != std::string::npos)
boost::algorithm::replace_all(text, "${MR}", std::to_string(bearer->magicResistance()));
return text;
} }
std::string CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const std::string CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const
@ -304,31 +221,33 @@ void CBonusTypeHandler::load(const JsonNode & config)
// //
// bonusTypes.push_back(bt); // bonusTypes.push_back(bt);
logBonus->warn("Adding new bonuses not implemented (%s)", node.first); logBonus->warn("Unrecognized bonus name! (%s)", node.first);
} }
else else
{ {
CBonusType & bt = bonusTypes[it->second]; CBonusType & bt = bonusTypes[it->second];
loadItem(node.second, bt); loadItem(node.second, bt, node.first);
logBonus->trace("Loaded bonus type %s", node.first); logBonus->trace("Loaded bonus type %s", node.first);
} }
} }
} }
void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest) void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest, const std::string & name)
{ {
dest.nameTemplate = source["name"].String(); dest.identifier = name;
dest.descriptionTemplate = source["description"].String();
dest.hidden = source["hidden"].Bool(); //Null -> false dest.hidden = source["hidden"].Bool(); //Null -> false
if (!dest.hidden)
{
VLC->generaltexth->registerString(dest.getNameTextID(), source["name"].String());
VLC->generaltexth->registerString(dest.getDescriptionTextID(), source["description"].String());
}
const JsonNode & graphics = source["graphics"]; const JsonNode & graphics = source["graphics"];
if(!graphics.isNull()) if(!graphics.isNull())
{
dest.icon = graphics["icon"].String(); dest.icon = graphics["icon"].String();
}
dest.buildMacros();
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -21,53 +21,27 @@ class JsonNode;
typedef Bonus::BonusType BonusTypeID; typedef Bonus::BonusType BonusTypeID;
class MacroString
{
struct Item
{
enum ItemType
{
STRING, MACRO
};
Item(ItemType _type, std::string _value): type(_type), value(_value){};
ItemType type;
std::string value; //constant string or macro name
};
std::vector<Item> items;
public:
typedef std::function<std::string(const std::string &)> GetValue;
MacroString() = default;
~MacroString() = default;
explicit MacroString(const std::string & format);
std::string build(const GetValue & getValue) const;
};
class DLL_LINKAGE CBonusType class DLL_LINKAGE CBonusType
{ {
public: public:
CBonusType(); CBonusType();
~CBonusType();
std::string getNameTextID() const;
std::string getDescriptionTextID() const;
template <typename Handler> void serialize(Handler & h, const int version) template <typename Handler> void serialize(Handler & h, const int version)
{ {
h & icon; h & icon;
h & nameTemplate; h & identifier;
h & descriptionTemplate;
h & hidden; h & hidden;
if (!h.saving)
buildMacros();
} }
private: private:
void buildMacros();
MacroString name, description;
friend class CBonusTypeHandler; friend class CBonusTypeHandler;
std::string icon; std::string icon;
std::string nameTemplate, descriptionTemplate; std::string identifier;
bool hidden; bool hidden;
}; };
@ -91,7 +65,7 @@ public:
private: private:
void load(); void load();
void load(const JsonNode & config); void load(const JsonNode & config);
void loadItem(const JsonNode & source, CBonusType & dest); void loadItem(const JsonNode & source, CBonusType & dest, const std::string & name);
std::vector<CBonusType> bonusTypes; //index = BonusTypeID std::vector<CBonusType> bonusTypes; //index = BonusTypeID
}; };

View File

@ -198,14 +198,14 @@ void LibClasses::init(bool onlyEssential)
modh->initializeConfig(); modh->initializeConfig();
createHandler(generaltexth, "General text", pomtime);
createHandler(bth, "Bonus type", pomtime); createHandler(bth, "Bonus type", pomtime);
createHandler(roadTypeHandler, "Road", pomtime); createHandler(roadTypeHandler, "Road", pomtime);
createHandler(riverTypeHandler, "River", pomtime); createHandler(riverTypeHandler, "River", pomtime);
createHandler(terrainTypeHandler, "Terrain", pomtime); createHandler(terrainTypeHandler, "Terrain", pomtime);
createHandler(generaltexth, "General text", pomtime);
createHandler(heroh, "Hero", pomtime); createHandler(heroh, "Hero", pomtime);
createHandler(arth, "Artifact", pomtime); createHandler(arth, "Artifact", pomtime);