2009-02-04 15:40:54 +02:00
# pragma once
# include "../global.h"
# include <string>
2010-05-02 21:20:26 +03:00
# include <set>
# include <boost/function.hpp>
2011-05-04 05:37:27 +03:00
# include <boost/shared_ptr.hpp>
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 ;
2010-05-02 21:20:26 +03:00
typedef std : : vector < std : : pair < int , std : : string > > TModDescr ; //modifiers values and their descriptions
typedef std : : set < CBonusSystemNode * > TNodes ;
typedef std : : set < const CBonusSystemNode * > TCNodes ;
2010-11-20 19:36:02 +02:00
typedef std : : vector < CBonusSystemNode * > TNodesVector ;
2010-11-19 00:06:56 +02:00
typedef boost : : function < bool ( const Bonus * ) > CSelector ;
2010-05-02 21:20:26 +03:00
namespace PrimarySkill
{
enum { ATTACK , DEFENSE , SPELL_POWER , KNOWLEDGE } ;
}
# define BONUS_LIST \
BONUS_NAME ( NONE ) \
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*/ \
BONUS_NAME ( SIGHT_RADIOUS ) \
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 ) /*%*/ \
BONUS_NAME ( STACKS_SPEED ) /*additional info - percent of speed bonus applied after direct bonuses; >0 - added, <0 - substracted to this part*/ \
2010-05-15 18:00:19 +03:00
BONUS_NAME ( FLYING_MOVEMENT ) /*subtype 1 - without penalty, 2 - with penalty*/ \
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 ) \
2010-05-15 18:00:19 +03:00
BONUS_NAME ( WATER_WALKING ) /*subtype 1 - without penalty, 2 - with penalty*/ \
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*/ \
BONUS_NAME ( ENEMY_CANT_ESCAPE ) /*for shackles of war*/ \
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*/ \
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*/ \
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*/ \
BONUS_NAME ( RANDOM_GENIE_SPELLCASTER ) /*eg. master genie*/ \
BONUS_NAME ( BLOCKS_RETALIATION ) /*eg. naga*/ \
BONUS_NAME ( SPELL_IMMUNITY ) /*subid - spell id*/ \
BONUS_NAME ( MANA_CHANNELING ) /*value in %, eg. familiar*/ \
BONUS_NAME ( SPELL_LIKE_ATTACK ) /*value - spell id; range is taken from spell, but damage from creature; eg. magog*/ \
BONUS_NAME ( THREE_HEADED_ATTACK ) /*eg. cerberus*/ \
BONUS_NAME ( DAEMON_SUMMONING ) /*pit lord*/ \
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 ) \
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*/ \
BONUS_NAME ( SPELLCASTER ) /*subtype - spell id, value - level of school, additional info - spell power*/ \
BONUS_NAME ( CATAPULT ) \
BONUS_NAME ( ENEMY_DEFENCE_REDUCTION ) /*in % (value) eg. behemots*/ \
BONUS_NAME ( GENERAL_DAMAGE_REDUCTION ) /* shield / air shield effect */ \
BONUS_NAME ( GENERAL_ATTACK_REDUCTION ) /*eg. while stoned or blinded - in %, subtype: -1 - any damage, 0 - melee damage, 1 - ranged damage*/ \
BONUS_NAME ( ATTACKS_ALL_ADJACENT ) /*eg. hydra*/ \
BONUS_NAME ( MORE_DAMAGE_FROM_SPELL ) /*value - damage increase in %, subtype - spell id*/ \
BONUS_NAME ( CASTS_SPELL_WHEN_KILLED ) /*similar to spell after attack*/ \
BONUS_NAME ( FEAR ) \
BONUS_NAME ( FEARLESS ) \
BONUS_NAME ( NO_DISTANCE_PENALTY ) \
BONUS_NAME ( NO_OBSTACLES_PENALTY ) \
BONUS_NAME ( SELF_LUCK ) /*halfling*/ \
BONUS_NAME ( ENCHANTER ) \
BONUS_NAME ( HEALER ) \
BONUS_NAME ( SIEGE_WEAPON ) \
BONUS_NAME ( HYPNOTIZED ) \
BONUS_NAME ( ADDITIONAL_RETALIATION ) /*value - number of additional retaliations*/ \
BONUS_NAME ( MAGIC_MIRROR ) /* value - chance of redirecting in %*/ \
BONUS_NAME ( ALWAYS_MINIMUM_DAMAGE ) /*unit does its minimum damage from range; subtype: -1 - any attack, 0 - melee, 1 - ranged, value: additional damage, additional info - multiplicative anti-bonus for dmg in % [eg 20 means that creature will inflict 80% of normal dmg]*/ \
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*/ \
BONUS_NAME ( NOT_ACTIVE ) \
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*/ \
BONUS_NAME ( CASTS ) /*how many times creature can cast activated spell*/
2010-05-02 21:20:26 +03:00
2011-02-22 13:52:36 +02:00
/// Struct for handling bonuses of several types. Can be transfered to any hero
2010-05-02 21:20:26 +03:00
struct DLL_EXPORT Bonus
2009-02-04 15:40:54 +02:00
{
2009-04-04 01:34:31 +03:00
enum BonusType
{
2010-05-02 21:20:26 +03:00
# define BONUS_NAME(x) x,
BONUS_LIST
# undef BONUS_NAME
} ;
enum BonusDuration //when bonus is automatically removed
{
PERMANENT = 1 ,
ONE_BATTLE = 2 , //at the end of battle
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*/
STACK_GETS_TURN = 256 /*removed when stack gets its turn - used for defensive stance*/
2010-05-02 21:20:26 +03:00
} ;
enum BonusSource
{
2011-01-20 21:57:12 +02:00
ARTIFACT ,
ARTIFACT_INSTANCE ,
OBJECT ,
2011-04-25 12:03:13 +03:00
CREATURE_ABILITY ,
2010-05-02 21:20:26 +03:00
TERRAIN_NATIVE ,
TERRAIN_OVERLAY ,
SPELL_EFFECT ,
TOWN_STRUCTURE ,
HERO_BASE_SKILL ,
SECONDARY_SKILL ,
2010-07-06 10:32:40 +03:00
HERO_SPECIAL ,
2010-07-31 16:55:05 +03:00
ARMY ,
2010-08-24 17:26:57 +03:00
CAMPAIGN_BONUS ,
2011-01-18 19:23:31 +02:00
SPECIAL_WEEK ,
2011-02-06 10:32:05 +02:00
STACK_EXPERIENCE ,
2011-02-21 15:27:31 +02:00
OTHER /*used for defensive stance and default value of spell level limit*/
2010-05-02 21:20:26 +03:00
} ;
enum LimitEffect
{
NO_LIMIT = 0 ,
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
{
ADDITIVE_VALUE ,
BASE_NUMBER ,
PERCENT_TO_ALL ,
2010-08-05 12:11:38 +03:00
PERCENT_TO_BASE ,
2011-02-12 18:12:48 +02:00
INDEPENDENT_MAX , //used for SPELL bonus
INDEPENDENT_MIN //used for SECONDARY_SKILL_PREMY bonus
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
2010-05-02 21:20:26 +03:00
si16 turnsRemain ; //used if duration is N_TURNS or N_DAYS
TBonusType type ; //uses BonusType values - says to what is this bonus - 1 byte
TBonusSubtype subtype ; //-1 if not applicable - 4 bytes
ui8 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
2010-08-05 12:11:38 +03:00
ui8 valType ; //by ValueType enum
2010-05-12 05:32:56 +03:00
2010-05-02 21:20:26 +03:00
si32 additionalInfo ;
ui8 effectRange ; //if not NO_LIMIT, bonus will be ommitted by default
2010-11-20 02:03:31 +02:00
boost : : shared_ptr < ILimiter > limiter ;
boost : : shared_ptr < IPropagator > propagator ;
2010-07-12 13:20:25 +03:00
2009-02-04 15:40:54 +02:00
std : : string description ;
2011-02-21 06:24:46 +02:00
Bonus ( ui16 Dur , ui8 Type , ui8 Src , si32 Val , ui32 ID , std : : string Desc , si32 Subtype = - 1 ) ;
Bonus ( ui16 Dur , ui8 Type , ui8 Src , si32 Val , ui32 ID , si32 Subtype = - 1 , ui8 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 )
{
2011-02-23 05:57:45 +02: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
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
}
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
}
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
Bonus * addLimiter ( ILimiter * Limiter ) ; //returns this for convenient chain-calls
2011-02-21 06:13:00 +02:00
Bonus * addPropagator ( IPropagator * Propagator ) ; //returns this for convenient chain-calls
Bonus * addLimiter ( boost : : shared_ptr < ILimiter > Limiter ) ; //returns this for convenient chain-calls
Bonus * addPropagator ( boost : : shared_ptr < IPropagator > Propagator ) ; //returns this for convenient chain-calls
2009-02-06 13:15:39 +02:00
} ;
2010-02-10 04:56:00 +02:00
2010-07-12 13:20:25 +03:00
DLL_EXPORT std : : ostream & operator < < ( std : : ostream & out , const Bonus & bonus ) ;
2011-06-25 16:53:15 +03:00
class BonusList : public std : : vector < Bonus * >
2010-02-10 04:56:00 +02:00
{
public :
2010-05-02 21:20:26 +03:00
int DLL_EXPORT totalValue ( ) const ; //subtype -> subtype of bonus, if -1 then any
2011-06-25 16:53:15 +03:00
void DLL_EXPORT getBonuses ( boost : : shared_ptr < BonusList > out , const CSelector & selector , const CSelector & limit , const bool caching = false ) const ;
2010-05-02 21:20:26 +03:00
void DLL_EXPORT getModifiersWDescr ( TModDescr & out ) const ;
2011-06-25 16:53:15 +03:00
void DLL_EXPORT getBonuses ( boost : : shared_ptr < 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
DLL_EXPORT Bonus * getFirst ( const CSelector & select ) ;
DLL_EXPORT const Bonus * getFirst ( const CSelector & select ) const ;
2010-02-10 04:56:00 +02:00
2010-07-12 13:20:25 +03:00
void limit ( const CBonusSystemNode & node ) ; //erases bonuses using limitor
2011-02-27 13:26:18 +02:00
void DLL_EXPORT eliminateDuplicates ( ) ;
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 ;
for ( int i = 0 ; i < this - > size ( ) ; i + + )
{
Bonus * b = ( * this ) [ i ] ;
if ( ! pred ( b ) )
newList . push_back ( b ) ;
}
this - > clear ( ) ;
this - > resize ( newList . size ( ) ) ;
std : : copy ( newList . begin ( ) , newList . end ( ) , this - > begin ( ) ) ;
}
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-06-25 16:53:15 +03:00
h & static_cast < std : : vector < Bonus * > & > ( * this ) ;
2010-02-10 04:56:00 +02:00
}
2010-04-03 06:33:46 +03:00
} ;
2010-07-12 13:20:25 +03:00
DLL_EXPORT std : : ostream & operator < < ( std : : ostream & out , const BonusList & bonusList ) ;
2010-11-19 00:22:51 +02:00
class DLL_EXPORT IPropagator
{
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 )
{ }
} ;
class DLL_EXPORT CPropagatorNodeType : public IPropagator
{
ui8 nodeType ;
public :
CPropagatorNodeType ( ) ;
CPropagatorNodeType ( ui8 NodeType ) ;
bool shouldBeAttached ( CBonusSystemNode * dest ) ;
//CBonusSystemNode *getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild) OVERRIDE;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & nodeType ;
}
2010-11-19 00:22:51 +02:00
} ;
2010-07-12 13:20:25 +03:00
class DLL_EXPORT ILimiter
{
public :
virtual ~ ILimiter ( ) ;
2010-11-19 00:06:56 +02:00
virtual bool limit ( const Bonus * b , const CBonusSystemNode & node ) const ; //return true to drop the bonus
2010-07-12 13:20:25 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{ }
} ;
2011-02-27 21:58:14 +02:00
class DLL_EXPORT 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
// * root is node on which call was made (NULL will be replaced with this)
2010-11-13 22:26:15 +02:00
//interface
2011-06-25 16:53:15 +03:00
virtual const boost : : shared_ptr < BonusList > getAllBonuses ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = NULL ) const = 0 ;
virtual void setCachingStr ( const std : : string & request ) const ;
2010-11-13 22:26:15 +02:00
void getModifiersWDescr ( TModDescr & out , const CSelector & selector ) const ; //out: pairs<modifier value, modifier description>
int getBonusesCount ( const CSelector & selector ) const ;
int valOfBonuses ( const CSelector & selector ) const ;
bool hasBonus ( const CSelector & selector ) const ;
2011-06-25 16:53:15 +03:00
const boost : : shared_ptr < BonusList > getBonuses ( const CSelector & selector , const CSelector & limit ) const ;
const boost : : shared_ptr < BonusList > getBonuses ( const CSelector & selector ) const ;
2010-11-13 22:26:15 +02:00
2010-05-02 21:20:26 +03:00
//legacy interface
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)
bool hasBonusFrom ( ui8 source , ui32 sourceID ) const ;
void getModifiersWDescr ( TModDescr & out , Bonus : : BonusType type , int subtype = - 1 ) const ; //out: pairs<modifier value, modifier description>
2010-04-03 06:33:46 +03:00
int getBonusesCount ( int 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
ui16 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 ;
2010-05-02 21:20:26 +03:00
2011-02-27 21:58:14 +02:00
si32 manaLimit ( ) const ; //maximum mana value for this hero (basically 10*knowledge)
int getPrimSkillLevel ( int id ) const ; //0-attack, 1-defence, 2-spell power, 3-knowledge
2011-06-25 16:53:15 +03:00
const boost : : shared_ptr < BonusList > getSpellBonuses ( ) const ;
2011-02-27 21:58:14 +02:00
} ;
2010-05-02 21:20:26 +03:00
2011-02-27 21:58:14 +02:00
class DLL_EXPORT CBonusSystemNode : public IBonusBearer
{
2011-06-25 16:53:15 +03:00
static const bool cachingEnabled ;
mutable BonusList cachedBonuses ;
mutable int cachedLast ;
static int treeChanged ;
// Setting a value to cachingStr before getting any bonuses caches the result for later requests.
// This string needs to be unique, that's why it has to be setted in the following manner:
// [property key]_[value] => only for selector
mutable std : : string cachingStr ;
2011-06-28 17:19:16 +03:00
mutable std : : map < std : : string , boost : : shared_ptr < BonusList > > cachedRequests ;
2011-06-25 16:53:15 +03:00
void getAllBonusesRec ( boost : : shared_ptr < BonusList > out , const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = NULL , const bool caching = false ) const ;
2011-02-27 21:58:14 +02:00
public :
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 ;
ui8 nodeType ;
std : : string description ;
2011-06-25 16:53:15 +03:00
explicit CBonusSystemNode ( ) ;
2011-02-27 21:58:14 +02:00
virtual ~ CBonusSystemNode ( ) ;
2011-06-25 16:53:15 +03:00
const boost : : shared_ptr < BonusList > getAllBonuses ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = NULL ) const ;
void setCachingStr ( const std : : string & request ) const ;
2011-02-27 21:58:14 +02:00
void getParents ( TCNodes & out ) const ; //retrieves list of parent nodes (nodes to inherit bonuses from),
2010-12-17 20:47:07 +02:00
const Bonus * getBonus ( 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 ) ;
void getRedChildren ( TNodes & out ) ;
void getRedDescendants ( TNodes & out ) ;
2010-05-02 21:20:26 +03:00
Bonus * getBonus ( 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 ( ) ;
2010-11-19 00:06:56 +02:00
void addNewBonus ( Bonus * b ) ; //b will be deleted with destruction of node
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 ;
2010-11-20 02:03:31 +02:00
bool isLimitedOnUs ( Bonus * b ) const ; //if bonus should be removed from list acquired from this node
2010-11-19 00:06:56 +02:00
void popBonuses ( const CSelector & s ) ;
2011-02-27 13:26:18 +02:00
virtual std : : string bonusToString ( 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 ( ) ;
2010-11-13 22:26:15 +02:00
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
}
2010-07-12 13:20:25 +03:00
enum ENodeTypes
{
2011-02-21 06:13:00 +02:00
UNKNOWN , STACK_INSTANCE , STACK_BATTLE , SPECIALITY , ARTIFACT , CREATURE , ARTIFACT_INSTANCE , HERO , PLAYER , TEAM
2010-07-12 13:20:25 +03:00
} ;
2010-04-03 06:33:46 +03:00
} ;
namespace NBonus
{
//set of methods that may be safely called with NULL objs
2010-05-02 21:20:26 +03:00
DLL_EXPORT int valOf ( const CBonusSystemNode * obj , Bonus : : BonusType type , int subtype = - 1 ) ; //subtype -> subtype of bonus, if -1 then any
DLL_EXPORT bool hasOfType ( const CBonusSystemNode * obj , Bonus : : BonusType type , int subtype = - 1 ) ; //determines if hero has a bonus of given type (and optionally subtype)
//DLL_EXPORT const HeroBonus * get(const CBonusSystemNode *obj, int from, int id );
DLL_EXPORT void getModifiersWDescr ( const CBonusSystemNode * obj , TModDescr & out , Bonus : : BonusType type , int subtype = - 1 ) ; //out: pairs<modifier value, modifier description>
2010-04-03 06:33:46 +03:00
DLL_EXPORT int getCount ( const CBonusSystemNode * obj , int from , int id ) ;
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 ;
}
2011-01-20 21:57:12 +02:00
//generates HeroBonus from given data
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
class DLL_EXPORT CSelectorsConjunction
{
const CSelector first , second ;
public :
CSelectorsConjunction ( const CSelector & First , const CSelector & Second )
: first ( First ) , second ( Second )
{
}
2010-11-19 00:06:56 +02:00
bool operator ( ) ( const Bonus * bonus ) const
2010-05-02 21:20:26 +03:00
{
return first ( bonus ) & & second ( bonus ) ;
}
} ;
CSelector DLL_EXPORT operator & & ( const CSelector & first , const CSelector & second ) ;
2010-08-30 21:06:17 +03:00
class DLL_EXPORT CSelectorsAlternative
{
const CSelector first , second ;
public :
CSelectorsAlternative ( const CSelector & First , const CSelector & Second )
: first ( First ) , second ( Second )
{
}
2010-11-19 00:06:56 +02:00
bool operator ( ) ( const Bonus * bonus ) const
2010-08-30 21:06:17 +03:00
{
return first ( bonus ) | | second ( bonus ) ;
}
} ;
CSelector DLL_EXPORT operator | | ( const CSelector & first , const CSelector & second ) ;
2010-05-02 21:20:26 +03:00
template < typename T >
class CSelectFieldEqual
{
T Bonus : : * ptr ;
T val ;
public :
CSelectFieldEqual ( T Bonus : : * Ptr , const T & Val )
: ptr ( Ptr ) , val ( Val )
{
}
2010-11-19 00:06:56 +02:00
bool operator ( ) ( const Bonus * bonus ) const
2010-05-02 21:20:26 +03:00
{
2010-11-19 00:06:56 +02:00
return bonus - > * ptr = = val ;
2010-05-02 21:20:26 +03:00
}
CSelectFieldEqual & operator ( ) ( const T & setVal )
{
val = setVal ;
return * this ;
}
} ;
2010-11-20 02:03:31 +02:00
class DLL_EXPORT 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
2010-11-19 00:06:56 +02:00
| | ! ( bonus - > duration & Bonus : : N_TURNS ) //so do every not expriing after N-turns effect
| | bonus - > turnsRemain > turnsRequested ;
2010-05-02 21:20:26 +03:00
}
CWillLastTurns & operator ( ) ( const int & setVal )
{
turnsRequested = setVal ;
return * this ;
}
} ;
2010-11-20 02:03:31 +02:00
class DLL_EXPORT 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 ;
ui8 includeUpgrades ;
CCreatureTypeLimiter ( ) ;
CCreatureTypeLimiter ( const CCreature & Creature , ui8 IncludeUpgrades = true ) ;
2010-11-19 00:06:56 +02:00
bool limit ( const Bonus * b , const CBonusSystemNode & node ) const OVERRIDE ;
2010-07-12 13:20:25 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & creature & includeUpgrades ;
}
} ;
2010-08-06 13:46:40 +03:00
2010-11-20 02:03:31 +02:00
class DLL_EXPORT HasAnotherBonusLimiter : public ILimiter //applies only to nodes that have another bonus working
2010-08-06 13:46:40 +03:00
{
public :
TBonusType type ;
TBonusSubtype subtype ;
ui8 isSubtypeRelevant ; //check for subtype only if this is true
2010-11-20 02:03:31 +02:00
HasAnotherBonusLimiter ( TBonusType bonus = Bonus : : NONE ) ;
2010-08-06 13:46:40 +03:00
HasAnotherBonusLimiter ( TBonusType bonus , TBonusSubtype _subtype ) ;
2010-11-19 00:06:56 +02:00
bool limit ( const Bonus * b , const CBonusSystemNode & node ) const OVERRIDE ;
2010-08-06 13:46:40 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & type & subtype & isSubtypeRelevant ;
}
} ;
2010-11-20 02:03:31 +02:00
class DLL_EXPORT CreatureNativeTerrainLimiter : public ILimiter //applies only to creatures that are on their native terrain
{
public :
si8 terrainType ;
CreatureNativeTerrainLimiter ( ) ;
CreatureNativeTerrainLimiter ( int TerrainType ) ;
bool limit ( const Bonus * b , const CBonusSystemNode & node ) const OVERRIDE ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & terrainType ;
}
} ;
class DLL_EXPORT CreatureFactionLimiter : public ILimiter //applies only to creatures of given faction
{
public :
si8 faction ;
CreatureFactionLimiter ( ) ;
CreatureFactionLimiter ( int TerrainType ) ;
bool limit ( const Bonus * b , const CBonusSystemNode & node ) const OVERRIDE ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & faction ;
}
} ;
class DLL_EXPORT CreatureAlignmentLimiter : public ILimiter //applies only to creatures of given alignment
{
public :
si8 alignment ;
CreatureAlignmentLimiter ( ) ;
CreatureAlignmentLimiter ( si8 Alignment ) ;
bool limit ( const Bonus * b , const CBonusSystemNode & node ) const OVERRIDE ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & alignment ;
}
} ;
2011-02-21 06:13:00 +02:00
class DLL_EXPORT StackOwnerLimiter : public ILimiter //applies only to creatures of given alignment
{
public :
ui8 owner ;
StackOwnerLimiter ( ) ;
StackOwnerLimiter ( ui8 Owner ) ;
bool limit ( const Bonus * b , const CBonusSystemNode & node ) const OVERRIDE ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & owner ;
}
} ;
2011-02-11 10:20:26 +02:00
class DLL_EXPORT RankRangeLimiter : public ILimiter //applies to creatures with min <= Rank <= max
{
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 ) ;
bool limit ( const Bonus * b , const CBonusSystemNode & node ) const OVERRIDE ;
2011-02-11 10:20:26 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
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
{
extern DLL_EXPORT CSelectFieldEqual < TBonusType > type ;
extern DLL_EXPORT CSelectFieldEqual < TBonusSubtype > subtype ;
extern DLL_EXPORT CSelectFieldEqual < si32 > info ;
2011-03-03 20:25:48 +02:00
extern DLL_EXPORT CSelectFieldEqual < ui16 > duration ;
2010-05-02 21:20:26 +03:00
extern DLL_EXPORT CSelectFieldEqual < ui8 > sourceType ;
extern DLL_EXPORT CSelectFieldEqual < ui8 > effectRange ;
extern DLL_EXPORT CWillLastTurns turns ;
2011-06-24 20:43:02 +03:00
CSelector DLL_EXPORT typeSubtype ( TBonusType Type , TBonusSubtype Subtype ) ;
CSelector DLL_EXPORT typeSubtypeInfo ( TBonusType type , TBonusSubtype subtype , si32 info ) ;
2010-05-02 21:20:26 +03:00
CSelector DLL_EXPORT source ( ui8 source , ui32 sourceID ) ;
2011-03-03 20:25:48 +02:00
CSelector DLL_EXPORT durationType ( ui16 duration ) ;
2010-08-31 13:22:21 +03:00
CSelector DLL_EXPORT sourceTypeSel ( ui8 source ) ;
2010-05-02 21:20:26 +03:00
bool DLL_EXPORT matchesType ( const CSelector & sel , TBonusType type ) ;
2010-05-14 05:18:37 +03:00
bool DLL_EXPORT matchesTypeSubtype ( const CSelector & sel , TBonusType type , TBonusSubtype subtype ) ;
2011-02-21 06:13:00 +02:00
bool DLL_EXPORT positiveSpellEffects ( const Bonus * b ) ;
2010-05-12 05:32:56 +03:00
}
2010-07-12 13:20:25 +03:00
2011-05-04 05:37:27 +03:00
extern DLL_EXPORT const std : : map < std : : string , int > bonusNameMap ;