2010-02-10 04:56:00 +02:00
# define VCMI_DLL
# include "HeroBonus.h"
2010-04-03 06:33:46 +03:00
# include <boost/foreach.hpp>
2010-05-02 21:20:26 +03:00
# include "VCMI_Lib.h"
2010-12-20 23:22:53 +02:00
# include "CSpellHandler.h"
2010-05-02 21:20:26 +03:00
# include <sstream>
2010-12-20 23:22:53 +02:00
# include "CCreatureHandler.h"
2010-07-12 13:20:25 +03:00
# include <boost/assign/list_of.hpp>
# include "CCreatureSet.h"
2010-07-13 08:25:40 +03:00
# include <boost/algorithm/string/trim.hpp>
2010-11-20 02:03:31 +02:00
# include <boost/bind.hpp>
2010-12-20 23:22:53 +02:00
# include "CHeroHandler.h"
2011-01-15 04:17:56 +02:00
# include "CGeneralTextHandler.h"
2011-02-12 18:12:48 +02:00
# include "BattleState.h"
2011-02-22 11:47:25 +02:00
# include "CArtHandler.h"
2010-04-03 06:33:46 +03:00
2011-02-21 06:13:00 +02:00
# define FOREACH_CONST_PARENT(pname) TCNodes lparents; getParents(lparents); BOOST_FOREACH(const CBonusSystemNode *pname, lparents)
# define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents)
# define FOREACH_RED_CHILD(pname) TNodes lchildren; getRedChildren(lchildren); BOOST_FOREACH(CBonusSystemNode *pname, lchildren)
# define FOREACH_RED_PARENT(pname) TNodes lparents; getRedParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents)
2010-02-10 04:56:00 +02:00
2010-07-12 13:20:25 +03:00
# define BONUS_NAME(x) ( #x, Bonus::x )
DLL_EXPORT const std : : map < std : : string , int > bonusNameMap = boost : : assign : : map_list_of BONUS_LIST ;
# undef BONUS_NAME
2011-02-24 15:57:47 +02:00
# define BONUS_LOG_LINE(x) tlog5 << x << std::endl
2010-12-12 01:11:26 +02:00
2010-05-02 21:20:26 +03:00
int DLL_EXPORT BonusList : : totalValue ( ) const
2010-02-10 04:56:00 +02:00
{
2010-05-02 21:20:26 +03:00
int base = 0 ;
int percentToBase = 0 ;
int percentToAll = 0 ;
int additive = 0 ;
2010-08-05 12:11:38 +03:00
int indepMax = 0 ;
bool hasIndepMax = false ;
2011-02-12 18:12:48 +02:00
int indepMin = 0 ;
bool hasIndepMin = false ;
2010-02-10 04:56:00 +02:00
2010-11-19 00:06:56 +02:00
BOOST_FOREACH ( Bonus * i , * this )
2010-02-10 04:56:00 +02:00
{
2010-05-02 21:20:26 +03:00
switch ( i - > valType )
{
case Bonus : : BASE_NUMBER :
base + = i - > val ;
break ;
case Bonus : : PERCENT_TO_ALL :
percentToAll + = i - > val ;
break ;
case Bonus : : PERCENT_TO_BASE :
percentToBase + = i - > val ;
break ;
case Bonus : : ADDITIVE_VALUE :
additive + = i - > val ;
2010-08-05 12:11:38 +03:00
break ;
case Bonus : : INDEPENDENT_MAX :
2011-02-21 18:53:23 +02:00
if ( ! hasIndepMax )
2010-08-05 12:11:38 +03:00
{
indepMax = i - > val ;
hasIndepMax = true ;
}
else
{
amax ( indepMax , i - > val ) ;
}
2011-02-12 18:12:48 +02:00
break ;
case Bonus : : INDEPENDENT_MIN :
2011-02-21 18:53:23 +02:00
if ( ! hasIndepMin )
2011-02-12 18:12:48 +02:00
{
indepMin = i - > val ;
hasIndepMin = true ;
}
else
{
2011-02-21 18:53:23 +02:00
amin ( indepMin , i - > val ) ;
2011-02-12 18:12:48 +02:00
}
2010-05-02 21:20:26 +03:00
break ;
}
2010-02-10 04:56:00 +02:00
}
2010-05-02 21:20:26 +03:00
int modifiedBase = base + ( base * percentToBase ) / 100 ;
modifiedBase + = additive ;
2010-08-05 12:11:38 +03:00
int valFirst = ( modifiedBase * ( 100 + percentToAll ) ) / 100 ;
2011-02-12 18:12:48 +02:00
if ( hasIndepMin & & hasIndepMax )
assert ( indepMin < indepMax ) ;
2010-08-05 12:11:38 +03:00
if ( hasIndepMax )
2011-02-12 18:12:48 +02:00
amax ( valFirst , indepMax ) ;
2011-02-21 18:53:23 +02:00
if ( hasIndepMin )
2011-02-12 18:12:48 +02:00
amin ( valFirst , indepMin ) ;
return valFirst ;
2010-02-10 04:56:00 +02:00
}
2010-05-02 21:20:26 +03:00
const DLL_EXPORT Bonus * BonusList : : getFirst ( const CSelector & selector ) const
2010-02-10 04:56:00 +02:00
{
2010-11-19 00:06:56 +02:00
BOOST_FOREACH ( Bonus * i , * this )
if ( selector ( i ) )
2010-05-02 21:20:26 +03:00
return & * i ;
return NULL ;
}
2010-02-10 04:56:00 +02:00
2010-05-02 21:20:26 +03:00
DLL_EXPORT Bonus * BonusList : : getFirst ( const CSelector & select )
{
2010-11-19 00:06:56 +02:00
BOOST_FOREACH ( Bonus * i , * this )
if ( select ( i ) )
2010-05-02 21:20:26 +03:00
return & * i ;
return NULL ;
2010-02-10 04:56:00 +02:00
}
2010-05-02 21:20:26 +03:00
void DLL_EXPORT BonusList : : getModifiersWDescr ( TModDescr & out ) const
2010-02-10 04:56:00 +02:00
{
2010-11-19 00:06:56 +02:00
BOOST_FOREACH ( Bonus * i , * this )
2010-05-02 21:20:26 +03:00
out . push_back ( std : : make_pair ( i - > val , i - > Description ( ) ) ) ;
}
2011-02-27 13:26:18 +02:00
void DLL_EXPORT BonusList : : getBonuses ( BonusList & out , const CSelector & selector ) const
2010-05-02 21:20:26 +03:00
{
2011-02-27 13:26:18 +02:00
// BOOST_FOREACH(Bonus *i, *this)
// if(selector(i) && i->effectRange == Bonus::NO_LIMIT)
// out.push_back(i);
getBonuses ( out , selector , 0 ) ;
2010-05-02 21:20:26 +03:00
}
2011-02-27 13:26:18 +02:00
void DLL_EXPORT BonusList : : getBonuses ( BonusList & out , const CSelector & selector , const CSelector & limit ) const
2010-05-02 21:20:26 +03:00
{
2010-11-19 00:06:56 +02:00
BOOST_FOREACH ( Bonus * i , * this )
2011-02-27 13:26:18 +02:00
if ( selector ( i ) & & ( ! limit & & i - > effectRange = = Bonus : : NO_LIMIT | | limit & & limit ( i ) ) ) //add matching bonuses that matches limit predicate or have NO_LIMIT if no given predicate
2010-11-19 00:06:56 +02:00
out . push_back ( i ) ;
2010-05-02 21:20:26 +03:00
}
2010-08-31 13:22:21 +03:00
2010-07-12 13:20:25 +03:00
void BonusList : : limit ( const CBonusSystemNode & node )
{
2010-11-27 03:46:19 +02:00
remove_if ( boost : : bind ( & CBonusSystemNode : : isLimitedOnUs , boost : : ref ( node ) , _1 ) ) ;
2010-07-12 13:20:25 +03:00
}
2011-02-27 13:26:18 +02:00
void DLL_EXPORT BonusList : : eliminateDuplicates ( )
{
sort ( ) ;
unique ( ) ;
}
2011-02-27 21:58:14 +02:00
int IBonusBearer : : valOfBonuses ( Bonus : : BonusType type , const CSelector & selector ) const
2010-08-25 11:40:50 +03:00
{
return valOfBonuses ( Selector : : type ( type ) & & selector ) ;
}
2010-12-06 01:10:02 +02:00
2011-02-27 21:58:14 +02:00
int IBonusBearer : : valOfBonuses ( Bonus : : BonusType type , int subtype /*= -1*/ ) const
2010-05-02 21:20:26 +03:00
{
CSelector s = Selector : : type ( type ) ;
if ( subtype ! = - 1 )
s = s & & Selector : : subtype ( subtype ) ;
return valOfBonuses ( s ) ;
}
2010-12-06 01:10:02 +02:00
2011-02-27 21:58:14 +02:00
int IBonusBearer : : valOfBonuses ( const CSelector & selector ) const
2010-05-02 21:20:26 +03:00
{
BonusList hlp ;
2010-11-13 22:26:15 +02:00
getBonuses ( hlp , selector ) ;
2010-05-02 21:20:26 +03:00
return hlp . totalValue ( ) ;
}
2011-02-27 21:58:14 +02:00
bool IBonusBearer : : hasBonus ( const CSelector & selector ) const
2010-05-02 21:20:26 +03:00
{
return getBonuses ( selector ) . size ( ) > 0 ;
}
2011-02-27 21:58:14 +02:00
bool IBonusBearer : : hasBonusOfType ( Bonus : : BonusType type , int subtype /*= -1*/ ) const
2010-05-02 21:20:26 +03:00
{
CSelector s = Selector : : type ( type ) ;
if ( subtype ! = - 1 )
s = s & & Selector : : subtype ( subtype ) ;
return hasBonus ( s ) ;
}
2011-02-27 21:58:14 +02:00
void IBonusBearer : : getModifiersWDescr ( TModDescr & out , Bonus : : BonusType type , int subtype /*= -1 */ ) const
2010-02-10 04:56:00 +02:00
{
2011-01-15 04:17:56 +02:00
getModifiersWDescr ( out , subtype ! = - 1 ? Selector : : typeSybtype ( type , subtype ) : Selector : : type ( type ) ) ;
2010-05-02 21:20:26 +03:00
}
2010-02-10 04:56:00 +02:00
2011-02-27 21:58:14 +02:00
void IBonusBearer : : getModifiersWDescr ( TModDescr & out , const CSelector & selector ) const
2010-05-02 21:20:26 +03:00
{
getBonuses ( selector ) . getModifiersWDescr ( out ) ;
}
2011-02-27 21:58:14 +02:00
int IBonusBearer : : getBonusesCount ( int from , int id ) const
2010-05-02 21:20:26 +03:00
{
return getBonusesCount ( Selector : : source ( from , id ) ) ;
}
2011-02-27 21:58:14 +02:00
int IBonusBearer : : getBonusesCount ( const CSelector & selector ) const
2010-05-02 21:20:26 +03:00
{
2010-11-13 22:26:15 +02:00
return getBonuses ( selector ) . size ( ) ;
2010-05-02 21:20:26 +03:00
}
2011-02-27 21:58:14 +02:00
void IBonusBearer : : getBonuses ( BonusList & out , const CSelector & selector , const CBonusSystemNode * root /*= NULL*/ ) const
2010-05-02 21:20:26 +03:00
{
2011-02-27 13:26:18 +02:00
getBonuses ( out , selector , 0 , root ) ;
// FOREACH_CONST_PARENT(p)
// p->getBonuses(out, selector, root ? root : this);
//
// bonuses.getBonuses(out, selector);
//
// if(!root)
// out.limit(*this);
2010-04-03 06:33:46 +03:00
}
2011-02-27 21:58:14 +02:00
BonusList IBonusBearer : : getBonuses ( const CSelector & selector ) const
2010-04-03 06:33:46 +03:00
{
2010-05-02 21:20:26 +03:00
BonusList ret ;
2010-11-13 22:26:15 +02:00
getBonuses ( ret , selector ) ;
2010-05-02 21:20:26 +03:00
return ret ;
}
2010-04-03 06:33:46 +03:00
2011-02-27 21:58:14 +02:00
void IBonusBearer : : getBonuses ( BonusList & out , const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root /*= NULL*/ ) const
2010-05-02 21:20:26 +03:00
{
2011-02-27 13:26:18 +02:00
getAllBonuses ( out , selector , limit , root ) ;
out . eliminateDuplicates ( ) ;
//
// getBonuses(out, selector); //first get all the bonuses
// out.remove_if(std::not1(limit)); //now remove the ones we don't like
// out.limit(*this); //apply bonuses' limiters
2010-05-02 21:20:26 +03:00
}
2010-04-03 06:33:46 +03:00
2011-02-27 21:58:14 +02:00
BonusList IBonusBearer : : getBonuses ( const CSelector & selector , const CSelector & limit ) const
2010-05-02 21:20:26 +03:00
{
BonusList ret ;
2010-11-13 22:26:15 +02:00
getBonuses ( ret , selector , limit ) ;
2010-04-03 06:33:46 +03:00
return ret ;
}
2011-02-27 21:58:14 +02:00
bool IBonusBearer : : hasBonusFrom ( ui8 source , ui32 sourceID ) const
2010-05-02 21:20:26 +03:00
{
return hasBonus ( Selector : : source ( source , sourceID ) ) ;
}
2011-02-27 21:58:14 +02:00
int IBonusBearer : : MoraleVal ( ) const
2010-04-03 06:33:46 +03:00
{
2010-05-02 21:20:26 +03:00
if ( hasBonusOfType ( Bonus : : NON_LIVING ) | | hasBonusOfType ( Bonus : : UNDEAD ) | |
hasBonusOfType ( Bonus : : NO_MORALE ) | | hasBonusOfType ( Bonus : : SIEGE_WEAPON ) )
return 0 ;
2010-04-03 06:33:46 +03:00
2010-05-02 21:20:26 +03:00
int ret = valOfBonuses ( Selector : : type ( Bonus : : MORALE ) ) ;
2010-04-03 06:33:46 +03:00
2010-05-02 21:20:26 +03:00
if ( hasBonusOfType ( Bonus : : SELF_MORALE ) ) //eg. minotaur
amax ( ret , + 1 ) ;
2010-04-03 06:33:46 +03:00
2010-05-02 21:20:26 +03:00
return abetw ( ret , - 3 , + 3 ) ;
2010-04-03 06:33:46 +03:00
}
2011-02-27 21:58:14 +02:00
int IBonusBearer : : LuckVal ( ) const
2010-04-03 06:33:46 +03:00
{
2010-05-02 21:20:26 +03:00
if ( hasBonusOfType ( Bonus : : NO_LUCK ) )
return 0 ;
int ret = valOfBonuses ( Selector : : type ( Bonus : : LUCK ) ) ;
if ( hasBonusOfType ( Bonus : : SELF_LUCK ) ) //eg. halfling
amax ( ret , + 1 ) ;
return abetw ( ret , - 3 , + 3 ) ;
2010-04-03 06:33:46 +03:00
}
2011-02-27 21:58:14 +02:00
si32 IBonusBearer : : Attack ( ) const
2010-04-03 06:33:46 +03:00
{
2010-05-02 21:20:26 +03:00
si32 ret = valOfBonuses ( Bonus : : PRIMARY_SKILL , PrimarySkill : : ATTACK ) ;
if ( int frenzyPower = valOfBonuses ( Bonus : : IN_FRENZY ) ) //frenzy for attacker
{
ret + = frenzyPower * Defense ( false ) ;
}
2010-04-03 06:33:46 +03:00
2010-05-02 21:20:26 +03:00
return ret ;
2010-04-03 06:33:46 +03:00
}
2011-02-27 21:58:14 +02:00
si32 IBonusBearer : : Defense ( bool withFrenzy /*= true*/ ) const
2010-04-03 06:33:46 +03:00
{
2010-05-02 21:20:26 +03:00
si32 ret = valOfBonuses ( Bonus : : PRIMARY_SKILL , PrimarySkill : : DEFENSE ) ;
2010-04-03 06:33:46 +03:00
2010-05-02 21:20:26 +03:00
if ( withFrenzy & & hasBonusOfType ( Bonus : : IN_FRENZY ) ) //frenzy for defender
{
return 0 ;
}
2010-04-03 06:33:46 +03:00
return ret ;
}
2011-02-27 21:58:14 +02:00
ui16 IBonusBearer : : MaxHealth ( ) const
2010-04-03 06:33:46 +03:00
{
2010-05-02 21:20:26 +03:00
return valOfBonuses ( Bonus : : STACK_HEALTH ) ;
2010-04-03 06:33:46 +03:00
}
2011-02-27 21:58:14 +02:00
ui32 IBonusBearer : : getMinDamage ( ) const
2010-08-30 21:06:17 +03:00
{
return valOfBonuses ( Selector : : typeSybtype ( Bonus : : CREATURE_DAMAGE , 0 ) | | Selector : : typeSybtype ( Bonus : : CREATURE_DAMAGE , 1 ) ) ;
}
2011-02-27 21:58:14 +02:00
ui32 IBonusBearer : : getMaxDamage ( ) const
2010-08-30 21:06:17 +03:00
{
return valOfBonuses ( Selector : : typeSybtype ( Bonus : : CREATURE_DAMAGE , 0 ) | | Selector : : typeSybtype ( Bonus : : CREATURE_DAMAGE , 2 ) ) ;
}
2011-02-27 21:58:14 +02:00
si32 IBonusBearer : : manaLimit ( ) const
{
return si32 ( getPrimSkillLevel ( 3 ) * ( 100.0f + valOfBonuses ( Bonus : : SECONDARY_SKILL_PREMY , 24 ) ) / 10.0f ) ;
}
int IBonusBearer : : getPrimSkillLevel ( int id ) const
{
int ret = 0 ;
if ( id = = PrimarySkill : : ATTACK )
ret = Attack ( ) ;
else if ( id = = PrimarySkill : : DEFENSE )
ret = Defense ( ) ;
else
ret = valOfBonuses ( Bonus : : PRIMARY_SKILL , id ) ;
amax ( ret , id / 2 ) ; //minimal value is 0 for attack and defense and 1 for spell power and knowledge
return ret ;
}
Bonus * CBonusSystemNode : : getBonus ( const CSelector & selector )
{
Bonus * ret = bonuses . getFirst ( selector ) ;
if ( ret )
return ret ;
FOREACH_PARENT ( pname )
{
ret = pname - > getBonus ( selector ) ;
if ( ret )
return ret ;
}
return NULL ;
}
const Bonus * CBonusSystemNode : : getBonus ( const CSelector & selector ) const
{
return ( const_cast < CBonusSystemNode * > ( this ) ) - > getBonus ( selector ) ;
}
void CBonusSystemNode : : getParents ( TCNodes & out ) const /*retreives list of parent nodes (nodes to inherit bonuses from) */
{
BOOST_FOREACH ( const CBonusSystemNode * parent , parents )
out . insert ( parent ) ;
}
void CBonusSystemNode : : getParents ( TNodes & out )
{
BOOST_FOREACH ( const CBonusSystemNode * parent , parents )
out . insert ( const_cast < CBonusSystemNode * > ( parent ) ) ;
}
void CBonusSystemNode : : getAllBonuses ( BonusList & out , const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root /*= NULL*/ ) const
{
FOREACH_CONST_PARENT ( p )
p - > getBonuses ( out , selector , limit , root ? root : this ) ;
bonuses . getBonuses ( out , selector , limit ) ;
if ( ! root )
out . limit ( * this ) ;
}
2010-07-12 13:20:25 +03:00
CBonusSystemNode : : CBonusSystemNode ( )
{
nodeType = UNKNOWN ;
}
CBonusSystemNode : : ~ CBonusSystemNode ( )
{
2010-12-06 01:10:02 +02:00
detachFromAll ( ) ;
2010-07-12 13:20:25 +03:00
2010-11-27 03:46:19 +02:00
if ( children . size ( ) )
{
tlog2 < < " Warning: an orphaned child! \n " ;
2011-02-04 16:58:14 +02:00
while ( children . size ( ) )
children . front ( ) - > detachFrom ( this ) ;
2010-11-27 03:46:19 +02:00
}
2011-02-21 06:13:00 +02:00
BOOST_FOREACH ( Bonus * b , exportedBonuses )
delete b ;
2010-07-12 13:20:25 +03:00
}
2010-11-22 02:34:46 +02:00
void CBonusSystemNode : : attachTo ( CBonusSystemNode * parent )
2010-11-13 22:26:15 +02:00
{
2010-11-22 02:34:46 +02:00
assert ( ! vstd : : contains ( parents , parent ) ) ;
parents . push_back ( parent ) ;
2011-02-21 06:13:00 +02:00
if ( parent - > actsAsBonusSourceOnly ( ) )
parent - > newRedDescendant ( this ) ;
else
newRedDescendant ( parent ) ;
2010-11-22 02:34:46 +02:00
parent - > newChildAttached ( this ) ;
2010-11-13 22:26:15 +02:00
}
2010-11-22 02:34:46 +02:00
void CBonusSystemNode : : detachFrom ( CBonusSystemNode * parent )
2010-11-13 22:26:15 +02:00
{
2010-11-22 02:34:46 +02:00
assert ( vstd : : contains ( parents , parent ) ) ;
2010-11-13 22:26:15 +02:00
2011-02-21 06:13:00 +02:00
if ( parent - > actsAsBonusSourceOnly ( ) )
parent - > removedRedDescendant ( this ) ;
else
removedRedDescendant ( parent ) ;
parents - = parent ;
2010-11-22 02:34:46 +02:00
parent - > childDetached ( this ) ;
2010-11-13 22:26:15 +02:00
}
2010-11-19 00:06:56 +02:00
void CBonusSystemNode : : popBonuses ( const CSelector & s )
{
2010-11-19 00:22:51 +02:00
BonusList bl ;
exportedBonuses . getBonuses ( bl , s ) ;
BOOST_FOREACH ( Bonus * b , bl )
removeBonus ( b ) ;
2010-11-19 00:06:56 +02:00
BOOST_FOREACH ( CBonusSystemNode * child , children )
child - > popBonuses ( s ) ;
}
2010-11-20 02:03:31 +02:00
// void CBonusSystemNode::addNewBonus(const Bonus &b)
// {
// addNewBonus(new Bonus(b));
// }
2010-11-19 00:06:56 +02:00
void CBonusSystemNode : : addNewBonus ( Bonus * b )
{
2011-02-21 06:13:00 +02:00
assert ( ! vstd : : contains ( exportedBonuses , b ) ) ;
2010-11-19 00:22:51 +02:00
exportedBonuses . push_back ( b ) ;
2011-02-23 05:57:45 +02:00
exportBonus ( b ) ;
2010-11-19 00:06:56 +02:00
}
void CBonusSystemNode : : removeBonus ( Bonus * b )
{
2010-11-19 00:22:51 +02:00
exportedBonuses - = b ;
2010-11-20 02:03:31 +02:00
if ( b - > propagator )
2011-02-21 06:13:00 +02:00
unpropagateBonus ( b ) ;
2010-11-20 02:03:31 +02:00
else
2011-02-21 06:13:00 +02:00
bonuses - = b ;
delNull ( b ) ;
2010-11-20 02:03:31 +02:00
}
bool CBonusSystemNode : : isLimitedOnUs ( Bonus * b ) const
{
return b - > limiter & & b - > limiter - > limit ( b , * this ) ;
2010-11-19 00:06:56 +02:00
}
2011-02-21 06:13:00 +02:00
bool CBonusSystemNode : : actsAsBonusSourceOnly ( ) const
2010-11-20 19:36:02 +02:00
{
switch ( nodeType )
{
case CREATURE :
case ARTIFACT :
case ARTIFACT_INSTANCE :
return true ;
default :
return false ;
}
}
2011-02-21 06:13:00 +02:00
void CBonusSystemNode : : propagateBonus ( Bonus * b )
2010-11-20 19:36:02 +02:00
{
2011-02-21 06:13:00 +02:00
if ( b - > propagator - > shouldBeAttached ( this ) )
{
bonuses . push_back ( b ) ;
BONUS_LOG_LINE ( " #$# " < < b - > Description ( ) < < " #propagated to# " < < nodeName ( ) ) ;
}
FOREACH_RED_CHILD ( child )
child - > propagateBonus ( b ) ;
2010-11-20 19:36:02 +02:00
}
2011-02-21 06:13:00 +02:00
void CBonusSystemNode : : unpropagateBonus ( Bonus * b )
2010-11-22 02:34:46 +02:00
{
2011-02-21 06:13:00 +02:00
if ( b - > propagator - > shouldBeAttached ( this ) )
{
bonuses - = b ;
BONUS_LOG_LINE ( " #$# " < < b - > Description ( ) < < " #is no longer propagated to# " < < nodeName ( ) ) ;
}
FOREACH_RED_CHILD ( child )
child - > unpropagateBonus ( b ) ;
2010-11-22 02:34:46 +02:00
}
void CBonusSystemNode : : newChildAttached ( CBonusSystemNode * child )
{
assert ( ! vstd : : contains ( children , child ) ) ;
children . push_back ( child ) ;
2010-12-12 01:11:26 +02:00
BONUS_LOG_LINE ( child - > nodeName ( ) < < " #attached to# " < < nodeName ( ) ) ;
2010-11-22 02:34:46 +02:00
}
void CBonusSystemNode : : childDetached ( CBonusSystemNode * child )
{
assert ( vstd : : contains ( children , child ) ) ;
children - = child ;
2010-12-12 01:11:26 +02:00
BONUS_LOG_LINE ( child - > nodeName ( ) < < " #detached from# " < < nodeName ( ) ) ;
2010-11-22 02:34:46 +02:00
}
2010-12-06 01:10:02 +02:00
void CBonusSystemNode : : detachFromAll ( )
{
while ( parents . size ( ) )
detachFrom ( parents . front ( ) ) ;
}
bool CBonusSystemNode : : isIndependentNode ( ) const
{
return parents . empty ( ) & & children . empty ( ) ;
}
2010-12-12 01:11:26 +02:00
std : : string CBonusSystemNode : : nodeName ( ) const
{
2011-02-10 15:12:53 +02:00
return description . size ( )
? description
: std : : string ( " Bonus system node of type " ) + typeid ( * this ) . name ( ) ;
2010-12-12 01:11:26 +02:00
}
2011-02-04 16:58:14 +02:00
void CBonusSystemNode : : deserializationFix ( )
{
2011-03-01 12:19:05 +02:00
exportBonuses ( ) ;
2011-02-04 16:58:14 +02:00
}
2011-02-21 06:13:00 +02:00
void CBonusSystemNode : : getRedParents ( TNodes & out )
{
FOREACH_PARENT ( pname )
{
if ( pname - > actsAsBonusSourceOnly ( ) )
{
out . insert ( pname ) ;
}
}
if ( ! actsAsBonusSourceOnly ( ) )
{
BOOST_FOREACH ( CBonusSystemNode * child , children )
{
out . insert ( child ) ;
}
}
}
void CBonusSystemNode : : getRedChildren ( TNodes & out )
{
FOREACH_PARENT ( pname )
{
if ( ! pname - > actsAsBonusSourceOnly ( ) )
{
out . insert ( pname ) ;
}
}
if ( actsAsBonusSourceOnly ( ) )
{
BOOST_FOREACH ( CBonusSystemNode * child , children )
{
out . insert ( child ) ;
}
}
}
void CBonusSystemNode : : newRedDescendant ( CBonusSystemNode * descendant )
{
BOOST_FOREACH ( Bonus * b , exportedBonuses )
if ( b - > propagator )
descendant - > propagateBonus ( b ) ;
FOREACH_RED_PARENT ( parent )
parent - > newRedDescendant ( descendant ) ;
}
void CBonusSystemNode : : removedRedDescendant ( CBonusSystemNode * descendant )
{
BOOST_FOREACH ( Bonus * b , exportedBonuses )
if ( b - > propagator )
descendant - > unpropagateBonus ( b ) ;
FOREACH_RED_PARENT ( parent )
parent - > removedRedDescendant ( descendant ) ;
}
void CBonusSystemNode : : getRedAncestors ( TNodes & out )
{
getRedParents ( out ) ;
FOREACH_RED_PARENT ( p )
p - > getRedAncestors ( out ) ;
}
void CBonusSystemNode : : getRedDescendants ( TNodes & out )
{
getRedChildren ( out ) ;
FOREACH_RED_CHILD ( c )
c - > getRedChildren ( out ) ;
}
void CBonusSystemNode : : battleTurnPassed ( )
{
BonusList bonusesCpy = exportedBonuses ; //copy, because removing bonuses invalidates iters
BOOST_FOREACH ( Bonus * b , bonusesCpy )
{
if ( b - > duration & Bonus : : N_TURNS )
{
b - > turnsRemain - - ;
if ( b - > turnsRemain < = 0 )
removeBonus ( b ) ;
}
}
}
2011-02-23 05:57:45 +02:00
void CBonusSystemNode : : exportBonus ( Bonus * b )
{
if ( b - > propagator )
propagateBonus ( b ) ;
else
bonuses . push_back ( b ) ;
}
2011-03-01 12:19:05 +02:00
void CBonusSystemNode : : exportBonuses ( )
{
BOOST_FOREACH ( Bonus * b , exportedBonuses )
exportBonus ( b ) ;
}
2010-05-02 21:20:26 +03:00
int NBonus : : valOf ( const CBonusSystemNode * obj , Bonus : : BonusType type , int subtype /*= -1*/ )
2010-04-03 06:33:46 +03:00
{
if ( obj )
return obj - > valOfBonuses ( type , subtype ) ;
return 0 ;
}
2010-05-02 21:20:26 +03:00
bool NBonus : : hasOfType ( const CBonusSystemNode * obj , Bonus : : BonusType type , int subtype /*= -1*/ )
2010-04-03 06:33:46 +03:00
{
if ( obj )
return obj - > hasBonusOfType ( type , subtype ) ;
return false ;
}
2010-05-02 21:20:26 +03:00
void NBonus : : getModifiersWDescr ( const CBonusSystemNode * obj , TModDescr & out , Bonus : : BonusType type , int subtype /*= -1 */ )
2010-04-03 06:33:46 +03:00
{
if ( obj )
return obj - > getModifiersWDescr ( out , type , subtype ) ;
}
int NBonus : : getCount ( const CBonusSystemNode * obj , int from , int id )
{
if ( obj )
return obj - > getBonusesCount ( from , id ) ;
return 0 ;
2010-05-02 21:20:26 +03:00
}
const CSpell * Bonus : : sourceSpell ( ) const
{
if ( source = = SPELL_EFFECT )
2011-02-20 20:32:39 +02:00
return VLC - > spellh - > spells [ sid ] ;
2010-05-02 21:20:26 +03:00
return NULL ;
}
std : : string Bonus : : Description ( ) const
{
if ( description . size ( ) )
return description ;
std : : ostringstream str ;
2011-02-22 11:47:25 +02:00
str < < std : : showpos < < val < < " " ;
2010-05-02 21:20:26 +03:00
switch ( source )
{
2011-02-22 11:47:25 +02:00
case ARTIFACT :
str < < VLC - > arth - > artifacts [ sid ] - > Name ( ) ;
break ; ;
case SPELL_EFFECT :
str < < VLC - > spellh - > spells [ sid ] - > name ;
break ;
2010-05-02 21:20:26 +03:00
case CREATURE_ABILITY :
2011-02-20 20:32:39 +02:00
str < < VLC - > creh - > creatures [ sid ] - > namePl ;
2010-05-02 21:20:26 +03:00
break ;
2011-01-15 04:17:56 +02:00
case SECONDARY_SKILL :
2011-02-22 11:47:25 +02:00
str < < VLC - > generaltexth - > skillName [ sid ] /* << " secondary skill"*/ ;
2011-01-15 04:17:56 +02:00
break ;
2010-05-02 21:20:26 +03:00
}
2011-02-20 20:32:39 +02:00
2010-05-02 21:20:26 +03:00
return str . str ( ) ;
}
2011-02-21 06:24:46 +02:00
Bonus : : Bonus ( ui16 Dur , ui8 Type , ui8 Src , si32 Val , ui32 ID , std : : string Desc , si32 Subtype /*=-1*/ )
2011-02-20 20:32:39 +02:00
: duration ( Dur ) , type ( Type ) , subtype ( Subtype ) , source ( Src ) , val ( Val ) , sid ( ID ) , description ( Desc )
2010-07-13 08:25:40 +03:00
{
additionalInfo = - 1 ;
turnsRemain = 0 ;
valType = ADDITIVE_VALUE ;
effectRange = NO_LIMIT ;
boost : : algorithm : : trim ( description ) ;
}
2011-02-21 06:24:46 +02:00
Bonus : : Bonus ( ui16 Dur , ui8 Type , ui8 Src , si32 Val , ui32 ID , si32 Subtype /*=-1*/ , ui8 ValType /*= ADDITIVE_VALUE*/ )
2011-02-20 20:32:39 +02:00
: duration ( Dur ) , type ( Type ) , subtype ( Subtype ) , source ( Src ) , val ( Val ) , sid ( ID ) , valType ( ValType )
2010-07-13 08:25:40 +03:00
{
additionalInfo = - 1 ;
turnsRemain = 0 ;
effectRange = NO_LIMIT ;
}
Bonus : : Bonus ( )
{
subtype = - 1 ;
additionalInfo = - 1 ;
turnsRemain = 0 ;
valType = ADDITIVE_VALUE ;
effectRange = NO_LIMIT ;
2010-11-20 02:03:31 +02:00
}
Bonus : : ~ Bonus ( )
{
}
Bonus * Bonus : : addLimiter ( ILimiter * Limiter )
{
2011-02-21 06:13:00 +02:00
return addLimiter ( boost : : shared_ptr < ILimiter > ( Limiter ) ) ;
}
Bonus * Bonus : : addLimiter ( boost : : shared_ptr < ILimiter > Limiter )
{
limiter = Limiter ;
return this ;
}
Bonus * Bonus : : addPropagator ( IPropagator * Propagator )
{
return addPropagator ( boost : : shared_ptr < IPropagator > ( Propagator ) ) ;
}
Bonus * Bonus : : addPropagator ( boost : : shared_ptr < IPropagator > Propagator )
{
propagator = Propagator ;
2010-11-20 02:03:31 +02:00
return this ;
2010-07-13 08:25:40 +03:00
}
2010-05-02 21:20:26 +03:00
CSelector DLL_EXPORT operator & & ( const CSelector & first , const CSelector & second )
{
return CSelectorsConjunction ( first , second ) ;
}
2010-08-30 21:06:17 +03:00
CSelector DLL_EXPORT operator | | ( const CSelector & first , const CSelector & second )
{
return CSelectorsAlternative ( first , second ) ;
}
2010-05-02 21:20:26 +03:00
namespace Selector
{
DLL_EXPORT CSelectFieldEqual < TBonusType > type ( & Bonus : : type , 0 ) ;
DLL_EXPORT CSelectFieldEqual < TBonusSubtype > subtype ( & Bonus : : subtype , 0 ) ;
DLL_EXPORT CSelectFieldEqual < si32 > info ( & Bonus : : additionalInfo , 0 ) ;
2011-03-03 20:25:48 +02:00
DLL_EXPORT CSelectFieldEqual < ui16 > duration ( & Bonus : : duration , 0 ) ;
2010-05-02 21:20:26 +03:00
DLL_EXPORT CSelectFieldEqual < ui8 > sourceType ( & Bonus : : source , 0 ) ;
DLL_EXPORT CSelectFieldEqual < ui8 > effectRange ( & Bonus : : effectRange , Bonus : : NO_LIMIT ) ;
2011-02-14 23:08:29 +02:00
DLL_EXPORT CWillLastTurns turns ;
2010-05-02 21:20:26 +03:00
CSelector DLL_EXPORT typeSybtype ( TBonusType Type , TBonusSubtype Subtype )
{
return type ( Type ) & & subtype ( Subtype ) ;
}
CSelector DLL_EXPORT typeSybtypeInfo ( TBonusType type , TBonusSubtype subtype , si32 info )
{
return CSelectFieldEqual < TBonusType > ( & Bonus : : type , type ) & & CSelectFieldEqual < TBonusSubtype > ( & Bonus : : subtype , subtype ) & & CSelectFieldEqual < si32 > ( & Bonus : : additionalInfo , info ) ;
}
CSelector DLL_EXPORT source ( ui8 source , ui32 sourceID )
{
2011-02-20 20:32:39 +02:00
return CSelectFieldEqual < ui8 > ( & Bonus : : source , source ) & & CSelectFieldEqual < ui32 > ( & Bonus : : sid , sourceID ) ;
2010-05-02 21:20:26 +03:00
}
2011-03-03 20:25:48 +02:00
CSelector DLL_EXPORT durationType ( ui16 duration )
{
return CSelectFieldEqual < ui16 > ( & Bonus : : duration , duration ) ;
}
2010-08-31 13:22:21 +03:00
CSelector DLL_EXPORT sourceTypeSel ( ui8 source )
{
return CSelectFieldEqual < ui8 > ( & Bonus : : source , source ) ;
}
2010-05-14 05:18:37 +03:00
bool DLL_EXPORT matchesType ( const CSelector & sel , TBonusType type )
2010-05-02 21:20:26 +03:00
{
Bonus dummy ;
dummy . type = type ;
2010-11-19 00:06:56 +02:00
return sel ( & dummy ) ;
2010-05-02 21:20:26 +03:00
}
2010-05-14 05:18:37 +03:00
bool DLL_EXPORT matchesTypeSubtype ( const CSelector & sel , TBonusType type , TBonusSubtype subtype )
{
Bonus dummy ;
dummy . type = type ;
dummy . subtype = subtype ;
2010-11-19 00:06:56 +02:00
return sel ( & dummy ) ;
2010-05-14 05:18:37 +03:00
}
2011-02-21 06:13:00 +02:00
bool DLL_EXPORT positiveSpellEffects ( const Bonus * b )
{
if ( b - > source = = Bonus : : SPELL_EFFECT )
{
CSpell * sp = VLC - > spellh - > spells [ b - > sid ] ;
return sp - > positiveness = = 1 ;
}
return false ; //not a spell effect
}
}
const CStack * retreiveStackBattle ( const CBonusSystemNode * node )
{
switch ( node - > nodeType )
{
case CBonusSystemNode : : STACK_BATTLE :
return static_cast < const CStack * > ( node ) ;
default :
return NULL ;
}
2010-07-12 13:20:25 +03:00
}
2011-02-12 18:12:48 +02:00
const CStackInstance * retreiveStackInstance ( const CBonusSystemNode * node )
{
switch ( node - > nodeType )
{
case CBonusSystemNode : : STACK_INSTANCE :
return ( static_cast < const CStackInstance * > ( node ) ) ;
case CBonusSystemNode : : STACK_BATTLE :
return ( static_cast < const CStack * > ( node ) ) - > base ;
default :
return NULL ;
}
}
2010-11-20 02:03:31 +02:00
const CCreature * retrieveCreature ( const CBonusSystemNode * node )
{
switch ( node - > nodeType )
{
case CBonusSystemNode : : CREATURE :
return ( static_cast < const CCreature * > ( node ) ) ;
default :
2011-02-12 18:12:48 +02:00
const CStackInstance * csi = retreiveStackInstance ( node ) ;
if ( csi )
return csi - > type ;
2010-11-20 02:03:31 +02:00
return NULL ;
}
}
2010-07-12 13:20:25 +03:00
DLL_EXPORT std : : ostream & operator < < ( std : : ostream & out , const BonusList & bonusList )
{
int i = 0 ;
2010-11-19 00:06:56 +02:00
BOOST_FOREACH ( const Bonus * b , bonusList )
2010-07-12 13:20:25 +03:00
{
2010-11-19 00:06:56 +02:00
out < < " Bonus " < < i + + < < " \n " < < * b < < std : : endl ;
2010-07-12 13:20:25 +03:00
}
return out ;
}
DLL_EXPORT std : : ostream & operator < < ( std : : ostream & out , const Bonus & bonus )
{
for ( std : : map < std : : string , int > : : const_iterator i = bonusNameMap . begin ( ) ; i ! = bonusNameMap . end ( ) ; i + + )
if ( i - > second = = bonus . type )
out < < " \t Type: " < < i - > first < < " \t " ;
# define printField(field) out << "\t" #field ": " << (int)bonus.field << "\n"
printField ( val ) ;
printField ( subtype ) ;
printField ( duration ) ;
printField ( source ) ;
2011-02-20 20:32:39 +02:00
printField ( sid ) ;
2010-07-12 13:20:25 +03:00
printField ( additionalInfo ) ;
printField ( turnsRemain ) ;
printField ( valType ) ;
printField ( effectRange ) ;
# undef printField
return out ;
}
ILimiter : : ~ ILimiter ( )
{
}
2010-11-19 00:06:56 +02:00
bool ILimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const /*return true to drop the bonus */
2010-07-12 13:20:25 +03:00
{
return false ;
}
2010-11-19 00:06:56 +02:00
bool CCreatureTypeLimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const
2010-07-12 13:20:25 +03:00
{
2011-02-12 18:12:48 +02:00
const CCreature * c = retrieveCreature ( & node ) ;
2011-02-22 11:47:25 +02:00
if ( ! c )
return true ;
2011-02-12 18:12:48 +02:00
return c ! = creature & & ( ! includeUpgrades | | ! creature - > isMyUpgrade ( c ) ) ;
//drop bonus if it's not our creature and (we dont check upgrades or its not our upgrade)
2010-07-12 13:20:25 +03:00
}
2011-02-12 18:12:48 +02:00
2010-07-12 13:20:25 +03:00
CCreatureTypeLimiter : : CCreatureTypeLimiter ( const CCreature & Creature , ui8 IncludeUpgrades /*= true*/ )
: creature ( & Creature ) , includeUpgrades ( IncludeUpgrades )
{
}
CCreatureTypeLimiter : : CCreatureTypeLimiter ( )
{
creature = NULL ;
includeUpgrades = false ;
2010-08-06 13:46:40 +03:00
}
HasAnotherBonusLimiter : : HasAnotherBonusLimiter ( TBonusType bonus )
: type ( bonus ) , subtype ( 0 ) , isSubtypeRelevant ( false )
{
}
HasAnotherBonusLimiter : : HasAnotherBonusLimiter ( TBonusType bonus , TBonusSubtype _subtype )
: type ( bonus ) , subtype ( _subtype ) , isSubtypeRelevant ( true )
{
}
2010-11-19 00:06:56 +02:00
bool HasAnotherBonusLimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const
2010-08-06 13:46:40 +03:00
{
if ( isSubtypeRelevant )
{
return ! node . hasBonusOfType ( static_cast < Bonus : : BonusType > ( type ) , subtype ) ;
}
else
{
return ! node . hasBonusOfType ( static_cast < Bonus : : BonusType > ( type ) ) ;
}
}
2010-11-19 00:22:51 +02:00
IPropagator : : ~ IPropagator ( )
{
2010-11-20 02:03:31 +02:00
}
2011-02-21 06:13:00 +02:00
// CBonusSystemNode * IPropagator::getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild)
// {
// tlog1 << "IPropagator::getDestNode called!\n";
// return source;
// }
bool IPropagator : : shouldBeAttached ( CBonusSystemNode * dest )
{
return false ;
}
// CBonusSystemNode * CPropagatorNodeType::getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild)
// {
// return NULL;
// }
CPropagatorNodeType : : CPropagatorNodeType ( )
{
}
CPropagatorNodeType : : CPropagatorNodeType ( ui8 NodeType )
: nodeType ( NodeType )
2010-11-20 02:03:31 +02:00
{
2011-02-21 06:13:00 +02:00
}
bool CPropagatorNodeType : : shouldBeAttached ( CBonusSystemNode * dest )
{
return nodeType = = dest - > nodeType ;
2010-11-20 02:03:31 +02:00
}
CreatureNativeTerrainLimiter : : CreatureNativeTerrainLimiter ( int TerrainType )
: terrainType ( TerrainType )
{
}
CreatureNativeTerrainLimiter : : CreatureNativeTerrainLimiter ( )
{
}
bool CreatureNativeTerrainLimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const
{
const CCreature * c = retrieveCreature ( & node ) ;
2011-02-21 06:13:00 +02:00
return ! c | | ! iswith ( c - > faction , 0 , 9 ) | | VLC - > heroh - > nativeTerrains [ c - > faction ] ! = terrainType ; //drop bonus for non-creatures or non-native residents
//TODO neutral creatues
2010-11-20 02:03:31 +02:00
}
CreatureFactionLimiter : : CreatureFactionLimiter ( int Faction )
: faction ( Faction )
{
}
CreatureFactionLimiter : : CreatureFactionLimiter ( )
{
}
bool CreatureFactionLimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const
{
const CCreature * c = retrieveCreature ( & node ) ;
return ! c | | c - > faction ! = faction ; //drop bonus for non-creatures or non-native residents
}
CreatureAlignmentLimiter : : CreatureAlignmentLimiter ( )
{
}
CreatureAlignmentLimiter : : CreatureAlignmentLimiter ( si8 Alignment )
: alignment ( Alignment )
{
}
bool CreatureAlignmentLimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const
{
const CCreature * c = retrieveCreature ( & node ) ;
if ( ! c )
return true ;
switch ( alignment )
{
case GOOD :
return ! c - > isGood ( ) ; //if not good -> return true (drop bonus)
case NEUTRAL :
return c - > isEvil ( ) | | c - > isGood ( ) ;
case EVIL :
return ! c - > isEvil ( ) ;
default :
tlog1 < < " Warning: illegal alignment in limiter! \n " ;
return true ;
}
2011-02-11 10:20:26 +02:00
}
2011-02-12 18:12:48 +02:00
RankRangeLimiter : : RankRangeLimiter ( ui8 Min , ui8 Max )
: minRank ( Min ) , maxRank ( Max )
2011-02-11 10:20:26 +02:00
{
}
2011-02-21 06:13:00 +02:00
RankRangeLimiter : : RankRangeLimiter ( )
{
minRank = maxRank = - 1 ;
}
2011-02-12 18:12:48 +02:00
bool RankRangeLimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const
2011-02-11 10:20:26 +02:00
{
2011-02-12 18:12:48 +02:00
const CStackInstance * csi = retreiveStackInstance ( & node ) ;
if ( csi )
return csi - > getExpRank ( ) < minRank | | csi - > getExpRank ( ) > maxRank ;
return true ;
2011-02-21 06:13:00 +02:00
}
bool StackOwnerLimiter : : limit ( const Bonus * b , const CBonusSystemNode & node ) const
{
const CStack * s = retreiveStackBattle ( & node ) ;
if ( s )
return s - > owner ! = owner ;
const CStackInstance * csi = retreiveStackInstance ( & node ) ;
if ( csi & & csi - > armyObj )
return csi - > armyObj - > tempOwner ! = owner ;
return true ;
}
StackOwnerLimiter : : StackOwnerLimiter ( )
: owner ( - 1 )
{
}
StackOwnerLimiter : : StackOwnerLimiter ( ui8 Owner )
: owner ( Owner )
{
2010-11-19 00:22:51 +02:00
}