2009-04-15 17:03:31 +03:00
/*
2023-05-01 19:29:53 +02:00
* Bonus . h , part of VCMI engine
2009-04-15 17:03:31 +03:00
*
* 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
*
*/
2017-07-13 10:26:03 +02:00
# pragma once
2023-04-27 23:47:29 +02:00
# include "../JsonNode.h"
2009-04-15 17:03:31 +03:00
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_BEGIN
2010-05-02 21:20:26 +03:00
struct Bonus ;
2017-07-04 13:24:46 +02:00
class IBonusBearer ;
2010-05-02 21:20:26 +03:00
class CBonusSystemNode ;
2010-07-12 13:20:25 +03:00
class ILimiter ;
2010-11-19 00:22:51 +02:00
class IPropagator ;
2017-09-09 07:43:53 +02:00
class IUpdater ;
2011-09-06 16:59:26 +03:00
class BonusList ;
2010-05-02 21:20:26 +03:00
2023-04-30 18:23:11 +02:00
using TBonusSubtype = int32_t ;
2023-04-17 23:11:16 +02:00
using TBonusListPtr = std : : shared_ptr < BonusList > ;
using TConstBonusListPtr = std : : shared_ptr < const BonusList > ;
using TLimiterPtr = std : : shared_ptr < ILimiter > ;
using TPropagatorPtr = std : : shared_ptr < IPropagator > ;
using TUpdaterPtr = std : : shared_ptr < IUpdater > ;
2013-07-02 15:08:30 +03:00
2018-03-12 07:20:18 +02:00
class DLL_LINKAGE CAddInfo : public std : : vector < si32 >
{
public :
2018-03-17 00:03:02 +02:00
enum { NONE = - 1 } ;
2018-03-12 07:20:18 +02:00
CAddInfo ( ) ;
CAddInfo ( si32 value ) ;
bool operator = = ( si32 value ) const ;
bool operator ! = ( si32 value ) const ;
2018-03-17 00:03:02 +02:00
si32 & operator [ ] ( size_type pos ) ;
2018-03-12 07:20:18 +02:00
si32 operator [ ] ( size_type pos ) const ;
std : : string toString ( ) const ;
JsonNode toJsonNode ( ) const ;
} ;
2011-12-14 00:23:17 +03:00
# define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();
2010-05-02 21:20:26 +03:00
# define BONUS_LIST \
BONUS_NAME ( NONE ) \
2012-07-16 19:18:02 +03:00
BONUS_NAME ( LEVEL_COUNTER ) /* for commander artifacts*/ \
2023-02-18 20:01:32 +02:00
BONUS_NAME ( MOVEMENT ) /*Subtype is 1 - land, 0 - sea*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( MORALE ) \
BONUS_NAME ( LUCK ) \
BONUS_NAME ( PRIMARY_SKILL ) /*uses subtype to pick skill; additional info if set: 1 - only melee, 2 - only distance*/ \
2023-02-19 13:40:28 +02:00
BONUS_NAME ( SIGHT_RADIUS ) \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( MANA_REGENERATION ) /*points per turn apart from normal (1 + mysticism)*/ \
BONUS_NAME ( FULL_MANA_REGENERATION ) /*all mana points are replenished every day*/ \
BONUS_NAME ( NONEVIL_ALIGNMENT_MIX ) /*good and neutral creatures can be mixed without morale penalty*/ \
BONUS_NAME ( SURRENDER_DISCOUNT ) /*%*/ \
2011-09-24 04:15:36 +03:00
BONUS_NAME ( STACKS_SPEED ) /*additional info - percent of speed bonus applied after direct bonuses; >0 - added, <0 - subtracted to this part*/ \
2015-10-26 17:30:11 +02:00
BONUS_NAME ( FLYING_MOVEMENT ) /*value - penalty percentage*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( SPELL_DURATION ) \
BONUS_NAME ( AIR_SPELL_DMG_PREMY ) \
BONUS_NAME ( EARTH_SPELL_DMG_PREMY ) \
BONUS_NAME ( FIRE_SPELL_DMG_PREMY ) \
BONUS_NAME ( WATER_SPELL_DMG_PREMY ) \
2015-10-26 17:30:11 +02:00
BONUS_NAME ( WATER_WALKING ) /*value - penalty percentage*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( NEGATE_ALL_NATURAL_IMMUNITIES ) \
BONUS_NAME ( STACK_HEALTH ) \
BONUS_NAME ( FIRE_SPELLS ) \
BONUS_NAME ( AIR_SPELLS ) \
BONUS_NAME ( WATER_SPELLS ) \
BONUS_NAME ( EARTH_SPELLS ) \
BONUS_NAME ( GENERATE_RESOURCE ) /*daily value, uses subtype (resource type)*/ \
2010-08-24 17:26:57 +03:00
BONUS_NAME ( CREATURE_GROWTH ) /*for legion artifacts: value - week growth bonus, subtype - monster level if aplicable*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( WHIRLPOOL_PROTECTION ) /*hero won't lose army when teleporting through whirlpool*/ \
BONUS_NAME ( SPELL ) /*hero knows spell, val - skill level (0 - 3), subtype - spell id*/ \
BONUS_NAME ( SPELLS_OF_LEVEL ) /*hero knows all spells of given level, val - skill level; subtype - level*/ \
2012-08-29 18:27:24 +03:00
BONUS_NAME ( BATTLE_NO_FLEEING ) /*for shackles of war*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( MAGIC_SCHOOL_SKILL ) /* //eg. for magic plains terrain, subtype: school of magic (0 - all, 1 - fire, 2 - air, 4 - water, 8 - earth), value - level*/ \
BONUS_NAME ( FREE_SHOOTING ) /*stacks can shoot even if otherwise blocked (sharpshooter's bow effect)*/ \
BONUS_NAME ( OPENING_BATTLE_SPELL ) /*casts a spell at expert level at beginning of battle, val - spell power, subtype - spell id*/ \
2023-02-19 22:55:18 +02:00
BONUS_NAME ( IMPROVED_NECROMANCY ) /* raise more powerful creatures: subtype - creature type raised, addInfo - [required necromancy level, required stack level], val - necromancy level for this purpose */ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( CREATURE_GROWTH_PERCENT ) /*increases growth of all units in all towns, val - percentage*/ \
BONUS_NAME ( FREE_SHIP_BOARDING ) /*movement points preserved with ship boarding and landing*/ \
BONUS_NAME ( FLYING ) \
BONUS_NAME ( SHOOTER ) \
BONUS_NAME ( CHARGE_IMMUNITY ) \
BONUS_NAME ( ADDITIONAL_ATTACK ) \
BONUS_NAME ( UNLIMITED_RETALIATIONS ) \
BONUS_NAME ( NO_MELEE_PENALTY ) \
BONUS_NAME ( JOUSTING ) /*for champions*/ \
2011-02-09 16:58:15 +02:00
BONUS_NAME ( HATE ) /*eg. angels hate devils, subtype - ID of hated creature, val - damage bonus percent */ \
2023-03-04 22:43:10 +02:00
BONUS_NAME ( KING ) /* val - required slayer bonus val to affect */ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( MAGIC_RESISTANCE ) /*in % (value)*/ \
BONUS_NAME ( CHANGES_SPELL_COST_FOR_ALLY ) /*in mana points (value) , eg. mage*/ \
BONUS_NAME ( CHANGES_SPELL_COST_FOR_ENEMY ) /*in mana points (value) , eg. pegasus */ \
2018-03-12 07:20:18 +02:00
BONUS_NAME ( SPELL_AFTER_ATTACK ) /* subtype - spell id, value - chance %, addInfo[0] - level, addInfo[1] -> [0 - all attacks, 1 - shot only, 2 - melee only] */ \
BONUS_NAME ( SPELL_BEFORE_ATTACK ) /* subtype - spell id, value - chance %, addInfo[0] - level, addInfo[1] -> [0 - all attacks, 1 - shot only, 2 - melee only] */ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( SPELL_RESISTANCE_AURA ) /*eg. unicorns, value - resistance bonus in % for adjacent creatures*/ \
2016-09-19 23:36:35 +02:00
BONUS_NAME ( LEVEL_SPELL_IMMUNITY ) /*creature is immune to all spell with level below or equal to value of this bonus */ \
2012-08-26 12:07:48 +03:00
BONUS_NAME ( BLOCK_MAGIC_ABOVE ) /*blocks casting spells of the level > value */ \
2015-09-29 13:44:03 +02:00
BONUS_NAME ( BLOCK_ALL_MAGIC ) /*blocks casting spells*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( TWO_HEX_ATTACK_BREATH ) /*eg. dragons*/ \
BONUS_NAME ( SPELL_DAMAGE_REDUCTION ) /*eg. golems; value - reduction in %, subtype - spell school; -1 - all, 0 - air, 1 - fire, 2 - water, 3 - earth*/ \
BONUS_NAME ( NO_WALL_PENALTY ) \
2020-01-18 11:02:17 +02:00
BONUS_NAME ( NON_LIVING ) /*eg. golems, cannot be rised or healed, only neutral morale */ \
2020-01-19 03:19:42 +02:00
BONUS_NAME ( RANDOM_SPELLCASTER ) /*eg. master genie, val - level*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( BLOCKS_RETALIATION ) /*eg. naga*/ \
BONUS_NAME ( SPELL_IMMUNITY ) /*subid - spell id*/ \
BONUS_NAME ( MANA_CHANNELING ) /*value in %, eg. familiar*/ \
2011-07-02 19:49:22 +03:00
BONUS_NAME ( SPELL_LIKE_ATTACK ) /*subtype - spell, value - spell level; range is taken from spell, but damage from creature; eg. magog*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( THREE_HEADED_ATTACK ) /*eg. cerberus*/ \
2023-01-14 19:03:56 +02:00
BONUS_NAME ( GENERAL_DAMAGE_PREMY ) \
2011-05-13 20:51:12 +03:00
BONUS_NAME ( FIRE_IMMUNITY ) /*subtype 0 - all, 1 - all except positive, 2 - only damage spells*/ \
BONUS_NAME ( WATER_IMMUNITY ) \
BONUS_NAME ( EARTH_IMMUNITY ) \
BONUS_NAME ( AIR_IMMUNITY ) \
2012-01-27 10:25:29 +03:00
BONUS_NAME ( MIND_IMMUNITY ) \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( FIRE_SHIELD ) \
BONUS_NAME ( UNDEAD ) \
BONUS_NAME ( HP_REGENERATION ) /*creature regenerates val HP every new round*/ \
BONUS_NAME ( MANA_DRAIN ) /*value - spell points per turn*/ \
BONUS_NAME ( LIFE_DRAIN ) \
BONUS_NAME ( DOUBLE_DAMAGE_CHANCE ) /*value in %, eg. dread knight*/ \
BONUS_NAME ( RETURN_AFTER_STRIKE ) \
2011-10-03 22:29:36 +03:00
BONUS_NAME ( SPELLCASTER ) /*subtype - spell id, value - level of school, additional info - weighted chance. use SPECIFIC_SPELL_POWER, CREATURE_SPELL_POWER or CREATURE_ENCHANT_POWER for calculating the power*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( CATAPULT ) \
BONUS_NAME ( ENEMY_DEFENCE_REDUCTION ) /*in % (value) eg. behemots*/ \
2023-02-15 01:05:36 +02:00
BONUS_NAME ( GENERAL_DAMAGE_REDUCTION ) /* shield / air shield effect, also armorer skill/petrify effect for subtype -1*/ \
2013-02-06 11:02:46 +03:00
BONUS_NAME ( GENERAL_ATTACK_REDUCTION ) /*eg. while stoned or blinded - in %,// subtype not used, use ONLY_MELEE_FIGHT / DISTANCE_FIGHT*/ \
2011-07-16 19:40:38 +03:00
BONUS_NAME ( DEFENSIVE_STANCE ) /* val - bonus to defense while defending */ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( ATTACKS_ALL_ADJACENT ) /*eg. hydra*/ \
BONUS_NAME ( MORE_DAMAGE_FROM_SPELL ) /*value - damage increase in %, subtype - spell id*/ \
BONUS_NAME ( FEAR ) \
BONUS_NAME ( FEARLESS ) \
BONUS_NAME ( NO_DISTANCE_PENALTY ) \
2011-10-09 10:20:23 +03:00
BONUS_NAME ( ENCHANTER ) /* for Enchanter spells, val - skill level, subtype - spell id, additionalInfo - cooldown */ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( HEALER ) \
BONUS_NAME ( SIEGE_WEAPON ) \
BONUS_NAME ( HYPNOTIZED ) \
2012-02-20 14:02:19 +03:00
BONUS_NAME ( NO_RETALIATION ) /*temporary bonus for basilisk, unicorn and scorpicore paralyze*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( ADDITIONAL_RETALIATION ) /*value - number of additional retaliations*/ \
BONUS_NAME ( MAGIC_MIRROR ) /* value - chance of redirecting in %*/ \
2011-09-06 16:59:26 +03:00
BONUS_NAME ( ALWAYS_MINIMUM_DAMAGE ) /*unit does its minimum damage from range; subtype: -1 - any attack, 0 - melee, 1 - ranged, value: additional damage penalty (it'll subtracted from dmg), additional info - multiplicative anti-bonus for dmg in % [eg 20 means that creature will inflict 80% of normal minimal dmg]*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( ALWAYS_MAXIMUM_DAMAGE ) /*eg. bless effect, subtype: -1 - any attack, 0 - melee, 1 - ranged, value: additional damage, additional info - multiplicative bonus for dmg in %*/ \
BONUS_NAME ( ATTACKS_NEAREST_CREATURE ) /*while in berserk*/ \
BONUS_NAME ( IN_FRENZY ) /*value - level*/ \
BONUS_NAME ( SLAYER ) /*value - level*/ \
BONUS_NAME ( FORGETFULL ) /*forgetfulness spell effect, value - level*/ \
2012-02-20 14:02:19 +03:00
BONUS_NAME ( NOT_ACTIVE ) /* subtype - spell ID (paralyze, blind, stone gaze) for graphical effect*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( NO_LUCK ) /*eg. when fighting on cursed ground*/ \
2010-06-07 08:28:12 +03:00
BONUS_NAME ( NO_MORALE ) /*eg. when fighting on cursed ground*/ \
2010-07-06 10:32:40 +03:00
BONUS_NAME ( DARKNESS ) /*val = radius */ \
2017-09-17 05:28:15 +02:00
BONUS_NAME ( SPECIAL_SPELL_LEV ) /*subtype = id, val = value per level in percent*/ \
2023-02-19 01:29:23 +02:00
BONUS_NAME ( SPELL_DAMAGE ) /*val = value, now works for sorcery*/ \
2010-07-17 16:11:12 +03:00
BONUS_NAME ( SPECIFIC_SPELL_DAMAGE ) /*subtype = id of spell, val = value*/ \
2010-07-06 10:32:40 +03:00
BONUS_NAME ( SPECIAL_PECULIAR_ENCHANT ) /*blesses and curses with id = val dependent on unit's level, subtype = 0 or 1 for Coronius*/ \
2017-09-12 10:56:59 +02:00
BONUS_NAME ( SPECIAL_UPGRADE ) /*subtype = base, additionalInfo = target */ \
2011-02-02 20:49:48 +02:00
BONUS_NAME ( DRAGON_NATURE ) \
2011-02-12 18:21:48 +02:00
BONUS_NAME ( CREATURE_DAMAGE ) /*subtype 0 = both, 1 = min, 2 = max*/ \
2011-04-12 11:59:18 +03:00
BONUS_NAME ( EXP_MULTIPLIER ) /* val - percent of additional exp gained by stack/commander (base value 100)*/ \
2011-04-23 20:10:54 +03:00
BONUS_NAME ( SHOTS ) \
2011-04-25 12:03:13 +03:00
BONUS_NAME ( DEATH_STARE ) /*subtype 0 - gorgon, 1 - commander*/ \
BONUS_NAME ( POISON ) /*val - max health penalty from poison possible*/ \
2011-05-13 12:02:16 +03:00
BONUS_NAME ( BIND_EFFECT ) /*doesn't do anything particular, works as a marker)*/ \
2011-05-13 20:51:12 +03:00
BONUS_NAME ( ACID_BREATH ) /*additional val damage per creature after attack, additional info - chance in percent*/ \
BONUS_NAME ( RECEPTIVE ) /*accepts friendly spells even with immunity*/ \
2011-05-15 09:37:57 +03:00
BONUS_NAME ( DIRECT_DAMAGE_IMMUNITY ) /*direct damage spells, that is*/ \
2011-07-08 10:00:11 +03:00
BONUS_NAME ( CASTS ) /*how many times creature can cast activated spell*/ \
2015-09-21 11:19:35 +02:00
BONUS_NAME ( SPECIFIC_SPELL_POWER ) /* value used for Thunderbolt and Resurrection cast by units, subtype - spell id */ \
2011-07-08 10:00:11 +03:00
BONUS_NAME ( CREATURE_SPELL_POWER ) /* value per unit, divided by 100 (so faerie Dragons have 800)*/ \
2015-09-21 11:19:35 +02:00
BONUS_NAME ( CREATURE_ENCHANT_POWER ) /* total duration of spells cast by creature */ \
2012-12-01 21:30:03 +03:00
BONUS_NAME ( ENCHANTED ) /* permanently enchanted with spell subID of level = val, if val > 3 then spell is mass and has level of val-3*/ \
2012-04-04 20:41:55 +03:00
BONUS_NAME ( REBIRTH ) /* val - percent of life restored, subtype = 0 - regular, 1 - at least one unit (sacred Phoenix) */ \
BONUS_NAME ( ADDITIONAL_UNITS ) /*val of units with id = subtype will be added to hero's army at the beginning of battle */ \
2012-04-22 16:28:46 +03:00
BONUS_NAME ( SPOILS_OF_WAR ) /*val * 10^-6 * gained exp resources of subtype will be given to hero after battle*/ \
2015-02-05 13:59:08 +02:00
BONUS_NAME ( BLOCK ) \
BONUS_NAME ( DISGUISED ) /* subtype - spell level */ \
2015-10-15 10:44:59 +02:00
BONUS_NAME ( VISIONS ) /* subtype - spell level */ \
BONUS_NAME ( NO_TERRAIN_PENALTY ) /* subtype - terrain type */ \
2017-01-29 12:50:37 +02:00
BONUS_NAME ( SOUL_STEAL ) /*val - number of units gained per enemy killed, subtype = 0 - gained units survive after battle, 1 - they do not*/ \
BONUS_NAME ( TRANSMUTATION ) /*val - chance to trigger in %, subtype = 0 - resurrection based on HP, 1 - based on unit count, additional info - target creature ID (attacker default)*/ \
BONUS_NAME ( SUMMON_GUARDIANS ) /*val - amount in % of stack count, subtype = creature ID*/ \
2023-02-21 01:47:40 +02:00
BONUS_NAME ( CATAPULT_EXTRA_SHOTS ) /*val - power of catapult effect, requires CATAPULT bonus to work*/ \
2017-02-04 11:33:45 +02:00
BONUS_NAME ( RANGED_RETALIATION ) /*allows shooters to perform ranged retaliation*/ \
2017-09-09 21:27:22 +02:00
BONUS_NAME ( BLOCKS_RANGED_RETALIATION ) /*disallows ranged retaliation for shooter unit, BLOCKS_RETALIATION bonus is for melee retaliation only*/ \
2017-08-28 10:09:27 +02:00
BONUS_NAME ( MANUAL_CONTROL ) /* manually control warmachine with id = subtype, chance = val */ \
2017-09-04 23:32:24 +02:00
BONUS_NAME ( WIDE_BREATH ) /* initial desigh: dragon breath affecting multiple nearby hexes */ \
BONUS_NAME ( FIRST_STRIKE ) /* first counterattack, then attack if possible */ \
BONUS_NAME ( SYNERGY_TARGET ) /* dummy skill for alternative upgrades mod */ \
BONUS_NAME ( SHOOTS_ALL_ADJACENT ) /* H4 Cyclops-like shoot (attacks all hexes neighboring with target) without spell-like mechanics */ \
2017-09-06 00:03:32 +02:00
BONUS_NAME ( BLOCK_MAGIC_BELOW ) /*blocks casting spells of the level < value */ \
2017-11-13 02:59:41 +02:00
BONUS_NAME ( DESTRUCTION ) /*kills extra units after hit, subtype = 0 - kill percentage of units, 1 - kill amount, val = chance in percent to trigger, additional info - amount/percentage to kill*/ \
2019-03-17 20:48:47 +02:00
BONUS_NAME ( SPECIAL_CRYSTAL_GENERATION ) /*crystal dragon crystal generation*/ \
2019-05-04 05:42:55 +02:00
BONUS_NAME ( NO_SPELLCAST_BY_DEFAULT ) /*spellcast will not be default attack option for this creature*/ \
2020-01-19 02:43:08 +02:00
BONUS_NAME ( GARGOYLE ) /* gargoyle is special than NON_LIVING, cannot be rised or healed */ \
2021-02-13 17:02:42 +02:00
BONUS_NAME ( SPECIAL_ADD_VALUE_ENCHANT ) /*specialty spell like Aenin has, increased effect of spell, additionalInfo = value to add*/ \
BONUS_NAME ( SPECIAL_FIXED_VALUE_ENCHANT ) /*specialty spell like Melody has, constant spell effect (i.e. 3 luck), additionalInfo = value to fix.*/ \
2023-01-12 17:27:21 +02:00
BONUS_NAME ( TOWN_MAGIC_WELL ) /*one-time pseudo-bonus to implement Magic Well in the town*/ \
2023-01-15 15:54:41 +02:00
BONUS_NAME ( LIMITED_SHOOTING_RANGE ) /*limits range of shooting creatures, doesn't adjust any other mechanics (half vs full damage etc). val - range in hexes, additional info - optional new range for broken arrow mechanic */ \
2023-01-28 20:19:58 +02:00
BONUS_NAME ( LEARN_BATTLE_SPELL_CHANCE ) /*skill-agnostic eagle eye chance. subtype = 0 - from enemy, 1 - TODO: from entire battlefield*/ \
BONUS_NAME ( LEARN_BATTLE_SPELL_LEVEL_LIMIT ) /*skill-agnostic eagle eye limit, subtype - school (-1 for all), others TODO*/ \
2023-02-13 01:16:42 +02:00
BONUS_NAME ( PERCENTAGE_DAMAGE_BOOST ) /*skill-agnostic archery and offence, subtype is 0 for offence and 1 for archery*/ \
2023-02-15 01:05:36 +02:00
BONUS_NAME ( LEARN_MEETING_SPELL_LIMIT ) /*skill-agnostic scholar, subtype is -1 for all, TODO for others (> 0)*/ \
2023-02-15 21:01:38 +02:00
BONUS_NAME ( ROUGH_TERRAIN_DISCOUNT ) /*skill-agnostic pathfinding*/ \
2023-02-18 17:39:54 +02:00
BONUS_NAME ( WANDERING_CREATURES_JOIN_BONUS ) /*skill-agnostic diplomacy*/ \
2023-02-19 02:44:47 +02:00
BONUS_NAME ( BEFORE_BATTLE_REPOSITION ) /*skill-agnostic tactics, bonus for allowing tactics*/ \
BONUS_NAME ( BEFORE_BATTLE_REPOSITION_BLOCK ) /*skill-agnostic tactics, bonus for blocking opposite tactics. For now donble side tactics is TODO.*/ \
2023-02-19 21:09:10 +02:00
BONUS_NAME ( HERO_EXPERIENCE_GAIN_PERCENT ) /*skill-agnostic learning, and we can use it as a global effect also*/ \
2023-02-19 22:55:18 +02:00
BONUS_NAME ( UNDEAD_RAISE_PERCENTAGE ) /*Percentage of killed enemy creatures to be raised after battle as undead*/ \
2023-02-26 00:19:39 +02:00
BONUS_NAME ( MANA_PER_KNOWLEDGE ) /*Percentage rate of translating 10 hero knowledge to mana, used to intelligence and global bonus*/ \
BONUS_NAME ( HERO_GRANTS_ATTACKS ) /*If hero can grant additional attacks to creature, value is number of attacks, subtype is creatureID*/ \
BONUS_NAME ( BONUS_DAMAGE_PERCENTAGE ) /*If hero can grant conditional damage to creature, value is percentage, subtype is creatureID*/ \
BONUS_NAME ( BONUS_DAMAGE_CHANCE ) /*If hero can grant additional damage to creature, value is chance, subtype is creatureID*/ \
2023-02-27 12:57:21 +02:00
BONUS_NAME ( MAX_LEARNABLE_SPELL_LEVEL ) /*This can work as wisdom before. val = max learnable spell level*/ \
2015-10-15 11:20:53 +02:00
/* end of list */
2016-01-31 17:01:58 +02:00
2010-05-02 21:20:26 +03:00
2012-08-23 21:46:43 +03:00
# define BONUS_SOURCE_LIST \
BONUS_SOURCE ( ARTIFACT ) \
BONUS_SOURCE ( ARTIFACT_INSTANCE ) \
BONUS_SOURCE ( OBJECT ) \
BONUS_SOURCE ( CREATURE_ABILITY ) \
BONUS_SOURCE ( TERRAIN_NATIVE ) \
BONUS_SOURCE ( TERRAIN_OVERLAY ) \
BONUS_SOURCE ( SPELL_EFFECT ) \
BONUS_SOURCE ( TOWN_STRUCTURE ) \
BONUS_SOURCE ( HERO_BASE_SKILL ) \
BONUS_SOURCE ( SECONDARY_SKILL ) \
BONUS_SOURCE ( HERO_SPECIAL ) \
BONUS_SOURCE ( ARMY ) \
BONUS_SOURCE ( CAMPAIGN_BONUS ) \
BONUS_SOURCE ( SPECIAL_WEEK ) \
BONUS_SOURCE ( STACK_EXPERIENCE ) \
BONUS_SOURCE ( COMMANDER ) /*TODO: consider using simply STACK_INSTANCE */ \
2023-02-19 20:42:51 +02:00
BONUS_SOURCE ( GLOBAL ) /*used for base bonuses which all heroes or all stacks should have*/ \
2012-08-23 21:46:43 +03:00
BONUS_SOURCE ( OTHER ) /*used for defensive stance and default value of spell level limit*/
# define BONUS_VALUE_LIST \
BONUS_VALUE ( ADDITIVE_VALUE ) \
BONUS_VALUE ( BASE_NUMBER ) \
BONUS_VALUE ( PERCENT_TO_ALL ) \
BONUS_VALUE ( PERCENT_TO_BASE ) \
2023-02-13 10:57:11 +02:00
BONUS_VALUE ( PERCENT_TO_SOURCE ) /*Adds value only to bonuses with same source*/ \
2023-02-15 21:19:35 +02:00
BONUS_VALUE ( PERCENT_TO_TARGET_TYPE ) /*Adds value only to bonuses with SourceType target*/ \
2016-09-19 23:36:35 +02:00
BONUS_VALUE ( INDEPENDENT_MAX ) /*used for SPELL bonus */ \
2012-08-23 21:46:43 +03:00
BONUS_VALUE ( INDEPENDENT_MIN ) //used for SECONDARY_SKILL_PREMY bonus
2011-09-24 04:15:36 +03:00
/// Struct for handling bonuses of several types. Can be transferred to any hero
2016-09-19 23:36:35 +02:00
struct DLL_LINKAGE Bonus : public std : : enable_shared_from_this < Bonus >
2009-02-04 15:40:54 +02:00
{
2009-04-04 01:34:31 +03:00
enum BonusType
{
2010-05-02 21:20:26 +03:00
# define BONUS_NAME(x) x,
BONUS_LIST
# undef BONUS_NAME
} ;
enum BonusDuration //when bonus is automatically removed
{
PERMANENT = 1 ,
2012-09-15 22:16:16 +03:00
ONE_BATTLE = 2 , //at the end of battle
2010-05-02 21:20:26 +03:00
ONE_DAY = 4 , //at the end of day
ONE_WEEK = 8 , //at the end of week (bonus lasts till the end of week, thats NOT 7 days
N_TURNS = 16 , //used during battles, after battle bonus is always removed
N_DAYS = 32 ,
2016-09-30 00:57:33 +02:00
UNTIL_BEING_ATTACKED = 64 , /*removed after attack and counterattacks are performed*/
2011-01-18 19:23:31 +02:00
UNTIL_ATTACK = 128 , /*removed after attack and counterattacks are performed*/
2012-07-16 19:18:02 +03:00
STACK_GETS_TURN = 256 , /*removed when stack gets its turn - used for defensive stance*/
COMMANDER_KILLED = 512
2010-05-02 21:20:26 +03:00
} ;
enum BonusSource
{
2012-08-23 21:46:43 +03:00
# define BONUS_SOURCE(x) x,
BONUS_SOURCE_LIST
# undef BONUS_SOURCE
2023-02-13 10:57:11 +02:00
NUM_BONUS_SOURCE /*This is a dummy value, which will be always last*/
2010-05-02 21:20:26 +03:00
} ;
enum LimitEffect
{
2012-09-15 22:16:16 +03:00
NO_LIMIT = 0 ,
2010-05-02 21:20:26 +03:00
ONLY_DISTANCE_FIGHT = 1 , ONLY_MELEE_FIGHT , //used to mark bonuses for attack/defense primary skills from spells like Precision (distance only)
} ;
enum ValueType
{
2012-08-23 21:46:43 +03:00
# define BONUS_VALUE(x) x,
BONUS_VALUE_LIST
# undef BONUS_VALUE
2009-04-04 01:34:31 +03:00
} ;
2009-02-04 15:40:54 +02:00
2023-03-13 23:26:44 +02:00
ui16 duration = PERMANENT ; //uses BonusDuration values
si16 turnsRemain = 0 ; //used if duration is N_TURNS, N_DAYS or ONE_WEEK
2010-05-02 21:20:26 +03:00
2023-03-13 23:26:44 +02:00
BonusType type = NONE ; //uses BonusType values - says to what is this bonus - 1 byte
TBonusSubtype subtype = - 1 ; //-1 if not applicable - 4 bytes
2010-05-02 21:20:26 +03:00
2023-03-13 23:26:44 +02:00
BonusSource source = OTHER ; //source type" uses BonusSource values - what gave that bonus
2023-02-15 21:19:35 +02:00
BonusSource targetSourceType ; //Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE.
2023-03-13 23:26:44 +02:00
si32 val = 0 ;
ui32 sid = 0 ; //source id: id of object/artifact/spell
ValueType valType = ADDITIVE_VALUE ;
2018-03-27 09:54:58 +02:00
std : : string stacking ; // bonuses with the same stacking value don't stack (e.g. Angel/Archangel morale bonus)
2010-05-12 05:32:56 +03:00
2018-03-12 07:20:18 +02:00
CAddInfo additionalInfo ;
2023-03-13 23:26:44 +02:00
LimitEffect effectRange = NO_LIMIT ; //if not NO_LIMIT, bonus will be omitted by default
2010-05-02 21:20:26 +03:00
2013-01-20 15:06:18 +03:00
TLimiterPtr limiter ;
2012-03-06 19:59:55 +03:00
TPropagatorPtr propagator ;
2017-09-09 07:43:53 +02:00
TUpdaterPtr updater ;
2021-09-12 13:30:54 +02:00
TUpdaterPtr propagationUpdater ;
2010-07-12 13:20:25 +03:00
2012-09-15 22:16:16 +03:00
std : : string description ;
2009-02-04 15:40:54 +02:00
2021-01-14 00:02:13 +02:00
Bonus ( BonusDuration Duration , BonusType Type , BonusSource Src , si32 Val , ui32 ID , std : : string Desc , si32 Subtype = - 1 ) ;
Bonus ( BonusDuration Duration , BonusType Type , BonusSource Src , si32 Val , ui32 ID , si32 Subtype = - 1 , ValueType ValType = ADDITIVE_VALUE ) ;
2023-03-13 23:26:44 +02:00
Bonus ( ) = default ;
2010-02-10 04:56:00 +02:00
2009-02-04 15:40:54 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2017-07-31 15:35:42 +02:00
h & duration ;
h & type ;
h & subtype ;
h & source ;
h & val ;
h & sid ;
h & description ;
2022-06-20 16:39:50 +02:00
h & additionalInfo ;
2017-07-31 15:35:42 +02:00
h & turnsRemain ;
h & valType ;
2022-06-20 16:39:50 +02:00
h & stacking ;
2017-07-31 15:35:42 +02:00
h & effectRange ;
h & limiter ;
h & propagator ;
2022-06-20 16:39:50 +02:00
h & updater ;
h & propagationUpdater ;
2023-02-15 21:19:35 +02:00
h & targetSourceType ;
2009-02-04 15:40:54 +02:00
}
2009-02-06 13:15:39 +02:00
2016-09-19 23:36:35 +02:00
template < typename Ptr >
static bool compareByAdditionalInfo ( const Ptr & a , const Ptr & b )
2011-09-06 16:59:26 +03:00
{
return a - > additionalInfo < b - > additionalInfo ;
}
2015-04-13 09:24:32 +02:00
static bool NDays ( const Bonus * hb )
{
return hb - > duration & Bonus : : N_DAYS ;
}
static bool NTurns ( const Bonus * hb )
{
return hb - > duration & Bonus : : N_TURNS ;
2016-01-31 17:01:58 +02:00
}
2010-11-19 00:06:56 +02:00
static bool OneDay ( const Bonus * hb )
2010-05-02 21:20:26 +03:00
{
2010-11-19 00:06:56 +02:00
return hb - > duration & Bonus : : ONE_DAY ;
2010-05-02 21:20:26 +03:00
}
2010-11-19 00:06:56 +02:00
static bool OneWeek ( const Bonus * hb )
2010-05-02 21:20:26 +03:00
{
2010-11-19 00:06:56 +02:00
return hb - > duration & Bonus : : ONE_WEEK ;
2010-05-02 21:20:26 +03:00
}
2010-11-19 00:06:56 +02:00
static bool OneBattle ( const Bonus * hb )
2009-02-06 13:15:39 +02:00
{
2010-11-19 00:06:56 +02:00
return hb - > duration & Bonus : : ONE_BATTLE ;
2009-02-06 13:15:39 +02:00
}
2015-04-13 09:24:32 +02:00
static bool Permanent ( const Bonus * hb )
{
return hb - > duration & Bonus : : PERMANENT ;
}
2011-01-18 19:23:31 +02:00
static bool UntilGetsTurn ( const Bonus * hb )
{
return hb - > duration & Bonus : : STACK_GETS_TURN ;
}
2010-11-19 00:06:56 +02:00
static bool UntilAttack ( const Bonus * hb )
2009-02-06 13:15:39 +02:00
{
2010-11-19 00:06:56 +02:00
return hb - > duration & Bonus : : UNTIL_ATTACK ;
2009-02-06 13:15:39 +02:00
}
2010-11-19 00:06:56 +02:00
static bool UntilBeingAttacked ( const Bonus * hb )
2009-02-06 13:15:39 +02:00
{
2016-09-30 00:57:33 +02:00
return hb - > duration & Bonus : : UNTIL_BEING_ATTACKED ;
2009-02-06 13:15:39 +02:00
}
2012-07-16 19:18:02 +03:00
static bool UntilCommanderKilled ( const Bonus * hb )
{
return hb - > duration & Bonus : : COMMANDER_KILLED ;
}
2010-08-04 14:18:13 +03:00
inline bool operator = = ( const BonusType & cf ) const
{
return type = = cf ;
}
2010-07-08 22:10:26 +03:00
inline void operator + = ( const ui32 Val ) //no return
{
val + = Val ;
}
2021-01-14 00:02:13 +02:00
STRONG_INLINE static ui32 getSid32 ( ui32 high , ui32 low )
{
return ( high < < 16 ) + low ;
}
2010-02-10 04:56:00 +02:00
2023-04-09 03:36:16 +02:00
STRONG_INLINE static ui32 getHighFromSid32 ( ui32 sid )
{
return sid > > 16 ;
}
STRONG_INLINE static ui32 getLowFromSid32 ( ui32 sid )
{
return sid & 0x0000FFFF ;
}
2023-04-16 19:42:56 +02:00
std : : string Description ( std : : optional < si32 > customValue = { } ) const ;
2017-09-11 08:21:24 +02:00
JsonNode toJsonNode ( ) const ;
2017-09-15 00:48:34 +02:00
std : : string nameForBonus ( ) const ; // generate suitable name for bonus - e.g. for storing in json struct
2010-11-20 02:03:31 +02:00
2023-03-13 23:26:44 +02:00
std : : shared_ptr < Bonus > addLimiter ( const TLimiterPtr & Limiter ) ; //returns this for convenient chain-calls
std : : shared_ptr < Bonus > addPropagator ( const TPropagatorPtr & Propagator ) ; //returns this for convenient chain-calls
std : : shared_ptr < Bonus > addUpdater ( const TUpdaterPtr & Updater ) ; //returns this for convenient chain-calls
2009-02-06 13:15:39 +02:00
} ;
2010-02-10 04:56:00 +02:00
2011-12-14 00:23:17 +03:00
DLL_LINKAGE std : : ostream & operator < < ( std : : ostream & out , const Bonus & bonus ) ;
2010-07-12 13:20:25 +03:00
2013-02-16 17:03:47 +03:00
extern DLL_LINKAGE const std : : map < std : : string , Bonus : : BonusType > bonusNameMap ;
extern DLL_LINKAGE const std : : map < std : : string , Bonus : : ValueType > bonusValueMap ;
2014-02-17 10:36:03 +03:00
extern DLL_LINKAGE const std : : map < std : : string , Bonus : : BonusSource > bonusSourceMap ;
extern DLL_LINKAGE const std : : map < std : : string , ui16 > bonusDurationMap ;
extern DLL_LINKAGE const std : : map < std : : string , Bonus : : LimitEffect > bonusLimitEffect ;
2023-03-05 02:16:05 +02:00
extern DLL_LINKAGE const std : : set < std : : string > deprecatedBonusSet ;
2014-02-17 10:36:03 +03:00
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_END