2009-04-15 17:03:31 +03:00
/*
* HeroBonus . h , 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
*
*/
2017-07-13 10:26:03 +02:00
# pragma once
# include "GameConstants.h"
2017-09-11 08:21:24 +02:00
# include "JsonNode.h"
2009-04-15 17:03:31 +03:00
2010-07-12 13:20:25 +03:00
class CCreature ;
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
2015-12-29 04:43:33 +02:00
typedef std : : shared_ptr < BonusList > TBonusListPtr ;
2020-10-01 07:55:41 +02:00
typedef std : : shared_ptr < const BonusList > TConstBonusListPtr ;
2015-12-29 04:43:33 +02:00
typedef std : : shared_ptr < ILimiter > TLimiterPtr ;
typedef std : : shared_ptr < IPropagator > TPropagatorPtr ;
2017-09-09 07:43:53 +02:00
typedef std : : shared_ptr < IUpdater > TUpdaterPtr ;
2010-05-02 21:20:26 +03:00
typedef std : : set < CBonusSystemNode * > TNodes ;
typedef std : : set < const CBonusSystemNode * > TCNodes ;
2010-11-20 19:36:02 +02:00
typedef std : : vector < CBonusSystemNode * > TNodesVector ;
2013-07-02 15:08:30 +03:00
class CSelector : std : : function < bool ( const Bonus * ) >
{
typedef std : : function < bool ( const Bonus * ) > TBase ;
public :
CSelector ( ) { }
template < typename T >
2016-01-31 17:01:58 +02:00
CSelector ( const T & t , //SFINAE trick -> include this c-tor in overload resolution only if parameter is class
2013-07-02 15:08:30 +03:00
//(includes functors, lambdas) or function. Without that VC is going mad about ambiguities.
typename std : : enable_if < boost : : mpl : : or_ < std : : is_class < T > , std : : is_function < T > > : : value > : : type * dummy = nullptr )
: TBase ( t )
{ }
CSelector ( std : : nullptr_t )
{ }
CSelector And ( CSelector rhs ) const
{
//lambda may likely outlive "this" (it can be even a temporary) => we copy the OBJECT (not pointer)
auto thisCopy = * this ;
return [ thisCopy , rhs ] ( const Bonus * b ) mutable { return thisCopy ( b ) & & rhs ( b ) ; } ;
}
CSelector Or ( CSelector rhs ) const
{
auto thisCopy = * this ;
2013-07-03 23:18:41 +03:00
return [ thisCopy , rhs ] ( const Bonus * b ) mutable { return thisCopy ( b ) | | rhs ( b ) ; } ;
2013-07-02 15:08:30 +03:00
}
bool operator ( ) ( const Bonus * b ) const
{
return TBase : : operator ( ) ( b ) ;
}
operator bool ( ) const
{
return ! ! static_cast < const TBase & > ( * this ) ;
}
} ;
2010-05-02 21:20:26 +03:00
2017-07-20 06:08:49 +02:00
class DLL_LINKAGE CBonusProxy
2017-07-04 13:24:46 +02:00
{
public :
CBonusProxy ( const IBonusBearer * Target , CSelector Selector ) ;
2017-07-20 06:08:49 +02:00
CBonusProxy ( const CBonusProxy & other ) ;
CBonusProxy ( CBonusProxy & & other ) ;
CBonusProxy & operator = ( CBonusProxy & & other ) ;
CBonusProxy & operator = ( const CBonusProxy & other ) ;
2017-07-04 13:24:46 +02:00
const BonusList * operator - > ( ) const ;
2020-11-11 21:43:40 +02:00
TConstBonusListPtr getBonusList ( ) const ;
protected :
2017-07-04 13:24:46 +02:00
CSelector selector ;
2020-11-11 21:43:40 +02:00
const IBonusBearer * target ;
mutable int64_t bonusListCachedLast ;
2022-04-04 09:16:32 +02:00
mutable TConstBonusListPtr bonusList [ 2 ] ;
mutable int currentBonusListIndex ;
mutable boost : : mutex swapGuard ;
void swapBonusList ( TConstBonusListPtr other ) const ;
2017-07-04 13:24:46 +02:00
} ;
2010-05-02 21:20:26 +03:00
2020-11-11 21:43:40 +02:00
class DLL_LINKAGE CTotalsProxy : public CBonusProxy
2020-06-28 15:19:27 +02:00
{
public :
CTotalsProxy ( const IBonusBearer * Target , CSelector Selector , int InitialValue ) ;
CTotalsProxy ( const CTotalsProxy & other ) ;
CTotalsProxy ( CTotalsProxy & & other ) = delete ;
CTotalsProxy & operator = ( const CTotalsProxy & other ) ;
CTotalsProxy & operator = ( CTotalsProxy & & other ) = delete ;
int getMeleeValue ( ) const ;
int getRangedValue ( ) const ;
int getValue ( ) const ;
2020-11-11 21:43:40 +02:00
/**
Returns total value of all selected bonuses and sets bonusList as a pointer to the list of selected bonuses
@ param bonusList is the out list of all selected bonuses
@ return total value of all selected bonuses and 0 otherwise
*/
int getValueAndList ( TConstBonusListPtr & bonusList ) const ;
2020-06-28 15:19:27 +02:00
private :
int initialValue ;
2020-11-11 21:43:40 +02:00
mutable int64_t valueCachedLast ;
2020-06-28 15:19:27 +02:00
mutable int value ;
mutable int64_t meleeCachedLast ;
mutable int meleeValue ;
mutable int64_t rangedCachedLast ;
mutable int rangedValue ;
} ;
class DLL_LINKAGE CCheckProxy
{
public :
CCheckProxy ( const IBonusBearer * Target , CSelector Selector ) ;
CCheckProxy ( const CCheckProxy & other ) ;
2022-05-19 14:14:50 +02:00
CCheckProxy & operator = ( const CCheckProxy & other ) = default ;
2020-06-28 15:19:27 +02:00
bool getHasBonus ( ) const ;
private :
const IBonusBearer * target ;
CSelector selector ;
mutable int64_t cachedLast ;
mutable bool hasBonus ;
} ;
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*/ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( MOVEMENT ) /*both water/land*/ \
BONUS_NAME ( LAND_MOVEMENT ) \
BONUS_NAME ( SEA_MOVEMENT ) \
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*/ \
2016-01-31 17:01:58 +02:00
BONUS_NAME ( SIGHT_RADIOUS ) /*the correct word is RADIUS, but this one's already used in mods */ \
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 ( SECONDARY_SKILL_PREMY ) /*%*/ \
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 ( BLOCK_MORALE ) \
BONUS_NAME ( BLOCK_LUCK ) \
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*/ \
2018-03-17 10:46:16 +02:00
BONUS_NAME ( IMPROVED_NECROMANCY ) /* raise more powerful creatures: subtype - creature type raised, addInfo - [required necromancy level, required stack level] */ \
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 ( NO_TYPE ) \
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 */ \
2010-05-02 21:20:26 +03:00
BONUS_NAME ( KING1 ) \
BONUS_NAME ( KING2 ) \
BONUS_NAME ( KING3 ) \
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*/ \
2011-07-08 10:00:11 +03:00
BONUS_NAME ( DAEMON_SUMMONING ) /*pit lord, subtype - type of creatures, val - hp per unit*/ \
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 ( FULL_HP_REGENERATION ) /*first creature regenerates all HP every new round; subtype 0 - animation 4 (trolllike), 1 - animation 47 (wightlike)*/ \
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 ) \
BONUS_NAME ( SELF_MORALE ) /*eg. minotaur*/ \
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*/ \
BONUS_NAME ( GENERAL_DAMAGE_REDUCTION ) /* shield / air shield effect */ \
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 ) \
BONUS_NAME ( SELF_LUCK ) /*halfling*/ \
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-14 23:25:43 +02:00
BONUS_NAME ( SPECIAL_SECONDARY_SKILL ) /*subtype = id, val = value per level in percent*/ \
2017-09-17 05:28:15 +02:00
BONUS_NAME ( SPECIAL_SPELL_LEV ) /*subtype = id, val = value per level in percent*/ \
2010-07-17 16:11:12 +03:00
BONUS_NAME ( SPELL_DAMAGE ) /*val = value*/ \
BONUS_NAME ( SPECIFIC_SPELL_DAMAGE ) /*subtype = id of spell, val = value*/ \
2010-07-06 10:32:40 +03:00
BONUS_NAME ( SPECIAL_BLESS_DAMAGE ) /*val = spell (bless), additionalInfo = value per level in percent*/ \
BONUS_NAME ( MAXED_SPELL ) /*val = id*/ \
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*/ \
2017-02-01 14:38:28 +02:00
BONUS_NAME ( CATAPULT_EXTRA_SHOTS ) /*val - number of additional shots, 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*/ \
BONUS_NAME ( SECONDARY_SKILL_VAL2 ) /*for secondary skills that have multiple effects, like eagle eye (max level and chance)*/ \
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.*/ \
2021-02-01 17:35:15 +02:00
BONUS_NAME ( TOWN_MAGIC_WELL ) /*one-time pseudo-bonus to implement Magic Well in the town*/ \
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 */ \
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 ) \
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
{
2013-02-26 18:07:21 +03:00
enum { EVERY_TYPE = - 1 } ;
2013-02-26 12:36:21 +03: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
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)
2011-02-21 06:13:00 +02:00
ONLY_ENEMY_ARMY
2010-05-02 21:20:26 +03:00
} ;
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
2011-01-18 19:23:31 +02:00
ui16 duration ; //uses BonusDuration values
2015-11-20 11:11:35 +02:00
si16 turnsRemain ; //used if duration is N_TURNS, N_DAYS or ONE_WEEK
2010-05-02 21:20:26 +03:00
2013-02-16 17:03:47 +03:00
BonusType type ; //uses BonusType values - says to what is this bonus - 1 byte
2010-05-02 21:20:26 +03:00
TBonusSubtype subtype ; //-1 if not applicable - 4 bytes
2013-02-02 01:04:25 +03:00
BonusSource source ; //source type" uses BonusSource values - what gave that bonus
2010-05-12 05:32:56 +03:00
si32 val ;
2011-02-20 20:32:39 +02:00
ui32 sid ; //source id: id of object/artifact/spell
2013-02-02 01:04:25 +03:00
ValueType valType ;
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 ;
2013-02-02 01:04:25 +03:00
LimitEffect effectRange ; //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 ) ;
2010-07-13 08:25:40 +03:00
Bonus ( ) ;
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 ;
2018-03-12 07:20:18 +02:00
if ( version > = 783 )
{
h & additionalInfo ;
}
else
{
additionalInfo . resize ( 1 , - 1 ) ;
h & additionalInfo [ 0 ] ;
}
2017-07-31 15:35:42 +02:00
h & turnsRemain ;
h & valType ;
2018-03-27 09:54:58 +02:00
if ( version > = 784 )
{
h & stacking ;
}
2017-07-31 15:35:42 +02:00
h & effectRange ;
h & limiter ;
h & propagator ;
2018-02-18 12:32:52 +02:00
if ( version > = 781 )
2018-02-20 12:36:00 +02:00
{
2017-09-10 06:03:02 +02:00
h & updater ;
2018-02-20 12:36:00 +02:00
}
2021-09-12 13:30:54 +02:00
if ( version > = 801 )
{
h & propagationUpdater ;
}
2021-08-19 00:45:28 +02:00
if ( version < 801 & & ! h . saving ) //Opposite Side bonuses are introduced
{
updateOppositeBonuses ( ) ;
}
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
2010-05-02 21:20:26 +03:00
std : : string Description ( ) 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
2016-09-19 23:36:35 +02:00
std : : shared_ptr < Bonus > addLimiter ( TLimiterPtr Limiter ) ; //returns this for convenient chain-calls
std : : shared_ptr < Bonus > addPropagator ( TPropagatorPtr Propagator ) ; //returns this for convenient chain-calls
2017-09-09 07:43:53 +02:00
std : : shared_ptr < Bonus > addUpdater ( TUpdaterPtr Updater ) ; //returns this for convenient chain-calls
2021-08-19 00:45:28 +02:00
void updateOppositeBonuses ( ) ;
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
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE BonusList
2010-02-10 04:56:00 +02:00
{
2016-09-19 23:36:35 +02:00
public :
typedef std : : vector < std : : shared_ptr < Bonus > > TInternalContainer ;
2012-09-20 19:55:21 +03:00
2016-09-19 23:36:35 +02:00
private :
2012-09-20 19:55:21 +03:00
TInternalContainer bonuses ;
2011-07-13 21:39:02 +03:00
bool belongsToTree ;
2016-07-29 12:10:32 +02:00
void changed ( ) ;
2012-09-20 19:55:21 +03:00
2011-07-13 21:39:02 +03:00
public :
2012-09-20 19:55:21 +03:00
typedef TInternalContainer : : const_reference const_reference ;
typedef TInternalContainer : : value_type value_type ;
2013-06-29 16:05:48 +03:00
typedef TInternalContainer : : const_iterator const_iterator ;
typedef TInternalContainer : : iterator iterator ;
2011-07-13 21:39:02 +03:00
BonusList ( bool BelongsToTree = false ) ;
BonusList ( const BonusList & bonusList ) ;
2016-08-15 08:28:00 +02:00
BonusList ( BonusList & & other ) ;
2012-09-15 22:16:16 +03:00
BonusList & operator = ( const BonusList & bonusList ) ;
2011-07-13 21:39:02 +03:00
// wrapper functions of the STL vector container
2016-09-19 23:36:35 +02:00
TInternalContainer : : size_type size ( ) const { return bonuses . size ( ) ; }
void push_back ( std : : shared_ptr < Bonus > x ) ;
TInternalContainer : : iterator erase ( const int position ) ;
2011-07-13 21:39:02 +03:00
void clear ( ) ;
2013-07-19 19:35:16 +03:00
bool empty ( ) const { return bonuses . empty ( ) ; }
2016-09-19 23:36:35 +02:00
void resize ( TInternalContainer : : size_type sz , std : : shared_ptr < Bonus > c = nullptr ) ;
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
STRONG_INLINE std : : shared_ptr < Bonus > & operator [ ] ( TInternalContainer : : size_type n ) { return bonuses [ n ] ; }
STRONG_INLINE const std : : shared_ptr < Bonus > & operator [ ] ( TInternalContainer : : size_type n ) const { return bonuses [ n ] ; }
2016-09-19 23:36:35 +02:00
std : : shared_ptr < Bonus > & back ( ) { return bonuses . back ( ) ; }
std : : shared_ptr < Bonus > & front ( ) { return bonuses . front ( ) ; }
const std : : shared_ptr < Bonus > & back ( ) const { return bonuses . back ( ) ; }
const std : : shared_ptr < Bonus > & front ( ) const { return bonuses . front ( ) ; }
2011-07-16 16:57:25 +03:00
// There should be no non-const access to provide solid,robust bonus caching
2016-09-19 23:36:35 +02:00
TInternalContainer : : const_iterator begin ( ) const { return bonuses . begin ( ) ; }
TInternalContainer : : const_iterator end ( ) const { return bonuses . end ( ) ; }
TInternalContainer : : size_type operator - = ( std : : shared_ptr < Bonus > const & i ) ;
2011-07-13 21:39:02 +03:00
// BonusList functions
2018-03-27 09:54:58 +02:00
void stackBonuses ( ) ;
2016-11-18 11:56:13 +02:00
int totalValue ( ) const ;
2012-03-06 19:59:55 +03:00
void getBonuses ( BonusList & out , const CSelector & selector , const CSelector & limit ) const ;
void getAllBonuses ( BonusList & out ) const ;
2011-07-13 21:39:02 +03:00
2012-03-06 19:59:55 +03:00
void getBonuses ( BonusList & out , const CSelector & selector ) const ;
2011-02-27 13:26:18 +02:00
2010-05-02 21:20:26 +03:00
//special find functions
2016-09-19 23:36:35 +02:00
std : : shared_ptr < Bonus > getFirst ( const CSelector & select ) ;
2020-10-01 07:55:41 +02:00
std : : shared_ptr < const Bonus > getFirst ( const CSelector & select ) const ;
2011-07-13 21:39:02 +03:00
int valOfBonuses ( const CSelector & select ) const ;
2010-02-10 04:56:00 +02:00
2018-03-27 09:54:58 +02:00
// conversion / output
JsonNode toJsonNode ( ) const ;
2012-09-15 22:16:16 +03:00
2011-06-25 16:53:15 +03:00
// remove_if implementation for STL vector types
template < class Predicate >
void remove_if ( Predicate pred )
{
BonusList newList ;
2011-12-14 00:23:17 +03:00
for ( ui32 i = 0 ; i < bonuses . size ( ) ; i + + )
2011-06-25 16:53:15 +03:00
{
2016-09-19 23:36:35 +02:00
auto b = bonuses [ i ] ;
if ( ! pred ( b . get ( ) ) )
2011-06-25 16:53:15 +03:00
newList . push_back ( b ) ;
}
2011-07-13 21:39:02 +03:00
bonuses . clear ( ) ;
bonuses . resize ( newList . size ( ) ) ;
std : : copy ( newList . begin ( ) , newList . end ( ) , bonuses . begin ( ) ) ;
}
2012-09-15 22:16:16 +03:00
2011-07-13 21:39:02 +03:00
template < class InputIterator >
2011-07-14 02:36:37 +03:00
void insert ( const int position , InputIterator first , InputIterator last ) ;
2016-09-19 23:36:35 +02:00
void insert ( TInternalContainer : : iterator position , TInternalContainer : : size_type n , std : : shared_ptr < Bonus > const & x ) ;
2010-07-12 13:20:25 +03:00
2016-09-19 23:36:35 +02:00
template < typename Handler >
void serialize ( Handler & h , const int version )
2010-02-10 04:56:00 +02:00
{
2016-09-19 23:36:35 +02:00
h & static_cast < TInternalContainer & > ( bonuses ) ;
2010-02-10 04:56:00 +02:00
}
2011-07-13 21:39:02 +03:00
2013-06-29 16:05:48 +03:00
// C++ for range support
auto begin ( ) - > decltype ( bonuses . begin ( ) )
{
return bonuses . begin ( ) ;
}
auto end ( ) - > decltype ( bonuses . end ( ) )
{
return bonuses . end ( ) ;
}
2010-04-03 06:33:46 +03:00
} ;
2011-07-13 21:39:02 +03:00
// Extensions for BOOST_FOREACH to enable iterating of BonusList objects
2011-07-16 16:57:25 +03:00
// Don't touch/call this functions
2013-06-29 16:05:48 +03:00
inline BonusList : : iterator range_begin ( BonusList & x )
2011-07-13 21:39:02 +03:00
{
2013-06-29 16:05:48 +03:00
return x . begin ( ) ;
2011-07-13 21:39:02 +03:00
}
2013-06-29 16:05:48 +03:00
inline BonusList : : iterator range_end ( BonusList & x )
2011-07-13 21:39:02 +03:00
{
2013-06-29 16:05:48 +03:00
return x . end ( ) ;
2011-07-13 21:39:02 +03:00
}
2013-06-29 16:05:48 +03:00
inline BonusList : : const_iterator range_begin ( BonusList const & x )
2011-07-13 21:39:02 +03:00
{
return x . begin ( ) ;
}
2013-06-29 16:05:48 +03:00
inline BonusList : : const_iterator range_end ( BonusList const & x )
2011-07-13 21:39:02 +03:00
{
return x . end ( ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE std : : ostream & operator < < ( std : : ostream & out , const BonusList & bonusList ) ;
2010-07-12 13:20:25 +03:00
2012-03-06 19:59:55 +03:00
struct BonusLimitationContext
{
2020-10-01 07:55:41 +02:00
std : : shared_ptr < const Bonus > b ;
2018-04-01 13:17:34 +02:00
const CBonusSystemNode & node ;
const BonusList & alreadyAccepted ;
const BonusList & stillUndecided ;
2012-03-06 19:59:55 +03:00
} ;
2012-09-15 22:16:16 +03:00
2013-01-20 15:06:18 +03:00
class DLL_LINKAGE ILimiter
2010-07-12 13:20:25 +03:00
{
public :
2012-03-06 19:59:55 +03:00
enum EDecision { ACCEPT , DISCARD , NOT_SURE } ;
2010-07-12 13:20:25 +03:00
virtual ~ ILimiter ( ) ;
2013-01-20 15:06:18 +03:00
virtual int limit ( const BonusLimitationContext & context ) const ; //0 - accept bonus; 1 - drop bonus; 2 - delay (drops eventually)
2017-09-12 01:56:38 +02:00
virtual std : : string toString ( ) const ;
virtual JsonNode toJsonNode ( ) const ;
2013-01-20 15:06:18 +03:00
2010-07-12 13:20:25 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
2013-01-17 21:15:00 +03:00
{
}
2010-07-12 13:20:25 +03:00
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE IBonusBearer
2010-04-03 06:33:46 +03:00
{
2020-06-28 15:19:27 +02:00
private :
static CSelector anaffectedByMoraleSelector ;
CCheckProxy anaffectedByMorale ;
static CSelector moraleSelector ;
CTotalsProxy moraleValue ;
2020-11-11 21:43:40 +02:00
static CSelector luckSelector ;
CTotalsProxy luckValue ;
2020-06-28 15:19:27 +02:00
static CSelector selfMoraleSelector ;
CCheckProxy selfMorale ;
2020-11-11 21:43:40 +02:00
static CSelector selfLuckSelector ;
CCheckProxy selfLuck ;
2020-06-28 15:19:27 +02:00
2010-04-03 06:33:46 +03:00
public :
2010-05-02 21:20:26 +03:00
//new bonusing node interface
// * selector is predicate that tests if HeroBonus matches our criteria
2013-06-26 14:18:27 +03:00
// * root is node on which call was made (nullptr will be replaced with this)
2010-11-13 22:26:15 +02:00
//interface
2020-06-28 15:19:27 +02:00
IBonusBearer ( ) ;
2022-05-19 14:14:50 +02:00
virtual ~ IBonusBearer ( ) = default ;
2020-10-01 07:55:41 +02:00
virtual TConstBonusListPtr getAllBonuses ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = nullptr , const std : : string & cachingStr = " " ) const = 0 ;
2011-07-16 16:57:25 +03:00
int valOfBonuses ( const CSelector & selector , const std : : string & cachingStr = " " ) const ;
2011-07-13 21:39:02 +03:00
bool hasBonus ( const CSelector & selector , const std : : string & cachingStr = " " ) const ;
2016-09-30 16:11:17 +02:00
bool hasBonus ( const CSelector & selector , const CSelector & limit , const std : : string & cachingStr = " " ) const ;
2020-10-01 07:55:41 +02:00
TConstBonusListPtr getBonuses ( const CSelector & selector , const CSelector & limit , const std : : string & cachingStr = " " ) const ;
TConstBonusListPtr getBonuses ( const CSelector & selector , const std : : string & cachingStr = " " ) const ;
2010-11-13 22:26:15 +02:00
2020-10-01 07:55:41 +02:00
std : : shared_ptr < const Bonus > getBonus ( const CSelector & selector ) const ; //returns any bonus visible on node that matches (or nullptr if none matches)
2012-09-20 19:55:21 +03:00
2012-09-15 22:16:16 +03:00
//legacy interface
2010-05-02 21:20:26 +03:00
int valOfBonuses ( Bonus : : BonusType type , const CSelector & selector ) const ;
2010-08-25 11:40:50 +03:00
int valOfBonuses ( Bonus : : BonusType type , int subtype = - 1 ) const ; //subtype -> subtype of bonus, if -1 then anyt;
2010-05-02 21:20:26 +03:00
bool hasBonusOfType ( Bonus : : BonusType type , int subtype = - 1 ) const ; //determines if hero has a bonus of given type (and optionally subtype)
2013-02-02 01:04:25 +03:00
bool hasBonusFrom ( Bonus : : BonusSource source , ui32 sourceID ) const ;
2011-02-27 21:58:14 +02:00
//various hlp functions for non-trivial values
2017-07-20 06:08:49 +02:00
//used for stacks and creatures only
virtual int getMinDamage ( bool ranged ) const ;
virtual int getMaxDamage ( bool ranged ) const ;
virtual int getAttack ( bool ranged ) const ;
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
virtual int getDefense ( bool ranged ) const ;
2017-07-20 06:08:49 +02:00
2010-05-02 21:20:26 +03:00
int MoraleVal ( ) const ; //range [-3, +3]
int LuckVal ( ) const ; //range [-3, +3]
2020-11-11 21:43:40 +02:00
/**
Returns total value of all morale bonuses and sets bonusList as a pointer to the list of selected bonuses .
@ param bonusList is the out param it ' s list of all selected bonuses
@ return total value of all morale in the range [ - 3 , + 3 ] and 0 otherwise
*/
int MoraleValAndBonusList ( TConstBonusListPtr & bonusList ) const ;
int LuckValAndBonusList ( TConstBonusListPtr & bonusList ) const ;
2012-01-26 19:48:53 +03:00
ui32 MaxHealth ( ) const ; //get max HP of stack with all modifiers
2011-06-25 18:05:01 +03:00
bool isLiving ( ) const ; //non-undead, non-non living or alive
2011-05-29 21:28:50 +03:00
virtual si32 magicResistance ( ) const ;
2013-07-22 20:06:32 +03:00
ui32 Speed ( int turn = 0 , bool useBind = false ) const ; //get speed of creature with all modificators
2010-05-02 21:20:26 +03:00
2012-02-20 19:26:14 +03:00
si32 manaLimit ( ) const ; //maximum mana value for this hero (basically 10*knowledge)
2013-02-06 13:16:44 +03:00
int getPrimSkillLevel ( PrimarySkill : : PrimarySkill id ) const ;
2017-07-20 06:08:49 +02:00
virtual int64_t getTreeVersion ( ) const = 0 ;
2011-02-27 21:58:14 +02:00
} ;
2010-05-02 21:20:26 +03:00
2017-07-20 06:08:49 +02:00
class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer , public boost : : noncopyable
2011-02-27 21:58:14 +02:00
{
2013-02-02 22:28:39 +03:00
public :
enum ENodeTypes
{
2021-01-14 00:02:13 +02:00
NONE = - 1 ,
2014-03-30 00:39:19 +03:00
UNKNOWN , STACK_INSTANCE , STACK_BATTLE , SPECIALTY , ARTIFACT , CREATURE , ARTIFACT_INSTANCE , HERO , PLAYER , TEAM ,
2021-03-23 16:47:07 +02:00
TOWN_AND_VISITOR , BATTLE , COMMANDER , GLOBAL_EFFECTS , ALL_CREATURES , TOWN
2013-02-02 22:28:39 +03:00
} ;
2011-07-13 21:39:02 +03:00
private :
BonusList bonuses ; //wielded bonuses (local or up-propagated here)
BonusList exportedBonuses ; //bonuses coming from this node (wielded or propagated away)
TNodesVector parents ; //parents -> we inherit bonuses from them, we may attach our bonuses to them
TNodesVector children ;
2012-09-15 22:16:16 +03:00
2013-02-02 22:28:39 +03:00
ENodeTypes nodeType ;
2011-07-13 21:39:02 +03:00
std : : string description ;
2021-05-23 13:28:43 +02:00
bool isHypotheticNode ;
2012-09-15 22:16:16 +03:00
static const bool cachingEnabled ;
2011-06-25 16:53:15 +03:00
mutable BonusList cachedBonuses ;
2017-07-20 06:08:49 +02:00
mutable int64_t cachedLast ;
static std : : atomic < int32_t > treeChanged ;
2011-06-25 16:53:15 +03:00
2012-09-15 22:16:16 +03:00
// Setting a value to cachingStr before getting any bonuses caches the result for later requests.
2011-06-25 16:53:15 +03:00
// This string needs to be unique, that's why it has to be setted in the following manner:
// [property key]_[value] => only for selector
2011-09-06 16:59:26 +03:00
mutable std : : map < std : : string , TBonusListPtr > cachedRequests ;
2021-05-16 19:53:11 +02:00
mutable boost : : mutex sync ;
2011-06-25 16:53:15 +03:00
2012-03-06 19:59:55 +03:00
void getAllBonusesRec ( BonusList & out ) const ;
2020-10-01 07:55:41 +02:00
TConstBonusListPtr getAllBonusesWithoutCaching ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = nullptr ) const ;
2021-09-12 13:30:54 +02:00
std : : shared_ptr < Bonus > getUpdatedBonus ( const std : : shared_ptr < Bonus > & b , const TUpdaterPtr updater ) const ;
2011-06-25 16:53:15 +03:00
2011-02-27 21:58:14 +02:00
public :
2011-06-25 16:53:15 +03:00
explicit CBonusSystemNode ( ) ;
2021-05-23 13:28:43 +02:00
explicit CBonusSystemNode ( bool isHypotetic ) ;
2017-07-20 06:08:49 +02:00
explicit CBonusSystemNode ( ENodeTypes NodeType ) ;
2016-07-29 11:27:55 +02:00
CBonusSystemNode ( CBonusSystemNode & & other ) ;
2011-02-27 21:58:14 +02:00
virtual ~ CBonusSystemNode ( ) ;
2012-09-15 22:16:16 +03:00
2012-03-06 19:59:55 +03:00
void limitBonuses ( const BonusList & allBonuses , BonusList & out ) const ; //out will bo populed with bonuses that are not limited here
TBonusListPtr limitBonuses ( const BonusList & allBonuses ) const ; //same as above, returns out by val for convienence
2020-10-01 07:55:41 +02:00
TConstBonusListPtr getAllBonuses ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = nullptr , const std : : string & cachingStr = " " ) const override ;
2011-02-27 21:58:14 +02:00
void getParents ( TCNodes & out ) const ; //retrieves list of parent nodes (nodes to inherit bonuses from),
2021-03-23 16:47:07 +02:00
std : : shared_ptr < const Bonus > getBonusLocalFirst ( const CSelector & selector ) const ;
2011-02-27 21:58:14 +02:00
2010-05-02 21:20:26 +03:00
//non-const interface
2011-02-21 06:13:00 +02:00
void getParents ( TNodes & out ) ; //retrieves list of parent nodes (nodes to inherit bonuses from)
2021-03-23 16:47:07 +02:00
2011-02-21 06:13:00 +02:00
void getRedParents ( TNodes & out ) ; //retrieves list of red parent nodes (nodes bonuses propagate from)
void getRedAncestors ( TNodes & out ) ;
2012-09-15 22:16:16 +03:00
void getRedChildren ( TNodes & out ) ;
void getRedDescendants ( TNodes & out ) ;
2021-02-05 00:56:21 +02:00
void getAllParents ( TCNodes & out ) const ;
2021-03-23 16:47:07 +02:00
static PlayerColor retrieveNodeOwner ( const CBonusSystemNode * node ) ;
std : : shared_ptr < Bonus > getBonusLocalFirst ( const CSelector & selector ) ;
2010-04-03 06:33:46 +03:00
2010-11-22 02:34:46 +02:00
void attachTo ( CBonusSystemNode * parent ) ;
void detachFrom ( CBonusSystemNode * parent ) ;
2010-12-06 01:10:02 +02:00
void detachFromAll ( ) ;
2016-09-19 23:36:35 +02:00
virtual void addNewBonus ( const std : : shared_ptr < Bonus > & b ) ;
void accumulateBonus ( const std : : shared_ptr < Bonus > & b ) ; //add value of bonus with same type/subtype or create new
2010-11-22 02:34:46 +02:00
void newChildAttached ( CBonusSystemNode * child ) ;
void childDetached ( CBonusSystemNode * child ) ;
2021-09-12 13:30:54 +02:00
void propagateBonus ( std : : shared_ptr < Bonus > b , const CBonusSystemNode & source ) ;
2016-09-19 23:36:35 +02:00
void unpropagateBonus ( std : : shared_ptr < Bonus > b ) ;
void removeBonus ( const std : : shared_ptr < Bonus > & b ) ;
2018-03-05 13:03:14 +02:00
void removeBonuses ( const CSelector & selector ) ;
void removeBonusesRecursive ( const CSelector & s ) ;
2011-02-21 06:13:00 +02:00
void newRedDescendant ( CBonusSystemNode * descendant ) ; //propagation needed
void removedRedDescendant ( CBonusSystemNode * descendant ) ; //de-propagation needed
2010-11-19 00:06:56 +02:00
2010-12-06 01:10:02 +02:00
bool isIndependentNode ( ) const ; //node is independent when it has no parents nor children
2011-02-21 06:13:00 +02:00
bool actsAsBonusSourceOnly ( ) const ;
2016-10-01 13:10:09 +02:00
///updates count of remaining turns and removes outdated bonuses by selector
2017-09-09 14:25:55 +02:00
void reduceBonusDurations ( const CSelector & s ) ;
2016-09-19 23:36:35 +02:00
virtual std : : string bonusToString ( const std : : shared_ptr < Bonus > & bonus , bool description ) const { return " " ; } ; //description or bonus name
2010-12-12 01:11:26 +02:00
virtual std : : string nodeName ( ) const ;
2021-03-23 16:47:07 +02:00
virtual std : : string nodeShortInfo ( ) const ;
2021-03-01 21:38:50 +02:00
bool isHypothetic ( ) const { return isHypotheticNode ; }
2011-03-01 12:19:05 +02:00
2011-02-04 16:58:14 +02:00
void deserializationFix ( ) ;
2016-09-19 23:36:35 +02:00
void exportBonus ( std : : shared_ptr < Bonus > b ) ;
2011-03-01 12:19:05 +02:00
void exportBonuses ( ) ;
2012-09-15 22:16:16 +03:00
2011-07-13 21:39:02 +03:00
const BonusList & getBonusList ( ) const ;
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
BonusList & getExportedBonusList ( ) ;
const BonusList & getExportedBonusList ( ) const ;
2013-02-02 22:28:39 +03:00
CBonusSystemNode : : ENodeTypes getNodeType ( ) const ;
void setNodeType ( CBonusSystemNode : : ENodeTypes type ) ;
2011-07-13 21:39:02 +03:00
const TNodesVector & getParentNodes ( ) const ;
const TNodesVector & getChildrenNodes ( ) const ;
const std : : string & getDescription ( ) const ;
void setDescription ( const std : : string & description ) ;
2010-11-13 22:26:15 +02:00
2012-03-06 19:59:55 +03:00
static void treeHasChanged ( ) ;
2017-07-20 06:08:49 +02:00
int64_t getTreeVersion ( ) const override ;
2021-09-12 13:30:54 +02:00
virtual PlayerColor getOwner ( ) const
{
return PlayerColor : : NEUTRAL ;
}
2010-04-03 06:33:46 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2017-07-31 15:35:42 +02:00
// h & bonuses;
h & nodeType ;
2011-01-28 04:11:58 +02:00
h & exportedBonuses ;
2011-02-10 15:12:53 +02:00
h & description ;
2011-02-23 05:57:45 +02:00
BONUS_TREE_DESERIALIZATION_FIX
2011-01-28 04:11:58 +02:00
//h & parents & children;
2010-04-03 06:33:46 +03:00
}
2017-07-04 13:24:46 +02:00
friend class CBonusProxy ;
2010-04-03 06:33:46 +03:00
} ;
2021-01-14 00:02:13 +02:00
class DLL_LINKAGE IPropagator
{
public :
virtual ~ IPropagator ( ) ;
virtual bool shouldBeAttached ( CBonusSystemNode * dest ) ;
virtual CBonusSystemNode : : ENodeTypes getPropagatorType ( ) const ;
template < typename Handler > void serialize ( Handler & h , const int version )
{ }
} ;
class DLL_LINKAGE CPropagatorNodeType : public IPropagator
{
CBonusSystemNode : : ENodeTypes nodeType ;
public :
CPropagatorNodeType ( ) ;
CPropagatorNodeType ( CBonusSystemNode : : ENodeTypes NodeType ) ;
bool shouldBeAttached ( CBonusSystemNode * dest ) override ;
CBonusSystemNode : : ENodeTypes getPropagatorType ( ) const override ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & nodeType ;
}
} ;
2010-04-03 06:33:46 +03:00
namespace NBonus
{
2013-06-26 14:18:27 +03:00
//set of methods that may be safely called with nullptr objs
2011-12-14 00:23:17 +03:00
DLL_LINKAGE int valOf ( const CBonusSystemNode * obj , Bonus : : BonusType type , int subtype = - 1 ) ; //subtype -> subtype of bonus, if -1 then any
DLL_LINKAGE bool hasOfType ( const CBonusSystemNode * obj , Bonus : : BonusType type , int subtype = - 1 ) ; //determines if hero has a bonus of given type (and optionally subtype)
2012-09-15 22:16:16 +03:00
}
2010-05-02 21:20:26 +03:00
template < typename T >
class CSelectFieldEqual
{
T Bonus : : * ptr ;
2013-07-02 15:08:30 +03:00
2010-05-02 21:20:26 +03:00
public :
2013-07-02 15:08:30 +03:00
CSelectFieldEqual ( T Bonus : : * Ptr )
: ptr ( Ptr )
2010-05-02 21:20:26 +03:00
{
}
2016-01-31 17:01:58 +02:00
2013-07-02 15:08:30 +03:00
CSelector operator ( ) ( const T & valueToCompareAgainst ) const
2010-05-02 21:20:26 +03:00
{
2013-07-02 15:08:30 +03:00
auto ptr2 = ptr ; //We need a COPY because we don't want to reference this (might be outlived by lambda)
2020-11-11 21:43:40 +02:00
return [ ptr2 , valueToCompareAgainst ] ( const Bonus * bonus )
{
return bonus - > * ptr2 = = valueToCompareAgainst ;
} ;
2010-05-02 21:20:26 +03:00
}
} ;
2013-02-26 12:36:21 +03:00
template < typename T > //can be same, needed for subtype field
class CSelectFieldEqualOrEvery
{
T Bonus : : * ptr ;
T val ;
public :
CSelectFieldEqualOrEvery ( T Bonus : : * Ptr , const T & Val )
: ptr ( Ptr ) , val ( Val )
{
}
bool operator ( ) ( const Bonus * bonus ) const
{
return ( bonus - > * ptr = = val ) | | ( bonus - > * ptr = = static_cast < T > ( Bonus : : EVERY_TYPE ) ) ;
}
CSelectFieldEqualOrEvery & operator ( ) ( const T & setVal )
{
val = setVal ;
return * this ;
}
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CWillLastTurns
2010-05-02 21:20:26 +03:00
{
public :
int turnsRequested ;
2010-11-19 00:06:56 +02:00
bool operator ( ) ( const Bonus * bonus ) const
2010-05-02 21:20:26 +03:00
{
2010-05-31 23:38:14 +03:00
return turnsRequested < = 0 //every present effect will last zero (or "less") turns
2015-11-20 12:24:48 +02:00
| | ! Bonus : : NTurns ( bonus ) //so do every not expriing after N-turns effect
2012-09-15 22:16:16 +03:00
| | bonus - > turnsRemain > turnsRequested ;
2010-05-02 21:20:26 +03:00
}
CWillLastTurns & operator ( ) ( const int & setVal )
{
turnsRequested = setVal ;
return * this ;
}
} ;
2015-11-09 14:01:58 +02:00
class DLL_LINKAGE CWillLastDays
{
public :
int daysRequested ;
bool operator ( ) ( const Bonus * bonus ) const
{
2015-11-20 12:24:48 +02:00
if ( daysRequested < = 0 | | Bonus : : Permanent ( bonus ) | | Bonus : : OneBattle ( bonus ) )
2015-11-09 14:01:58 +02:00
return true ;
2015-11-20 12:24:48 +02:00
else if ( Bonus : : OneDay ( bonus ) )
2015-11-09 14:01:58 +02:00
return false ;
2015-11-20 12:24:48 +02:00
else if ( Bonus : : NDays ( bonus ) | | Bonus : : OneWeek ( bonus ) )
2015-11-09 14:01:58 +02:00
{
return bonus - > turnsRemain > daysRequested ;
}
return false ; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations
}
CWillLastDays & operator ( ) ( const int & setVal )
{
daysRequested = setVal ;
return * this ;
}
} ;
2018-04-01 13:17:34 +02:00
class DLL_LINKAGE AggregateLimiter : public ILimiter
2013-01-20 15:06:18 +03:00
{
2018-04-01 13:17:34 +02:00
protected :
2013-01-20 15:06:18 +03:00
std : : vector < TLimiterPtr > limiters ;
2018-04-01 13:17:34 +02:00
virtual const std : : string & getAggregator ( ) const = 0 ;
2013-01-20 15:06:18 +03:00
public :
void add ( TLimiterPtr limiter ) ;
2018-04-01 13:17:34 +02:00
JsonNode toJsonNode ( ) const override ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < ILimiter & > ( * this ) ;
if ( version > = 786 )
{
h & limiters ;
}
}
} ;
class DLL_LINKAGE AllOfLimiter : public AggregateLimiter
{
protected :
const std : : string & getAggregator ( ) const override ;
public :
static const std : : string aggregator ;
int limit ( const BonusLimitationContext & context ) const override ;
} ;
class DLL_LINKAGE AnyOfLimiter : public AggregateLimiter
{
protected :
const std : : string & getAggregator ( ) const override ;
public :
static const std : : string aggregator ;
int limit ( const BonusLimitationContext & context ) const override ;
} ;
class DLL_LINKAGE NoneOfLimiter : public AggregateLimiter
{
protected :
const std : : string & getAggregator ( ) const override ;
public :
static const std : : string aggregator ;
int limit ( const BonusLimitationContext & context ) const override ;
2013-01-20 15:06:18 +03:00
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CCreatureTypeLimiter : public ILimiter //affect only stacks of given creature (and optionally it's upgrades)
2010-07-12 13:20:25 +03:00
{
public :
const CCreature * creature ;
2013-02-02 22:28:39 +03:00
bool includeUpgrades ;
2010-07-12 13:20:25 +03:00
CCreatureTypeLimiter ( ) ;
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
CCreatureTypeLimiter ( const CCreature & creature_ , bool IncludeUpgrades = true ) ;
2013-02-11 02:24:57 +03:00
void setCreature ( CreatureID id ) ;
2010-07-12 13:20:25 +03:00
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2017-09-12 01:56:38 +02:00
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
2010-07-12 13:20:25 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-19 20:38:37 +03:00
h & static_cast < ILimiter & > ( * this ) ;
2017-07-31 15:35:42 +02:00
h & creature ;
h & includeUpgrades ;
2010-07-12 13:20:25 +03:00
}
} ;
2010-08-06 13:46:40 +03:00
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE HasAnotherBonusLimiter : public ILimiter //applies only to nodes that have another bonus working
2010-08-06 13:46:40 +03:00
{
public :
2013-02-16 17:03:47 +03:00
Bonus : : BonusType type ;
2010-08-06 13:46:40 +03:00
TBonusSubtype subtype ;
2013-02-02 22:28:39 +03:00
bool isSubtypeRelevant ; //check for subtype only if this is true
2010-08-06 13:46:40 +03:00
2013-02-16 17:03:47 +03:00
HasAnotherBonusLimiter ( Bonus : : BonusType bonus = Bonus : : NONE ) ;
HasAnotherBonusLimiter ( Bonus : : BonusType bonus , TBonusSubtype _subtype ) ;
2010-08-06 13:46:40 +03:00
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2017-09-17 04:45:23 +02:00
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
2010-08-06 13:46:40 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-19 20:38:37 +03:00
h & static_cast < ILimiter & > ( * this ) ;
2017-07-31 15:35:42 +02:00
h & type ;
h & subtype ;
h & isSubtypeRelevant ;
2010-08-06 13:46:40 +03:00
}
} ;
2018-04-17 14:59:30 +02:00
class DLL_LINKAGE CreatureTerrainLimiter : public ILimiter //applies only to creatures that are on specified terrain, default native terrain
2010-11-20 02:03:31 +02:00
{
public :
2013-02-02 22:28:39 +03:00
int terrainType ;
2018-04-17 14:59:30 +02:00
CreatureTerrainLimiter ( ) ;
CreatureTerrainLimiter ( int TerrainType ) ;
2010-11-20 02:03:31 +02:00
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2018-04-17 14:59:30 +02:00
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
2010-11-20 02:03:31 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-19 20:38:37 +03:00
h & static_cast < ILimiter & > ( * this ) ;
2010-11-20 02:03:31 +02:00
h & terrainType ;
}
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CreatureFactionLimiter : public ILimiter //applies only to creatures of given faction
2010-11-20 02:03:31 +02:00
{
public :
2020-12-10 03:05:37 +02:00
TFaction faction ;
2010-11-20 02:03:31 +02:00
CreatureFactionLimiter ( ) ;
2020-12-10 03:05:37 +02:00
CreatureFactionLimiter ( TFaction faction ) ;
2010-11-20 02:03:31 +02:00
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2018-04-17 14:59:30 +02:00
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
2010-11-20 02:03:31 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-19 20:38:37 +03:00
h & static_cast < ILimiter & > ( * this ) ;
2010-11-20 02:03:31 +02:00
h & faction ;
}
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CreatureAlignmentLimiter : public ILimiter //applies only to creatures of given alignment
2010-11-20 02:03:31 +02:00
{
public :
si8 alignment ;
CreatureAlignmentLimiter ( ) ;
CreatureAlignmentLimiter ( si8 Alignment ) ;
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2018-04-17 14:59:30 +02:00
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
2010-11-20 02:03:31 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-19 20:38:37 +03:00
h & static_cast < ILimiter & > ( * this ) ;
2010-11-20 02:03:31 +02:00
h & alignment ;
}
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE StackOwnerLimiter : public ILimiter //applies only to creatures of given alignment
2011-02-21 06:13:00 +02:00
{
public :
2013-03-03 20:06:03 +03:00
PlayerColor owner ;
2011-02-21 06:13:00 +02:00
StackOwnerLimiter ( ) ;
2013-03-03 20:06:03 +03:00
StackOwnerLimiter ( PlayerColor Owner ) ;
2011-02-21 06:13:00 +02:00
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2011-02-21 06:13:00 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-19 20:38:37 +03:00
h & static_cast < ILimiter & > ( * this ) ;
2011-02-21 06:13:00 +02:00
h & owner ;
}
} ;
2021-03-23 16:47:07 +02:00
class DLL_LINKAGE OppositeSideLimiter : public ILimiter //applies only to creatures of enemy army during combat
{
public :
PlayerColor owner ;
OppositeSideLimiter ( ) ;
OppositeSideLimiter ( PlayerColor Owner ) ;
int limit ( const BonusLimitationContext & context ) const override ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < ILimiter & > ( * this ) ;
h & owner ;
}
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE RankRangeLimiter : public ILimiter //applies to creatures with min <= Rank <= max
2011-02-11 10:20:26 +02:00
{
public :
2011-02-12 18:12:48 +02:00
ui8 minRank , maxRank ;
2011-02-11 10:20:26 +02:00
2011-02-21 06:13:00 +02:00
RankRangeLimiter ( ) ;
2011-02-12 18:12:48 +02:00
RankRangeLimiter ( ui8 Min , ui8 Max = 255 ) ;
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2011-02-11 10:20:26 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-19 20:38:37 +03:00
h & static_cast < ILimiter & > ( * this ) ;
2017-07-31 15:35:42 +02:00
h & minRank ;
h & maxRank ;
2011-02-11 10:20:26 +02:00
}
} ;
2010-05-02 21:20:26 +03:00
namespace Selector
{
2020-11-11 21:43:40 +02:00
extern DLL_LINKAGE CSelectFieldEqual < Bonus : : BonusType > & type ( ) ;
extern DLL_LINKAGE CSelectFieldEqual < TBonusSubtype > & subtype ( ) ;
extern DLL_LINKAGE CSelectFieldEqual < CAddInfo > & info ( ) ;
extern DLL_LINKAGE CSelectFieldEqual < Bonus : : BonusSource > & sourceType ( ) ;
extern DLL_LINKAGE CSelectFieldEqual < Bonus : : LimitEffect > & effectRange ( ) ;
2011-12-14 00:23:17 +03:00
extern DLL_LINKAGE CWillLastTurns turns ;
2015-11-09 14:01:58 +02:00
extern DLL_LINKAGE CWillLastDays days ;
2011-12-14 00:23:17 +03:00
2013-02-16 17:03:47 +03:00
CSelector DLL_LINKAGE typeSubtype ( Bonus : : BonusType Type , TBonusSubtype Subtype ) ;
2018-03-12 07:20:18 +02:00
CSelector DLL_LINKAGE typeSubtypeInfo ( Bonus : : BonusType type , TBonusSubtype subtype , CAddInfo info ) ;
2013-02-02 01:04:25 +03:00
CSelector DLL_LINKAGE source ( Bonus : : BonusSource source , ui32 sourceID ) ;
CSelector DLL_LINKAGE sourceTypeSel ( Bonus : : BonusSource source ) ;
2017-08-27 05:35:04 +02:00
CSelector DLL_LINKAGE valueType ( Bonus : : ValueType valType ) ;
2011-12-14 00:23:17 +03:00
2016-10-01 09:31:59 +02:00
/**
* Selects all bonuses
* Usage example : Selector : : all . And ( < functor > ) . And ( < functor > ) . . . )
*/
2016-09-30 16:11:17 +02:00
extern DLL_LINKAGE CSelector all ;
2016-10-01 09:31:59 +02:00
/**
* Selects nothing
* Usage example : Selector : : none . Or ( < functor > ) . Or ( < functor > ) . . . )
*/
2016-09-30 16:11:17 +02:00
extern DLL_LINKAGE CSelector none ;
2013-02-16 17:03:47 +03:00
bool DLL_LINKAGE matchesType ( const CSelector & sel , Bonus : : BonusType type ) ;
bool DLL_LINKAGE matchesTypeSubtype ( const CSelector & sel , Bonus : : BonusType type , TBonusSubtype subtype ) ;
2010-05-12 05:32:56 +03:00
}
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 ;
extern DLL_LINKAGE const std : : map < std : : string , TLimiterPtr > bonusLimiterMap ;
extern DLL_LINKAGE const std : : map < std : : string , TPropagatorPtr > bonusPropagatorMap ;
2017-09-19 00:08:28 +02:00
extern DLL_LINKAGE const std : : map < std : : string , TUpdaterPtr > bonusUpdaterMap ;
2014-02-17 10:36:03 +03:00
// BonusList template that requires full interface of CBonusSystemNode
2011-07-14 02:36:37 +03:00
template < class InputIterator >
void BonusList : : insert ( const int position , InputIterator first , InputIterator last )
{
bonuses . insert ( bonuses . begin ( ) + position , first , last ) ;
2016-07-29 12:10:32 +02:00
changed ( ) ;
2011-07-14 02:36:37 +03:00
}
2017-09-09 07:43:53 +02:00
2017-09-10 04:10:50 +02:00
// observers for updating bonuses based on certain events (e.g. hero gaining level)
2017-09-09 07:43:53 +02:00
class DLL_LINKAGE IUpdater
{
public :
2017-09-10 05:20:47 +02:00
virtual ~ IUpdater ( ) ;
2021-09-12 13:30:54 +02:00
virtual std : : shared_ptr < Bonus > createUpdatedBonus ( const std : : shared_ptr < Bonus > & b , const CBonusSystemNode & context ) const ;
2017-09-11 02:36:02 +02:00
virtual std : : string toString ( ) const ;
2017-09-19 00:08:28 +02:00
virtual JsonNode toJsonNode ( ) const ;
2017-09-09 07:43:53 +02:00
2017-09-17 05:48:01 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
2017-09-09 07:43:53 +02:00
{
}
} ;
2017-09-19 00:08:28 +02:00
class DLL_LINKAGE GrowsWithLevelUpdater : public IUpdater
2017-09-09 07:43:53 +02:00
{
2017-09-15 02:20:03 +02:00
public :
2017-09-10 04:10:50 +02:00
int valPer20 ;
int stepSize ;
2017-09-19 00:08:28 +02:00
GrowsWithLevelUpdater ( ) ;
GrowsWithLevelUpdater ( int valPer20 , int stepSize = 1 ) ;
2017-09-09 07:43:53 +02:00
2017-09-17 05:48:01 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
2017-09-09 07:43:53 +02:00
{
2017-09-10 05:20:47 +02:00
h & static_cast < IUpdater & > ( * this ) ;
2017-09-09 07:43:53 +02:00
h & valPer20 ;
h & stepSize ;
}
2021-09-12 13:30:54 +02:00
std : : shared_ptr < Bonus > createUpdatedBonus ( const std : : shared_ptr < Bonus > & b , const CBonusSystemNode & context ) const override ;
2017-09-11 02:36:02 +02:00
virtual std : : string toString ( ) const override ;
2017-09-11 08:21:24 +02:00
virtual JsonNode toJsonNode ( ) const override ;
2017-09-09 07:43:53 +02:00
} ;
2017-09-19 00:08:28 +02:00
class DLL_LINKAGE TimesHeroLevelUpdater : public IUpdater
{
public :
TimesHeroLevelUpdater ( ) ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < IUpdater & > ( * this ) ;
}
2021-09-12 13:30:54 +02:00
std : : shared_ptr < Bonus > createUpdatedBonus ( const std : : shared_ptr < Bonus > & b , const CBonusSystemNode & context ) const override ;
2017-09-19 00:08:28 +02:00
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
} ;
2017-09-19 01:43:13 +02:00
class DLL_LINKAGE TimesStackLevelUpdater : public IUpdater
{
public :
TimesStackLevelUpdater ( ) ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < IUpdater & > ( * this ) ;
}
2021-09-12 13:30:54 +02:00
std : : shared_ptr < Bonus > createUpdatedBonus ( const std : : shared_ptr < Bonus > & b , const CBonusSystemNode & context ) const override ;
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
} ;
class DLL_LINKAGE OwnerUpdater : public IUpdater
{
public :
OwnerUpdater ( ) ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < IUpdater & > ( * this ) ;
}
std : : shared_ptr < Bonus > createUpdatedBonus ( const std : : shared_ptr < Bonus > & b , const CBonusSystemNode & context ) const override ;
2017-09-19 01:43:13 +02:00
virtual std : : string toString ( ) const override ;
virtual JsonNode toJsonNode ( ) const override ;
} ;