2009-02-04 15:40:54 +02:00
# pragma once
2011-12-14 00:23:17 +03:00
# include "GameConstants.h"
2009-02-04 15:40:54 +02:00
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
*
*/
2010-07-12 13:20:25 +03:00
class CCreature ;
2010-05-02 21:20:26 +03:00
class CSpell ;
struct Bonus ;
class CBonusSystemNode ;
2010-07-12 13:20:25 +03:00
class ILimiter ;
2010-11-19 00:22:51 +02:00
class IPropagator ;
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 ;
typedef std : : shared_ptr < ILimiter > TLimiterPtr ;
typedef std : : shared_ptr < IPropagator > TPropagatorPtr ;
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(std::function<bool(const Bonus*)> f) : std::function<bool(const Bonus*)>(std::move(f)) {}
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
2013-01-17 21:15:00 +03:00
2010-05-02 21:20:26 +03:00
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*/ \
BONUS_NAME ( IMPROVED_NECROMANCY ) /*allows Necropolis units other than skeletons to be raised by necromancy*/ \
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 */ \
2011-04-25 12:03:13 +03:00
BONUS_NAME ( SPELL_AFTER_ATTACK ) /* subtype - spell id, value - chance %, additional info % 1000 - level, (additional info)/1000 -> [0 - all attacks, 1 - shot only, 2 - melee only*/ \
2011-07-16 09:42:44 +03:00
BONUS_NAME ( SPELL_BEFORE_ATTACK ) /* subtype - spell id, value - chance %, additional info % 1000 - level, (additional info)/1000 -> [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*/ \
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 ) \
BONUS_NAME ( NON_LIVING ) /*eg. gargoyle*/ \
2011-10-08 12:11:36 +03: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 */ \
BONUS_NAME ( SPECIAL_SECONDARY_SKILL ) /*val = id, additionalInfo = value per level in percent*/ \
BONUS_NAME ( SPECIAL_SPELL_LEV ) /*val = id, additionalInfo = 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*/ \
BONUS_NAME ( SPECIAL_UPGRADE ) /*val = 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 */ \
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 ) \
BONUS_VALUE ( INDEPENDENT_MAX ) /*used for SPELL bonus*/ \
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
2013-01-20 15:06:18 +03:00
struct DLL_LINKAGE 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 ,
UNITL_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 ;
2010-05-12 05:32:56 +03:00
2010-05-02 21:20:26 +03:00
si32 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 ;
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
2013-02-16 17:03:47 +03:00
Bonus ( ui16 Dur , BonusType Type , BonusSource Src , si32 Val , ui32 ID , std : : string Desc , si32 Subtype = - 1 ) ;
Bonus ( ui16 Dur , 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-11-20 02:03:31 +02:00
~ Bonus ( ) ;
2010-02-10 04:56:00 +02:00
// //comparison
// bool operator==(const HeroBonus &other)
// {
// return &other == this;
// //TODO: what is best logic for that?
// }
// bool operator<(const HeroBonus &other)
// {
// return &other < this;
// //TODO: what is best logic for that?
// }
2009-02-04 15:40:54 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2013-01-20 15:06:18 +03:00
h & duration & type & subtype & source & val & sid & description & additionalInfo & turnsRemain & valType & effectRange & limiter & propagator ;
2009-02-04 15:40:54 +02:00
}
2009-02-06 13:15:39 +02:00
2011-09-06 16:59:26 +03:00
static bool compareByAdditionalInfo ( const Bonus * a , const Bonus * b )
{
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
{
2010-11-19 00:06:56 +02:00
return hb - > duration & Bonus : : UNITL_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-05-02 21:20:26 +03:00
static bool IsFrom ( const Bonus & hb , ui8 source , ui32 id ) //if id==0xffffff then id doesn't matter
2009-04-04 01:34:31 +03:00
{
2011-02-20 20:32:39 +02:00
return hb . source = = source & & ( id = = 0xffffff | | hb . sid = = id ) ;
2009-04-04 01:34:31 +03:00
}
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 ChangeBonusVal ( const ui32 newVal )
{
val = newVal ;
}
inline void operator + = ( const ui32 Val ) //no return
{
val + = Val ;
}
2010-05-02 21:20:26 +03:00
const CSpell * sourceSpell ( ) const ;
2010-02-10 04:56:00 +02:00
2010-05-02 21:20:26 +03:00
std : : string Description ( ) const ;
2010-11-20 02:03:31 +02:00
2013-01-20 15:06:18 +03:00
Bonus * addLimiter ( TLimiterPtr Limiter ) ; //returns this for convenient chain-calls
Bonus * addPropagator ( TPropagatorPtr Propagator ) ; //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
2011-07-13 21:39:02 +03:00
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE BonusList
2010-02-10 04:56:00 +02:00
{
2011-07-13 21:39:02 +03:00
private :
2012-09-20 19:55:21 +03:00
typedef std : : vector < Bonus * > TInternalContainer ;
TInternalContainer bonuses ;
2011-07-13 21:39:02 +03:00
bool belongsToTree ;
2010-05-02 21:20:26 +03:00
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 ) ;
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
std : : vector < Bonus * > : : size_type size ( ) const { return bonuses . size ( ) ; }
void push_back ( Bonus * const & x ) ;
2011-07-16 16:57:25 +03:00
std : : vector < Bonus * > : : 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 ( ) ; }
2013-06-26 14:18:27 +03:00
void resize ( std : : vector < Bonus * > : : size_type sz , Bonus * c = nullptr ) ;
2011-07-13 21:39:02 +03:00
void insert ( std : : vector < Bonus * > : : iterator position , std : : vector < Bonus * > : : size_type n , Bonus * const & x ) ;
2011-07-14 02:36:37 +03:00
Bonus * const & operator [ ] ( std : : vector < Bonus * > : : size_type n ) { return bonuses [ n ] ; }
Bonus * const & operator [ ] ( std : : vector < Bonus * > : : size_type n ) const { return bonuses [ n ] ; }
Bonus * const & back ( ) { return bonuses . back ( ) ; }
Bonus * const & front ( ) { return bonuses . front ( ) ; }
Bonus * const & back ( ) const { return bonuses . back ( ) ; }
Bonus * const & 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
2011-07-13 21:39:02 +03:00
std : : vector < Bonus * > : : const_iterator begin ( ) const { return bonuses . begin ( ) ; }
std : : vector < Bonus * > : : const_iterator end ( ) const { return bonuses . end ( ) ; }
std : : vector < Bonus * > : : size_type operator - = ( Bonus * const & i ) ;
// BonusList functions
int totalValue ( ) const ; //subtype -> subtype of bonus, if -1 then any
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
2011-07-13 21:39:02 +03:00
Bonus * getFirst ( const CSelector & select ) ;
const Bonus * getFirst ( const CSelector & select ) const ;
int valOfBonuses ( const CSelector & select ) const ;
2010-02-10 04:56:00 +02:00
2012-03-06 19:59:55 +03:00
//void limit(const CBonusSystemNode &node); //erases bonuses using limitor
2011-07-13 21:39:02 +03:00
void eliminateDuplicates ( ) ;
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
{
2011-07-13 21:39:02 +03:00
Bonus * b = bonuses [ i ] ;
2011-06-25 16:53:15 +03:00
if ( ! pred ( b ) )
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 ) ;
2010-07-12 13:20:25 +03:00
2010-02-10 04:56:00 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2011-07-13 21:39:02 +03:00
h & static_cast < std : : vector < Bonus * > & > ( 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 ( ) ;
}
//friend inline std::vector<Bonus*>::iterator range_begin(BonusList & x);
//friend inline std::vector<Bonus*>::iterator range_end(BonusList & x);
2010-04-03 06:33:46 +03:00
} ;
2011-09-06 16:59:26 +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
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE IPropagator
2010-11-19 00:22:51 +02:00
{
public :
virtual ~ IPropagator ( ) ;
2011-02-21 06:13:00 +02:00
virtual bool shouldBeAttached ( CBonusSystemNode * dest ) ;
//virtual CBonusSystemNode *getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild); //called when red relation between parent-childrem is established / removed
template < typename Handler > void serialize ( Handler & h , const int version )
{ }
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CPropagatorNodeType : public IPropagator
2011-02-21 06:13:00 +02:00
{
2013-02-02 22:28:39 +03:00
int nodeType ; //CBonusSystemNode::ENodeTypes
2011-02-21 06:13:00 +02:00
public :
CPropagatorNodeType ( ) ;
2013-02-02 22:28:39 +03:00
CPropagatorNodeType ( int NodeType ) ;
2015-10-12 15:47:10 +02:00
bool shouldBeAttached ( CBonusSystemNode * dest ) override ;
2013-06-26 14:18:27 +03:00
//CBonusSystemNode *getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild) override;
2011-02-21 06:13:00 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & nodeType ;
}
2010-11-19 00:22:51 +02:00
} ;
2012-03-06 19:59:55 +03:00
struct BonusLimitationContext
{
const Bonus * b ;
const CBonusSystemNode & node ;
const BonusList & alreadyAccepted ;
} ;
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)
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
{
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
2013-06-26 14:18:27 +03:00
virtual const TBonusListPtr 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 getBonusesCount ( const CSelector & selector , const std : : string & cachingStr = " " ) const ;
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 ;
2011-09-06 16:59:26 +03:00
const TBonusListPtr getBonuses ( const CSelector & selector , const CSelector & limit , const std : : string & cachingStr = " " ) const ;
const TBonusListPtr getBonuses ( const CSelector & selector , const std : : string & cachingStr = " " ) const ;
2010-11-13 22:26:15 +02:00
2012-09-20 19:55:21 +03:00
const TBonusListPtr getAllBonuses ( ) const ;
const Bonus * getBonus ( const CSelector & selector ) const ; //returns any bonus visible on node that matches (or nullptr if none matches)
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 ;
int getBonusesCount ( Bonus : : BonusSource from , int id ) const ;
2011-02-27 21:58:14 +02:00
//various hlp functions for non-trivial values
2010-12-12 01:11:26 +02:00
ui32 getMinDamage ( ) const ; //used for stacks and creatures only
ui32 getMaxDamage ( ) const ;
2010-05-02 21:20:26 +03:00
int MoraleVal ( ) const ; //range [-3, +3]
int LuckVal ( ) const ; //range [-3, +3]
si32 Attack ( ) const ; //get attack of stack with all modificators
si32 Defense ( bool withFrenzy = true ) const ; //get defense of stack with all modificators
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
2012-09-20 19:55:21 +03:00
const Bonus * getEffect ( ui16 id , int turn = 0 ) const ; //effect id (SP)
ui8 howManyEffectsSet ( ui16 id ) const ; //returns amount of effects with given id set for this stack
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 ;
2011-09-06 16:59:26 +03:00
const TBonusListPtr getSpellBonuses ( ) const ;
2011-02-27 21:58:14 +02:00
} ;
2010-05-02 21:20:26 +03:00
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CBonusSystemNode : public IBonusBearer
2011-02-27 21:58:14 +02:00
{
2013-02-02 22:28:39 +03:00
public :
enum ENodeTypes
{
2014-03-30 00:39:19 +03:00
UNKNOWN , STACK_INSTANCE , STACK_BATTLE , SPECIALTY , ARTIFACT , CREATURE , ARTIFACT_INSTANCE , HERO , PLAYER , TEAM ,
TOWN_AND_VISITOR , BATTLE , COMMANDER , GLOBAL_EFFECTS
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 ;
2012-09-15 22:16:16 +03:00
static const bool cachingEnabled ;
2011-06-25 16:53:15 +03:00
mutable BonusList cachedBonuses ;
2012-09-15 22:16:16 +03:00
mutable int cachedLast ;
2011-06-25 16:53:15 +03:00
static int treeChanged ;
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 ;
2011-06-25 16:53:15 +03:00
2012-03-06 19:59:55 +03:00
void getBonusesRec ( BonusList & out , const CSelector & selector , const CSelector & limit ) const ;
void getAllBonusesRec ( BonusList & out ) const ;
2013-06-26 14:18:27 +03:00
const TBonusListPtr getAllBonusesWithoutCaching ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = nullptr ) 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 ( ) ;
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
2015-10-12 15:47:10 +02:00
const TBonusListPtr 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),
2012-09-20 19:55:21 +03:00
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)
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 ) ;
2012-09-20 19:55:21 +03:00
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 ( ) ;
2012-12-13 17:27:33 +03:00
virtual void addNewBonus ( Bonus * b ) ; //b will be deleted with destruction of node
2012-04-22 22:56:03 +03:00
void accumulateBonus ( 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 ) ;
void propagateBonus ( Bonus * b ) ;
2011-02-21 06:13:00 +02:00
void unpropagateBonus ( Bonus * b ) ;
2010-11-20 02:03:31 +02:00
//void addNewBonus(const Bonus &b); //b will copied
2010-11-19 00:06:56 +02:00
void removeBonus ( Bonus * b ) ;
2011-02-21 06:13:00 +02:00
void newRedDescendant ( CBonusSystemNode * descendant ) ; //propagation needed
void removedRedDescendant ( CBonusSystemNode * descendant ) ; //de-propagation needed
2011-03-01 12:19:05 +02:00
void battleTurnPassed ( ) ; //updates count of remaining turns and removed outdated bonuses
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 ;
2012-03-06 19:59:55 +03:00
//bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
2010-11-20 02:03:31 +02:00
2010-11-19 00:06:56 +02:00
void popBonuses ( const CSelector & s ) ;
2015-11-09 13:18:36 +02:00
void updateBonuses ( const CSelector & s ) ;
2013-06-17 18:45:55 +03:00
virtual std : : string bonusToString ( const Bonus * bonus , bool description ) const { return " " ; } ; //description or bonus name
2010-12-12 01:11:26 +02:00
virtual std : : string nodeName ( ) const ;
2011-03-01 12:19:05 +02:00
2011-02-04 16:58:14 +02:00
void deserializationFix ( ) ;
2011-02-23 05:57:45 +02:00
void exportBonus ( 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 ;
BonusList & getExportedBonusList ( ) ;
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 ( ) ;
2010-04-03 06:33:46 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2011-02-23 05:57:45 +02:00
h & /*bonuses & */ 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
}
} ;
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)
2013-02-02 01:04:25 +03:00
DLL_LINKAGE int getCount ( const CBonusSystemNode * obj , Bonus : : BonusSource from , int id ) ;
2012-09-15 22:16:16 +03:00
}
2010-05-02 21:20:26 +03:00
2011-02-22 13:52:36 +02:00
/// generates HeroBonus from given data
2011-01-20 21:57:12 +02:00
inline Bonus makeFeatureVal ( Bonus : : BonusType type , ui8 duration , si16 subtype , si32 value , Bonus : : BonusSource source , ui16 turnsRemain = 0 , si32 additionalInfo = 0 )
2010-05-02 21:20:26 +03:00
{
2011-01-20 21:57:12 +02:00
Bonus sf ;
sf . type = type ;
sf . duration = duration ;
sf . source = source ;
sf . turnsRemain = turnsRemain ;
sf . subtype = subtype ;
sf . val = value ;
sf . additionalInfo = additionalInfo ;
2010-05-02 21:20:26 +03:00
return sf ;
}
2013-02-25 15:18:45 +03:00
///generates HeroBonus from given data
2011-01-20 21:57:12 +02:00
inline Bonus * makeFeature ( Bonus : : BonusType type , ui8 duration , si16 subtype , si32 value , Bonus : : BonusSource source , ui16 turnsRemain = 0 , si32 additionalInfo = 0 )
{
return new Bonus ( makeFeatureVal ( type , duration , subtype , value , source , turnsRemain , additionalInfo ) ) ;
}
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)
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 >
class CSelectFieldAny //allows to ignore value of certain field, that is to accept any value
{
T Bonus : : * ptr ;
public :
CSelectFieldAny ( T Bonus : : * Ptr )
: ptr ( Ptr )
{
}
bool operator ( ) ( const Bonus * bonus ) const
{
return true ;
}
CSelectFieldAny & operator ( ) ( )
{
return * this ;
}
} ;
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 ;
}
} ;
2013-01-20 15:06:18 +03:00
//Stores multiple limiters. If any of them fails -> bonus is dropped.
class DLL_LINKAGE LimiterList : public ILimiter
{
std : : vector < TLimiterPtr > limiters ;
public :
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) const override ;
2013-01-20 15:06:18 +03:00
void add ( TLimiterPtr limiter ) ;
} ;
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 ( ) ;
2013-02-02 22:28:39 +03: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 ;
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 ) ;
2010-07-12 13:20:25 +03:00
h & creature & includeUpgrades ;
}
} ;
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 ;
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 ) ;
2010-08-06 13:46:40 +03:00
h & type & subtype & isSubtypeRelevant ;
}
} ;
2012-09-15 22:16:16 +03:00
class DLL_LINKAGE CreatureNativeTerrainLimiter : public ILimiter //applies only to creatures that are on their native terrain
2010-11-20 02:03:31 +02:00
{
public :
2013-02-02 22:28:39 +03:00
int terrainType ;
2010-11-20 02:03:31 +02:00
CreatureNativeTerrainLimiter ( ) ;
CreatureNativeTerrainLimiter ( int TerrainType ) ;
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) 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 :
si8 faction ;
CreatureFactionLimiter ( ) ;
CreatureFactionLimiter ( int TerrainType ) ;
2013-06-26 14:18:27 +03:00
int limit ( const BonusLimitationContext & context ) 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 ;
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 ;
}
} ;
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 ) ;
2011-02-12 18:12:48 +02:00
h & minRank & maxRank ;
2011-02-11 10:20:26 +02:00
}
} ;
2010-11-20 02:03:31 +02:00
const CCreature * retrieveCreature ( const CBonusSystemNode * node ) ;
2010-05-02 21:20:26 +03:00
namespace Selector
{
2013-02-16 17:03:47 +03:00
extern DLL_LINKAGE CSelectFieldEqual < Bonus : : BonusType > type ;
2011-12-14 00:23:17 +03:00
extern DLL_LINKAGE CSelectFieldEqual < TBonusSubtype > subtype ;
extern DLL_LINKAGE CSelectFieldEqual < si32 > info ;
2013-02-02 01:04:25 +03:00
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 ;
2013-02-26 12:36:21 +03:00
extern DLL_LINKAGE CSelectFieldAny < Bonus : : LimitEffect > anyRange ;
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 ) ;
CSelector DLL_LINKAGE typeSubtypeInfo ( Bonus : : BonusType type , TBonusSubtype subtype , si32 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 ) ;
2011-12-14 00:23:17 +03:00
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 ) ;
2011-12-14 00:23:17 +03:00
bool DLL_LINKAGE positiveSpellEffects ( const Bonus * b ) ;
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 ;
// 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 ) ;
if ( belongsToTree )
2015-04-11 07:13:28 +02:00
CBonusSystemNode : : treeHasChanged ( ) ;
2011-07-14 02:36:37 +03:00
}
2011-07-13 21:39:02 +03:00
// Extensions for BOOST_FOREACH to enable iterating of BonusList objects
2013-06-29 16:05:48 +03:00
/*namespace boost
2011-07-13 21:39:02 +03:00
{
template < >
struct range_mutable_iterator < BonusList >
{
typedef std : : vector < Bonus * > : : iterator type ;
} ;
template < >
2011-07-14 02:36:37 +03:00
struct range_const_iterator < BonusList >
2011-07-13 21:39:02 +03:00
{
typedef std : : vector < Bonus * > : : const_iterator type ;
} ;
2013-06-29 16:05:48 +03:00
} */