Explorar el Código

Moved bonus names to translation

Ivan Savenko hace 2 años
padre
commit
35775b90f8

+ 158 - 1
Mods/vcmi/config/vcmi/english.json

@@ -82,5 +82,162 @@
 	"vcmi.stackExperience.rank.8" : "Expert",
 	"vcmi.stackExperience.rank.9" : "Elite",
 	"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)"
 }

+ 0 - 476
config/bonuses_texts.json

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

+ 1 - 2
config/gameConfig.json

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

+ 0 - 13
config/sp_sounds.json

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

+ 34 - 115
lib/CBonusTypeHandler.cpp

@@ -18,99 +18,29 @@
 
 #include "GameConstants.h"
 #include "CCreatureHandler.h"
+#include "CGeneralTextHandler.h"
 #include "spells/CSpellHandler.h"
 
 template class std::vector<VCMI_LIB_WRAP_NAMESPACE(CBonusType)>;
 
 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()
-{
-	hidden = true;
-	icon.clear();
-	nameTemplate.clear();
-	descriptionTemplate.clear();
-}
+CBonusType::CBonusType():
+	hidden(true)
+{}
 
-CBonusType::~CBonusType()
+std::string CBonusType::getNameTextID() const
 {
-
+	return TextIdentifier( "core", "bonus", identifier, "name").get();
 }
 
-void CBonusType::buildMacros()
+std::string CBonusType::getDescriptionTextID() const
 {
-	name = MacroString(nameTemplate);
-	description = MacroString(descriptionTemplate);
+	return TextIdentifier( "core", "bonus", identifier, "description").get();
 }
 
-
 ///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
 {
-	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];
 	if(bt.hidden)
 		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
@@ -304,31 +221,33 @@ void CBonusTypeHandler::load(const JsonNode & config)
 //
 //			bonusTypes.push_back(bt);
 
-			logBonus->warn("Adding new bonuses not implemented (%s)", node.first);
+			logBonus->warn("Unrecognized bonus name! (%s)", node.first);
 		}
 		else
 		{
 			CBonusType & bt = bonusTypes[it->second];
 
-			loadItem(node.second, bt);
+			loadItem(node.second, bt, 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.descriptionTemplate = source["description"].String();
+	dest.identifier = name;
 	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"];
 
 	if(!graphics.isNull())
-	{
 		dest.icon = graphics["icon"].String();
-	}
-	dest.buildMacros();
 }
 
 VCMI_LIB_NAMESPACE_END

+ 7 - 33
lib/CBonusTypeHandler.h

@@ -21,53 +21,27 @@ class JsonNode;
 
 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
 {
 public:
 	CBonusType();
-	~CBonusType();
+
+	std::string getNameTextID() const;
+	std::string getDescriptionTextID() const;
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & icon;
-		h & nameTemplate;
-		h & descriptionTemplate;
+		h & identifier;
 		h & hidden;
 
-		if (!h.saving)
-			buildMacros();
 	}
 
 private:
-	void buildMacros();
-	MacroString name, description;
-
 	friend class CBonusTypeHandler;
+
 	std::string icon;
-	std::string nameTemplate, descriptionTemplate;
+	std::string identifier;
 
 	bool hidden;
 };
@@ -91,7 +65,7 @@ public:
 private:
 	void load();
 	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
 };

+ 2 - 2
lib/VCMI_Lib.cpp

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