2009-02-04 15:40:54 +02:00
# pragma once
# include "../global.h"
# include <string>
2010-02-10 04:56:00 +02:00
# include <list>
2010-05-02 21:20:26 +03:00
# include <set>
# include <boost/function.hpp>
2010-11-20 02:03:31 +02:00
# include <boost/smart_ptr/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-05-02 21:20:26 +03:00
typedef ui8 TBonusType ;
typedef si32 TBonusSubtype ;
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 ) \
BONUS_NAME ( BLOCK_SPELLS_ABOVE_LEVEL ) \
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 ( NO_SHOTING_PENALTY ) \
BONUS_NAME ( DISPEL_IMMUNITY ) \
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*/ \
BONUS_NAME ( HATE ) /*eg. angels hate devils, subtype - ID of hated creature*/ \
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 */ \
BONUS_NAME ( SPELL_AFTER_ATTACK ) /* subtype - spell id, value - spell level, (additional info)%1000 - chance in %; eg. dendroids, (additional info)/1000 -> [0 - all attacks, 1 - shot only, 2 - melee only*/ \
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*/ \
BONUS_NAME ( FIRE_IMMUNITY ) \
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 */ \
2010-07-15 22:38:15 +03:00
BONUS_NAME ( DRAGON_NATURE ) /*TODO: implement it!*/ \
BONUS_NAME ( CREATURE_DAMAGE ) /*subtype 0 = both, 1 = min, 2 = max*/
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*/
UNTIL_ATTACK = 128 /*removed after attack and counterattacks are performed*/
} ;
enum BonusSource
{
ARTIFACT ,
2010-12-17 20:47:07 +02:00
ARTIFACT_INSTANCE ,
2010-05-02 21:20:26 +03:00
OBJECT ,
CASTED_SPELL ,
CREATURE_ABILITY ,
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 ,
SPECIAL_WEEK
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)
2010-05-14 05:18:37 +03:00
ONLY_ALLIED_ARMY , ONLY_ENEMY_ARMY ,
2010-09-25 23:23:55 +03:00
PLAYR_HEROES ,
GLOBAL //Statue of Legion etc.
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 ,
INDEPENDENT_MAX //used for SPELL bonus
2009-04-04 01:34:31 +03:00
} ;
2009-02-04 15:40:54 +02:00
ui8 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 ;
2010-05-02 21:20:26 +03:00
ui32 id ; //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 ;
2010-07-13 08:25:40 +03:00
Bonus ( ui8 Dur , ui8 Type , ui8 Src , si32 Val , ui32 ID , std : : string Desc , si32 Subtype = - 1 ) ;
Bonus ( ui8 Dur , ui8 Type , ui8 Src , si32 Val , ui32 ID , si32 Subtype = - 1 , ui8 ValType = ADDITIVE_VALUE ) ;
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 )
{
2010-07-12 13:20:25 +03:00
h & duration & type & subtype & source & val & id & description & additionalInfo & turnsRemain & valType & effectRange & limiter ;
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
}
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
{
return hb . source = = source & & ( id = = 0xffffff | | hb . id = = id ) ;
}
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
2009-02-06 13:15:39 +02:00
} ;
2010-02-10 04:56:00 +02:00
2010-09-25 23:23:55 +03:00
struct DLL_EXPORT stackExperience : public Bonus
{
std : : vector < ui32 > expBonuses ; // variations for levels 1-10, copied to val field;
bool enable ; //if true - turns ability on / off for zero value
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < Bonus & > ( this ) ;
h & expBonuses & enable ;
}
} ;
2010-07-12 13:20:25 +03:00
DLL_EXPORT std : : ostream & operator < < ( std : : ostream & out , const Bonus & bonus ) ;
2010-11-19 00:06:56 +02:00
class BonusList : public std : : list < 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
void DLL_EXPORT getBonuses ( BonusList & out , const CSelector & selector , const CBonusSystemNode * source = NULL ) const ;
void DLL_EXPORT getBonuses ( BonusList & out , const CSelector & selector , const CSelector & limit , const CBonusSystemNode * source = NULL ) const ;
void DLL_EXPORT getModifiersWDescr ( TModDescr & out ) const ;
2010-08-30 21:06:17 +03:00
void DLL_EXPORT removeSpells ( Bonus : : BonusSource sourceType ) ;
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
2010-02-10 04:56:00 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2010-11-19 00:06:56 +02:00
h & static_cast < std : : list < 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 ( ) ;
2010-11-20 02:03:31 +02:00
virtual CBonusSystemNode * getDestNode ( CBonusSystemNode * source ) ;
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 )
{ }
} ;
2010-04-03 06:33:46 +03:00
class DLL_EXPORT CBonusSystemNode
{
public :
2010-11-13 22:26:15 +02:00
BonusList bonuses ; //wielded bonuses (local and up-propagated here)
2010-11-19 00:22:51 +02:00
BonusList exportedBonuses ;
2010-11-13 22:26:15 +02:00
2010-11-20 19:36:02 +02:00
TNodesVector parents , //parents -> we inherit bonuses from them, we may attach our bonuses to them
2010-11-13 22:26:15 +02:00
children ;
2010-07-12 13:20:25 +03:00
ui8 nodeType ;
CBonusSystemNode ( ) ;
virtual ~ CBonusSystemNode ( ) ;
2010-04-03 06:33:46 +03:00
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
void getParents ( TCNodes & out ) const ; //retrieves list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
void getBonuses ( BonusList & out , const CSelector & selector , const CBonusSystemNode * root = NULL ) const ;
2010-04-03 06:33:46 +03:00
2010-05-02 21:20:26 +03:00
//////////////////////////////////////////////////////////////////////////
2010-11-13 22:26:15 +02:00
//interface
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 ;
BonusList getBonuses ( const CSelector & selector , const CSelector & limit ) const ;
void getBonuses ( BonusList & out , const CSelector & selector , const CSelector & limit ) const ;
BonusList getBonuses ( const CSelector & selector ) const ;
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 ;
2010-12-12 01:11:26 +02:00
ui32 getMinDamage ( ) const ; //used for stacks and creatures only
ui32 getMaxDamage ( ) const ;
2010-04-03 06:33:46 +03:00
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
2010-12-17 20:47:07 +02:00
const Bonus * getBonus ( const CSelector & selector ) const ;
2010-05-02 21:20:26 +03:00
//non-const interface
2010-11-13 22:26:15 +02:00
void getParents ( TNodes & out ) ; //retrieves list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
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 ) ;
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 ) ;
2010-11-20 19:36:02 +02:00
TNodesVector & nodesOnWhichWePropagate ( ) ;
2010-12-06 01:10:02 +02:00
bool isIndependentNode ( ) const ; //node is independent when it has no parents nor children
2010-11-20 19:36:02 +02:00
bool weActAsBonusSourceOnly ( ) 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
CBonusSystemNode * whereToPropagate ( Bonus * b ) ;
2010-11-19 00:06:56 +02:00
void popBonuses ( const CSelector & s ) ;
2010-12-12 01:11:26 +02:00
virtual std : : string nodeName ( ) const ;
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 )
{
2010-07-12 13:20:25 +03:00
h & bonuses & nodeType ;
2010-04-03 06:33:46 +03:00
}
2010-07-12 13:20:25 +03:00
enum ENodeTypes
{
2010-12-06 01:10:02 +02:00
UNKNOWN , STACK , SPECIALITY , ARTIFACT , CREATURE , ARTIFACT_INSTANCE , HERO
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
} ;
//generates HeroBonus from given data
2010-11-20 02:03:31 +02:00
inline Bonus * makeFeature ( 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
{
2010-11-20 02:03:31 +02:00
Bonus * sf = new Bonus ( ) ;
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 ;
}
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 ;
}
} ;
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 ;
extern DLL_EXPORT CSelectFieldEqual < ui8 > sourceType ;
extern DLL_EXPORT CSelectFieldEqual < ui8 > effectRange ;
extern DLL_EXPORT CWillLastTurns turns ;
CSelector DLL_EXPORT typeSybtype ( TBonusType Type , TBonusSubtype Subtype ) ;
CSelector DLL_EXPORT typeSybtypeInfo ( TBonusType type , TBonusSubtype subtype , si32 info ) ;
CSelector DLL_EXPORT source ( ui8 source , ui32 sourceID ) ;
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 ) ;
2010-05-12 05:32:56 +03:00
}
2010-07-12 13:20:25 +03:00
extern DLL_EXPORT const std : : map < std : : string , int > bonusNameMap ;