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"
2023-03-28 01:14:18 +02:00
# include "battle/BattleHex.h"
2023-04-06 17:28:02 +02:00
# include <limits>
2009-04-15 17:03:31 +03:00
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_BEGIN
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 * ) >
{
2023-03-29 14:23:23 +02:00
using TBase = std : : function < bool ( const Bonus * ) > ;
2013-07-02 15:08:30 +03:00
public :
2023-03-29 14:23:23 +02:00
CSelector ( ) = default ;
2013-07-02 15:08:30 +03:00
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
}
2023-03-04 00:23:15 +02:00
CSelector Not ( ) const
{
auto thisCopy = * this ;
return [ thisCopy ] ( const Bonus * b ) mutable { return ! thisCopy ( 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 ) ;
2023-03-13 23:26:44 +02:00
CBonusProxy ( CBonusProxy & & other ) noexcept ;
2017-07-20 06:08:49 +02:00
2023-03-13 23:26:44 +02:00
CBonusProxy & operator = ( CBonusProxy & & other ) noexcept ;
2017-07-20 06:08:49 +02:00
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 ;
2023-03-13 23:26:44 +02:00
CTotalsProxy & operator = ( const CTotalsProxy & other ) = default ;
2020-06-28 15:19:27 +02:00
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 ;
2023-03-13 23:26:44 +02:00
mutable int64_t valueCachedLast = 0 ;
mutable int value = 0 ;
2020-06-28 15:19:27 +02:00
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*/ \
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
{
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
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-01-24 17:35:30 +02:00
std : : string Description ( boost : : 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
2023-03-05 02:16:05 +02:00
struct DLL_LINKAGE BonusParams {
bool isConverted ;
Bonus : : BonusType type = Bonus : : NONE ;
TBonusSubtype subtype = - 1 ;
std : : string subtypeStr = " " ;
bool subtypeRelevant = false ;
Bonus : : ValueType valueType = Bonus : : BASE_NUMBER ;
bool valueTypeRelevant = false ;
si32 val = 0 ;
bool valRelevant = false ;
Bonus : : BonusSource targetType = Bonus : : SECONDARY_SKILL ;
bool targetTypeRelevant = false ;
BonusParams ( bool isConverted = true ) : isConverted ( isConverted ) { } ;
BonusParams ( std : : string deprecatedTypeStr , std : : string deprecatedSubtypeStr = " " , int deprecatedSubtype = 0 ) ;
const JsonNode & toJson ( ) ;
2023-03-09 01:16:18 +02:00
CSelector toSelector ( ) ;
2023-03-05 02:16:05 +02:00
private :
JsonNode ret ;
bool jsonCreated = false ;
} ;
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 ;
2023-03-13 23:26:44 +02:00
void changed ( ) const ;
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 ) ;
2023-03-13 23:26:44 +02:00
BonusList ( BonusList & & other ) noexcept ;
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 ( ) ; }
2023-03-13 23:26:44 +02:00
void push_back ( const std : : shared_ptr < Bonus > & x ) ;
2016-09-19 23:36:35 +02:00
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 ( ) ; }
2023-03-13 23:26:44 +02:00
void resize ( TInternalContainer : : size_type sz , const std : : shared_ptr < Bonus > & c = nullptr ) ;
2022-09-14 11:00:40 +02:00
void reserve ( TInternalContainer : : size_type sz ) ;
TInternalContainer : : size_type capacity ( ) const { return bonuses . capacity ( ) ; }
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 ( ) ; }
2023-03-13 23:26:44 +02:00
TInternalContainer : : size_type operator - = ( const std : : shared_ptr < Bonus > & 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 ;
2023-02-18 20:01:32 +02:00
void getBonuses ( BonusList & out , const CSelector & selector , const CSelector & limit = nullptr ) const ;
2012-03-06 19:59:55 +03:00
void getAllBonuses ( BonusList & out ) const ;
2011-07-13 21:39:02 +03: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 ) ;
2023-03-13 23:26:44 +02:00
void insert ( TInternalContainer : : iterator position , TInternalContainer : : size_type n , const std : : shared_ptr < Bonus > & 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
}
2023-03-13 23:26:44 +02:00
inline BonusList : : const_iterator range_begin ( const BonusList & x )
2011-07-13 21:39:02 +03:00
{
return x . begin ( ) ;
}
2023-03-13 23:26:44 +02:00
inline BonusList : : const_iterator range_end ( const BonusList & 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 :
2023-03-29 12:16:13 +02:00
enum class EDecision : uint8_t { ACCEPT , DISCARD , NOT_SURE } ;
2012-03-06 19:59:55 +03:00
2023-03-13 23:26:44 +02:00
virtual ~ ILimiter ( ) = default ;
2010-07-12 13:20:25 +03:00
2023-03-29 12:16:13 +02:00
virtual EDecision 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
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
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 ;
2023-03-29 13:17:09 +02:00
static std : : atomic < int64_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
2023-03-12 13:39:36 +02:00
void getAllBonusesRec ( BonusList & out , const CSelector & selector ) const ;
2020-10-01 07:55:41 +02:00
TConstBonusListPtr getAllBonusesWithoutCaching ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = nullptr ) const ;
2023-03-13 23:26:44 +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 ) ;
2023-03-13 23:26:44 +02:00
CBonusSystemNode ( CBonusSystemNode & & other ) noexcept ;
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 ) ;
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
2022-11-06 01:26:13 +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
2022-11-06 01:26:13 +02:00
void newChildAttached ( CBonusSystemNode & child ) ;
void childDetached ( CBonusSystemNode & child ) ;
2023-03-13 23:26:44 +02:00
void propagateBonus ( const std : : shared_ptr < Bonus > & b , const CBonusSystemNode & source ) ;
void unpropagateBonus ( const std : : shared_ptr < Bonus > & b ) ;
2016-09-19 23:36:35 +02:00
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 ) ;
2022-11-06 01:26:13 +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 ( ) ;
2023-03-13 23:26:44 +02:00
void exportBonus ( const 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 :
2023-03-13 23:26:44 +02:00
virtual ~ IPropagator ( ) = default ;
2021-01-14 00:02:13 +02:00
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 :
2023-04-09 16:51:05 +02:00
CPropagatorNodeType ( CBonusSystemNode : : ENodeTypes NodeType = CBonusSystemNode : : ENodeTypes : : UNKNOWN ) ;
2021-01-14 00:02:13 +02:00
bool shouldBeAttached ( CBonusSystemNode * dest ) override ;
CBonusSystemNode : : ENodeTypes getPropagatorType ( ) const override ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & nodeType ;
}
} ;
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 ;
2023-04-09 03:36:16 +02:00
AggregateLimiter ( std : : vector < TLimiterPtr > limiters = { } ) ;
2013-01-20 15:06:18 +03:00
public :
2023-03-13 23:26:44 +02:00
void add ( const 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 ) ;
2022-06-20 16:39:50 +02:00
h & limiters ;
2018-04-01 13:17:34 +02:00
}
} ;
class DLL_LINKAGE AllOfLimiter : public AggregateLimiter
{
protected :
const std : : string & getAggregator ( ) const override ;
public :
2023-04-09 03:36:16 +02:00
AllOfLimiter ( std : : vector < TLimiterPtr > limiters = { } ) ;
2018-04-01 13:17:34 +02:00
static const std : : string aggregator ;
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
2018-04-01 13:17:34 +02:00
} ;
class DLL_LINKAGE AnyOfLimiter : public AggregateLimiter
{
protected :
const std : : string & getAggregator ( ) const override ;
public :
2023-04-09 03:36:16 +02:00
AnyOfLimiter ( std : : vector < TLimiterPtr > limiters = { } ) ;
2018-04-01 13:17:34 +02:00
static const std : : string aggregator ;
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
2018-04-01 13:17:34 +02:00
} ;
class DLL_LINKAGE NoneOfLimiter : public AggregateLimiter
{
protected :
const std : : string & getAggregator ( ) const override ;
public :
2023-04-09 03:36:16 +02:00
NoneOfLimiter ( std : : vector < TLimiterPtr > limiters = { } ) ;
2018-04-01 13:17:34 +02:00
static const std : : string aggregator ;
2023-03-29 12:16:13 +02:00
EDecision 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 :
2023-03-13 23:26:44 +02:00
const CCreature * creature = nullptr ;
bool includeUpgrades = false ;
2010-07-12 13:20:25 +03:00
2023-03-13 23:26:44 +02:00
CCreatureTypeLimiter ( ) = default ;
2023-03-28 16:09:54 +02:00
CCreatureTypeLimiter ( const CCreature & creature_ , bool IncludeUpgrades ) ;
2023-03-13 23:26:44 +02:00
void setCreature ( const CreatureID & id ) ;
2010-07-12 13:20:25 +03:00
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
std : : string toString ( ) const override ;
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 ;
2023-03-01 23:54:10 +02:00
Bonus : : BonusSource source ;
si32 sid ;
2013-02-02 22:28:39 +03:00
bool isSubtypeRelevant ; //check for subtype only if this is true
2023-03-01 23:54:10 +02:00
bool isSourceRelevant ; //check for bonus source only if this is true
bool isSourceIDRelevant ; //check for bonus source 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 ) ;
2023-03-01 23:54:10 +02:00
HasAnotherBonusLimiter ( Bonus : : BonusType bonus , Bonus : : BonusSource src ) ;
HasAnotherBonusLimiter ( Bonus : : BonusType bonus , TBonusSubtype _subtype , Bonus : : BonusSource src ) ;
2010-08-06 13:46:40 +03:00
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
std : : string toString ( ) const override ;
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 ;
2023-03-01 23:54:10 +02:00
h & source ;
h & isSourceRelevant ;
h & sid ;
h & isSourceIDRelevant ;
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 :
2022-09-29 11:44:46 +02:00
TerrainId terrainType ;
2018-04-17 14:59:30 +02:00
CreatureTerrainLimiter ( ) ;
2022-09-29 11:44:46 +02:00
CreatureTerrainLimiter ( TerrainId terrain ) ;
2010-11-20 02:03:31 +02:00
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
std : : string toString ( ) const override ;
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 ;
}
} ;
2023-04-06 17:28:02 +02:00
class DLL_LINKAGE CreatureLevelLimiter : public ILimiter //applies only to creatures of given faction
{
public :
uint32_t minLevel ;
uint32_t maxLevel ;
//accept all levels by default, accept creatures of minLevel <= creature->getLevel() < maxLevel
CreatureLevelLimiter ( uint32_t minLevel = std : : numeric_limits < uint32_t > : : min ( ) , uint32_t maxLevel = std : : numeric_limits < uint32_t > : : max ( ) ) ;
EDecision limit ( const BonusLimitationContext & context ) const override ;
std : : string toString ( ) const override ;
JsonNode toJsonNode ( ) const override ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < ILimiter & > ( * this ) ;
h & minLevel ;
h & maxLevel ;
}
} ;
2023-04-09 03:36:16 +02:00
class DLL_LINKAGE FactionLimiter : public ILimiter //applies only to creatures of given faction
2010-11-20 02:03:31 +02:00
{
public :
2023-04-06 19:03:17 +02:00
FactionID faction ;
2023-04-09 03:36:16 +02:00
FactionLimiter ( FactionID faction = FactionID : : DEFAULT ) ;
2010-11-20 02:03:31 +02:00
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
std : : string toString ( ) const override ;
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 :
2023-04-04 12:36:42 +02:00
EAlignment alignment ;
CreatureAlignmentLimiter ( EAlignment Alignment = EAlignment : : NEUTRAL ) ;
2010-11-20 02:03:31 +02:00
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
std : : string toString ( ) const override ;
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 ;
}
} ;
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 ;
2023-04-09 03:36:16 +02:00
OppositeSideLimiter ( PlayerColor Owner = PlayerColor : : CANNOT_DETERMINE ) ;
2021-03-23 16:47:07 +02:00
2023-03-29 12:16:13 +02:00
EDecision limit ( const BonusLimitationContext & context ) const override ;
2021-03-23 16:47:07 +02:00
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 ) ;
2023-03-29 12:16:13 +02:00
EDecision 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
}
} ;
2023-03-28 01:14:18 +02:00
class DLL_LINKAGE UnitOnHexLimiter : public ILimiter //works only on selected hexes
{
public :
std : : set < BattleHex > applicableHexes ;
UnitOnHexLimiter ( const std : : set < BattleHex > & applicableHexes = { } ) ;
EDecision limit ( const BonusLimitationContext & context ) const override ;
JsonNode toJsonNode ( ) const override ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < ILimiter & > ( * this ) ;
h & applicableHexes ;
}
} ;
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 ( ) ;
2023-02-15 21:19:35 +02:00
extern DLL_LINKAGE CSelectFieldEqual < Bonus : : BonusSource > & targetSourceType ( ) ;
2020-11-11 21:43:40 +02:00
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 ) ;
2023-03-13 23:26:44 +02:00
CSelector DLL_LINKAGE typeSubtypeInfo ( Bonus : : BonusType type , TBonusSubtype subtype , const 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 ;
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 ;
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
// 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 :
2023-03-13 23:26:44 +02:00
virtual ~ IUpdater ( ) = default ;
2017-09-10 05:20:47 +02:00
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 :
2023-03-13 23:26:44 +02:00
int valPer20 = 0 ;
int stepSize = 1 ;
2017-09-10 04:10:50 +02:00
2023-03-13 23:26:44 +02:00
GrowsWithLevelUpdater ( ) = default ;
2017-09-19 00:08:28 +02:00
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 :
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 :
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 ;
} ;
2023-02-18 20:01:32 +02:00
class DLL_LINKAGE ArmyMovementUpdater : public IUpdater
{
public :
2023-03-11 22:09:16 +02:00
si32 base ;
si32 divider ;
si32 multiplier ;
si32 max ;
ArmyMovementUpdater ( ) ;
ArmyMovementUpdater ( int base , int divider , int multiplier , int max ) ;
2023-02-18 20:01:32 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < IUpdater & > ( * this ) ;
2023-03-11 22:09:16 +02:00
h & base ;
h & divider ;
h & multiplier ;
h & max ;
2023-02-18 20:01:32 +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 ;
} ;
2021-09-12 13:30:54 +02:00
class DLL_LINKAGE OwnerUpdater : public IUpdater
{
public :
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 ;
} ;
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_END