diff --git a/client/CCreatureWindow.cpp b/client/CCreatureWindow.cpp index 566899f70..65af3a886 100644 --- a/client/CCreatureWindow.cpp +++ b/client/CCreatureWindow.cpp @@ -22,13 +22,13 @@ #include "../lib/CArtHandler.h" #include "../lib/NetPacks.h" //ArtifactLocation #include "../lib/CModHandler.h" +#include "../lib/IBonusTypeHandler.h" #include "UIFramework/CGuiHandler.h" #include "UIFramework/CIntObjectClasses.h" using namespace CSDL_Ext; -class CBonusItem; class CCreatureArtifactInstance; class CSelectableSkill; @@ -269,24 +269,24 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode * } } - int magicResistance = 0; //handle it separately :/ + + //handle Magic resistance separately :/ + const IBonusBearer *temp = stack; + if (battleStack) { - magicResistance = battleStack->magicResistance(); //include Aura of Resistance - } - else - { - magicResistance = stack->magicResistance(); //include Resiatance hero skill + temp = battleStack; } + + int magicResistance = temp->magicResistance(); + if (magicResistance) { - std::map >::const_iterator it = CGI->creh->stackBonuses.find(Bonus::MAGIC_RESISTANCE); - std::string description; - text = it->second.first; - description = it->second.second; - boost::algorithm::replace_first(description, "%d", boost::lexical_cast(magicResistance)); Bonus b; b.type = Bonus::MAGIC_RESISTANCE; + + text = VLC->getBth()->bonusToString(&b,temp,false); + const std::string description = VLC->getBth()->bonusToString(&b,temp,true); bonusItems.push_back (new CBonusItem(genRect(0, 0, 251, 57), text, description, stack->bonusToGraphics(&b))); } diff --git a/client/CCreatureWindow.h b/client/CCreatureWindow.h index 440bd90e5..d8537f89c 100644 --- a/client/CCreatureWindow.h +++ b/client/CCreatureWindow.h @@ -117,7 +117,6 @@ public: CBonusItem(const Rect &Pos, const std::string &Name, const std::string &Description, const std::string &graphicsName); ~CBonusItem(); - void setBonus (const Bonus &bonus); void showAll (SDL_Surface * to); }; diff --git a/config/bonuses.json b/config/bonuses.json new file mode 100644 index 000000000..89a2eb9ac --- /dev/null +++ b/config/bonuses.json @@ -0,0 +1,526 @@ +//TODO: selector-based config +// SECONDARY_SKILL_PREMY +// school immunities +// LEVEL_SPELL_IMMUNITY + +{ + "ADDITIONAL_ATTACK": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_DOUBLE" + } + }, + + "ADDITIONAL_RETALIATION": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_RETAIL1" + } + }, + + "AIR_IMMUNITY": + { + "graphics": + { + "icon": "" + } + }, + + "ATTACKS_ALL_ADJACENT": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_ROUND" + } + }, + + "BLOCKS_RETALIATION": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_RETAIL" + } + }, + + "CATAPULT": + { + "graphics": + { + "icon": "zvs/Lib1.res/Catapult" + } + }, + + "CHANGES_SPELL_COST_FOR_ALLY": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_MANA" + } + }, + + "CHANGES_SPELL_COST_FOR_ENEMY": + { + "graphics": + { + "icon": "zvs/Lib1.res/MagicDamper" + } + }, + + "CHARGE_IMMUNITY": + { + "graphics": + { + "icon": "zvs/Lib1.res/ChargeImmune" + } + }, + + "DAEMON_SUMMONING": + { + "graphics": + { + "icon": "zvs/Lib1.res/RiseDemons" + } + }, + + "DARKNESS": + { + }, + + "DEATH_STARE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_DEATH" + } + }, + + "DEFENSIVE_STANCE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_DEFBON" + } + }, + + "DOUBLE_DAMAGE_CHANCE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_DBLOW" + } + }, + + "DRAGON_NATURE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_DRAGON" + } + }, + + "DIRECT_DAMAGE_IMMUNITY": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_SPDIR" + } + }, + + "EARTH_IMMUNITY": + { + "graphics": + { + "icon": "" + } + }, + + "ENCHANTER": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_CAST1" + } + }, + + "ENCHANTED": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_BLESS" + } + }, + + + + "ENEMY_DEFENCE_REDUCTION": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_RDEF" + } + }, + + "FIRE_IMMUNITY": + { + "graphics": + { + "icon": "" + } + }, + + "FIRE_SHIELD": + { + "graphics": + { + "icon": "zvs/Lib1.res/FireShield" + } + }, + "FEAR": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_FEAR" + } + }, + + "FEARLESS": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_FEARL" + } + }, + + "FLYING": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_FLY" + } + + }, + + "FREE_SHOOTING": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_SHOOTA" + } + + }, + + "FULL_HP_REGENERATION": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_TROLL" + } + }, + + "HATE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_HATE" + } + }, + + "HEALER": + { + "graphics": + { + "icon": "zvs/Lib1.res/Healer" + } + }, + + "HP_REGENERATION": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_TROLL" + } + }, + "JOUSTING": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_CHAMP" + } + }, + + "KING1": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_KING1" + } + }, + + "KING2": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_KING2" + } + }, + + "KING3": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_KING3" + } + }, + + "LEVEL_SPELL_IMMUNITY": + { + "graphics": + { + "icon": "" + } + }, + + "LIFE_DRAIN": + { + "graphics": + { + "icon": "zvs/Lib1.res/DrainLife" + } + }, + + "MANA_CHANNELING": + { + "graphics": + { + "icon": "zvs/Lib1.res/ManaChannel" + } + }, + "MANA_DRAIN": + { + "graphics": + { + "icon": "zvs/Lib1.res/ManaDrain" + } + }, + + "MAGIC_MIRROR": + { + "graphics": + { + "icon": "zvs/Lib1.res/MagicMirror" + } + }, + + "MAGIC_RESISTANCE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_DWARF" + } + }, + + "MIND_IMMUNITY": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_MIND" + } + }, + + "NO_DISTANCE_PENALTY": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_DIST" + } + }, + "NO_MELEE_PENALTY": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_MELEE" + } + }, + + "NO_MORALE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_MORAL" + } + }, + "NO_WALL_PENALTY": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_OBST" + } + }, + + "NON_LIVING": + { + "graphics": + { + "icon": "zvs/Lib1.res/NonLiving" + } + }, + + "RANDOM_SPELLCASTER": + { + "graphics": + { + "icon": "zvs/Lib1.res/RandomBoost" + } + }, + + "RECEPTIVE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_NOFRIM" + } + }, + "REBIRTH": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_REBIRTH" + } + }, + + "RETURN_AFTER_STRIKE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_HARPY" + } + }, + + "SECONDARY_SKILL_PREMY": + { + "hidden": true + //todo: selector based config + }, + + "SELF_LUCK": + { + "graphics": + { + "icon": "" + } + }, + + "SELF_MORALE": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_MINOT" + } + }, + + "SHOOTER": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_SHOOT" + } + }, + "SPELLCASTER": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_CASTER" + } + }, + + "SPELL_AFTER_ATTACK": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_CAST" + } + }, + + "SPELL_BEFORE_ATTACK": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_CAST2" + } + }, + + "SPELL_DAMAGE_REDUCTION": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_GOLEM" + } + }, + + "SPELL_IMMUNITY": + { + "graphics": + { + "icon": "" //todo: configurable use from spell handler + } + }, + + + "SPELL_LIKE_ATTACK": + { + "graphics": + { + "icon": "zvs/Lib1.res/SpellLikeAttack" + } + }, + + "SPELL_RESISTANCE_AURA": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_UNIC" + } + }, + + "TWO_HEX_ATTACK_BREATH": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_BREATH" + } + }, + + + "THREE_HEADED_ATTACK": + { + "graphics": + { + "icon": "zvs/Lib1.res/ThreeHeaded" + } + }, + + "UNDEAD": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_UNDEAD" + } + }, + "UNLIMITED_RETALIATIONS": + { + "graphics": + { + "icon": "zvs/Lib1.res/E_RETAIL1" + } + }, + "WATER_IMMUNITY": + { + "graphics": + { + "icon": "" + } + } +} + diff --git a/config/bonuses_texts.json b/config/bonuses_texts.json new file mode 100644 index 000000000..359b39770 --- /dev/null +++ b/config/bonuses_texts.json @@ -0,0 +1,387 @@ +// 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": "Immune to Air", + "description": "" + }, + + "ATTACKS_ALL_ADJACENT": + { + "name": "Attack all around", + "description": "Attacks all adjacent enemies" + }, + + "BLOCKS_RETALIATION": + { + "name": "No retaliation", + "description": "Enemy cannot Retaliate" + }, + + "CATAPULT": + { + "name": "Catapult", + "description": "Attacks siege walls" + }, + + "CHANGES_SPELL_COST_FOR_ALLY": + { + "name": "Reduce Casting Cost (${val})", + "description": "Reduce Casting Cost for hero" + }, + + "CHANGES_SPELL_COST_FOR_ENEMY": + { + "name": "Magic Damper (${val})", + "description": "Increase Cost of enemy spells" + }, + + "CHARGE_IMMUNITY": + { + "name": "Immune to Charge", + "description": "Immune to Champion charge" + }, + + "DAEMON_SUMMONING": + { + "name": "Summoner (${subtype.creature})", + "description": "Can rise creatures from corpses" + }, + + "DARKNESS": + { + "name": "Darness cover", + "description": "Adds ${val} darkness radius" + }, + + "DEATH_STARE": + { + "name": "Death Stare (${val}%)", + "description": "Chance to kill single creature" + }, + + "DEFENSIVE_STANCE": + { + "name": "Defense Bonus", + "description": "+${val} Defense when defending" + }, + + "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": "Immune to Earth", + "description": "" + }, + + "ENCHANTER": + { + "name": "Enchanter (${subtype.spell})", + "description": "Casts mass spell every turn" + }, + + "ENCHANTED": + { + "name": "Enchanted (${subtype.spell})", + "description": "Affected by permanent spell" + }, + + "ENEMY_DEFENCE_REDUCTION": + { + "name": "Reduce Enemy Defense (${val}%)", + "description": "Reduces Defense for one attack" + }, + + "FIRE_IMMUNITY": + { + "name": "Immune to Fire", + "description": "" + }, + + "FIRE_SHIELD": + { + "name": "Fire Shield (${val}%)", + "description": "Reflects melee damage" + }, + "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 full Health" + }, + + "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": + { + }, + + "KING2": + { + }, + + "KING3": + { + }, + + "LEVEL_SPELL_IMMUNITY": + { + "name": "Spell immunity 1-${val}", + "description": "Immune to spells levels 1-${val}" + }, + + "LIFE_DRAIN": + { + "name": "Drain life (${val}%)", + "description": "Drains ${val}% of damage dealt" + }, + + "MANA_CHANNELING": + { + "name": "Magic Channel ${val}%", + "description": "Gives 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 offensive spell to enemy" + }, + + "MAGIC_RESISTANCE": + { + "name": "Magic Resistance(${MR}%)", + "description": "${MR}% chance to resist enemy spell" + }, + + "MIND_IMMUNITY": + { + "name": "Immune to mind spells", + "description": "" + }, + + "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": + { + + }, + + "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" + }, + + "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" + }, + "SPELLCASTER": + { + "name": "Spellcaster (${subtype.spell})", + "description": "Can cast spells" + }, + + "SPELL_AFTER_ATTACK": + { + "name": "Caster - ${subtype.spell}", + "description": "${val}% chance to cast after attack" + }, + + "SPELL_BEFORE_ATTACK": + { + "name": "Caster - ${subtype.spell}", + "description": "${val}% chance to cast before attack" + }, + + "SPELL_DAMAGE_REDUCTION": + { + "name": "Spell Resistance", + "description": "Damage from spells reduced ${val}%." + }, + + "SPELL_IMMUNITY": + { + "name": "Immune to ${subtype.spell}", + "description": "" + }, + + + "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" + }, + + "TWO_HEX_ATTACK_BREATH": + { + "name": "Breath", + "description": "Breath Attack (2-hex range)" + }, + + + + "THREE_HEADED_ATTACK": + { + "name": "Three-headed attack", + "description": "Attacks three adjacent units" + }, + + "UNDEAD": + { + "name": "Undead", + "description": "Creature is Undead" + }, + "UNLIMITED_RETALIATIONS": + { + "name": "Unlimited retaliations", + "description": "Retaliate any number of attacks" + }, + "WATER_IMMUNITY": + { + "name": "Immune to Water", + "description": "" + } +} diff --git a/config/bonusnames.json b/config/bonusnames.json deleted file mode 100644 index a3ecb8e8b..000000000 --- a/config/bonusnames.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "bonuses": - [ - { "id": "ADDITIONAL_RETALIATION", "name": "Additional retaliations", "description": "May Retaliate %d extra times" }, - { "id": "ATTACKS_ALL_ADJACENT", "name": "Attack all around", "description": "Attacks all adjacent enemies" }, - { "id": "RETURN_AFTER_STRIKE", "name": "Attack and Return", "description": "Returns after melee attack" }, - { "id": "SPELL_RESISTANCE_AURA", "name": "Aura of Resistance", "description": "Nearby stacks get %d% resistance" }, - { "id": "TWO_HEX_ATTACK_BREATH", "name": "Breath", "description": "Breath Attack (2-hex range)" }, - { "id": "SPELL_AFTER_ATTACK", "name": "Caster - %s", "description": "%d% chance to cast after attack" }, - { "id": "SPELL_BEFORE_ATTACK", "name": "Caster - %s", "description": "%d% chance to cast before attack" }, - { "id": "SPELL_LIKE_ATTACK", "name": "Spell-like attack", "description": "Attacks with %s" }, - { "id": "CATAPULT", "name": "Catapult", "description": "Attacks siege walls" }, - { "id": "JOUSTING", "name": "Champion Charge", "description": "+5% damage per hex travelled" }, - { "id": "DOUBLE_DAMAGE_CHANCE", "name": "Death Blow", "description": "%d% chance for double damage" }, - { "id": "DEFENSIVE_STANCE", "name": "Defense Bonus", "description": "+%d Defense when defending" }, - { "id": "ADDITIONAL_ATTACK", "name": "Double Strike", "description": "Attacks twice" }, - { "id": "DRAGON_NATURE", "name": "Dragon", "description": "Creature has a Dragon Nature" }, - { "id": "LIFE_DRAIN", "name": "Drain life (%d%)", "description": "Drains life equal to damage dealt" }, - { "id": "FEAR", "name": "Fear", "description": "Causes Fear on an enemy stack" }, - { "id": "FEARLESS", "name": "Fearless", "description": "Immune to Fear ability" }, - { "id": "FLYING", "name": "Fly", "description": "Can Fly (ignores obstacles)" }, - { "id": "HATE", "name": "Hates %s", "description": "Does %d% more damage" }, - { "id": "HEALER", "name": "Healer", "description": "Heals allied units" }, - { "id": "SPELL_IMMUNITY", "name": "Immune to %s", "description": "" }, - { "id": "CHARGE_IMMUNITY", "name": "Immune to Charge", "description": "Immune to Champion charge" }, - { "id": "MANA_CHANNELING", "name": "Magic Channel %d%", "description": "Gives mana spent by enemy" }, - { "id": "MANA_DRAIN", "name": "Mana Drain", "description": "Drains %d mana every turn" }, - { "id": "CHANGES_SPELL_COST_FOR_ENEMY", "name": "Magic Damper (%d)", "description": "Increase Cost of enemy spells" }, - { "id": "MAGIC_MIRROR", "name": "Magic Mirror (%d%)", "description": "Redirects offensive spell to enemy" }, - { "id": "MAGIC_RESISTANCE", "name": "Magic Resistance", "description": "%d% chance to resist enemy spell" }, - { "id": "NO_DISTANCE_PENALTY", "name": "No distance penalty", "description": "Full damage from any distance" }, - { "id": "NO_MELEE_PENALTY", "name": "No melee penalty", "description": "Creature has no Melee Penalty" }, - { "id": "NO_WALL_PENALTY", "name": "No wall penalty", "description": "Full damage during siege" }, - { "id": "BLOCKS_RETALIATION", "name": "No retaliation", "description": "Enemy cannot Retaliate" }, - { "id": "NON_LIVING", "name": "Non living", "description": "Immunity to many effects" }, - { "id": "SELF_LUCK", "name": "Positive luck", "description": "Always has Positive Luck" }, - { "id": "SELF_MORALE", "name": "Positive morale", "description": "Always has Positive Morale" }, - { "id": "SHOOTER", "name": "Ranged", "description": "Creature can shoot" }, - { "id": "CHANGES_SPELL_COST_FOR_ALLY", "name": "Reduce Casting Cost (%d)", "description": "Reduce Casting Cost for hero" }, - { "id": "ENEMY_DEFENCE_REDUCTION", "name": "Reduce Enemy Defense (%d%)", "description": "Reduces Defense for one attack" }, - { "id": "FULL_HP_REGENERATION", "name": "Regeneration", "description": "May Regenerate full Health" }, - { "id": "HP_REGENERATION", "name": "Regeneration", "description": "Heals %d hit points every round" }, - { "id": "FREE_SHOOTING", "name": "Shoot Close", "description": "Can shoot in Close Combat" }, - { "id": "LEVEL_SPELL_IMMUNITY", "name": "Spell immunity 1-%d", "description": "Immune to spells levels 1-%d" }, - { "id": "SPELL_DAMAGE_REDUCTION", "name": "Spell Resistance", "description": "Damage from spells reduced %d%." }, - { "id": "THREE_HEADED_ATTACK", "name": "Three-headed attack", "description": "Attacks three adjacent units" }, - { "id": "UNDEAD", "name": "Undead", "description": "Creature is Undead" }, - { "id": "UNLIMITED_RETALIATIONS", "name": "Unlimited retaliations", "description": "Retaliate any number of attacks" }, - { "id": "DEATH_STARE", "name": "Death Stare (%d%)", "description": "Chance to kill single creature" }, - { "id": "FIRE_IMMUNITY", "name": "Immune to Fire", "description": "" }, - { "id": "WATER_IMMUNITY", "name": "Immune to Water", "description": "" }, - { "id": "AIR_IMMUNITY", "name": "Immune to Air", "description": "" }, - { "id": "EARTH_IMMUNITY", "name": "Immune to Earth", "description": "" }, - { "id": "MIND_IMMUNITY", "name": "Immune to mind spells", "description": "" }, - { "id": "DIRECT_DAMAGE_IMMUNITY", "name": "Direct Damage Immunity", "description": "Immune to direct damage spells" }, - { "id": "RECEPTIVE", "name": "Receptive", "description": "No Immunity to Friendly Spells" }, - { "id": "REBIRTH", "name": "Rebirth (%d%)", "description": "Stack will rise after death" }, - { "id": "SPELLCASTER", "name": "Spellcaster (%s)", "description": "Can cast spells" }, - { "id": "ENCHANTER", "name": "Enchanter (%s)", "description": "Casts mass spell every turn" }, - { "id": "ENCHANTED", "name": "Enchanted (%s)", "description": "Affected by permanent spell" }, - { "id": "FIRE_SHIELD", "name": "Fire Shield (%d%)", "description": "Reflects melee damage" }, - { "id": "MAGIC_MIRROR", "name": "Magic Mirror (%d%)", "description": "Chance to reflect hostile spell" }, - { "id": "RANDOM_SPELLCASTER", "name": "Random spellcaster", "description": "Can cast random spell" }, - { "id": "DAEMON_SUMMONING", "name": "Summoner (%s)", "description": "Can rise creatures from corpses" } - ] -} diff --git a/config/gameConfig.json b/config/gameConfig.json index bd271c0d7..8bc34cd74 100644 --- a/config/gameConfig.json +++ b/config/gameConfig.json @@ -45,4 +45,10 @@ "config/heroes/conflux.json", "config/heroes/special.json" ], + + "bonuses" : + [ + "config/bonuses.json", + "config/bonuses_texts.json" + ] } diff --git a/lib/BattleState.h b/lib/BattleState.h index f8a6cbd26..9bf813743 100644 --- a/lib/BattleState.h +++ b/lib/BattleState.h @@ -79,8 +79,6 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb BattleInfo(); ~BattleInfo(){}; - ////////////////////////////////////////////////////////////////////////// - //void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const; ////////////////////////////////////////////////////////////////////////// CStack * getStackT(BattleHex tileID, bool onlyAlive = true); CStack * getStack(int stackID, bool onlyAlive = true); diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index de088993f..f221efbea 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -161,7 +161,7 @@ CArtHandler::~CArtHandler() { } -void CArtHandler::loadArtifacts(bool onlyTxt) +void CArtHandler::load(bool onlyTxt) { if (onlyTxt) return; // looks to be broken anyway... diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 9273db159..1286bd910 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -59,8 +59,8 @@ public: bool isBig () const; int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other - std::string nodeName() const override; - void addNewBonus(Bonus *b) override; + std::string nodeName() const OVERRIDE; + void addNewBonus(Bonus *b) OVERRIDE; virtual void levelUpArtifact (CArtifactInstance * art){}; @@ -198,7 +198,7 @@ public: std::set bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines. std::set growingArtifacts; - void loadArtifacts(bool onlyTxt); + void load(bool onlyTxt = false); /// load artifact from json structure void load(std::string objectID, const JsonNode & node); /// load one artifact from json config diff --git a/lib/CBonusTypeHandler.cpp b/lib/CBonusTypeHandler.cpp new file mode 100644 index 000000000..f347675f0 --- /dev/null +++ b/lib/CBonusTypeHandler.cpp @@ -0,0 +1,337 @@ +/* + * CBonusTypeHandler.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "CBonusTypeHandler.h" + +#include "JsonNode.h" +#include "Filesystem/CResourceLoader.h" +#include "Filesystem/ISimpleResourceLoader.h" + + +#include "VCMI_Lib.h" +#include "CCreatureHandler.h" +#include "CSpellHandler.h" + +///Helpers + +static inline void jsonSetString(const JsonNode& source, const std::string& name, std::string& dest) +{ + const JsonNode& val = source[name]; + if(!val.isNull()) + { + dest = val.String(); + } +} + +static inline void jsonSetBool(const JsonNode& source, const std::string& name, bool& dest) +{ + const JsonNode& val = source[name]; + if(!val.isNull()) + { + dest = val.Bool(); + } +} + +///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; + + tlog5 << "Parsing format " << format << std::endl; + + 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) + { + tlog2 << "Format error in: " << format <