mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Changes towards better bonus system.
This commit is contained in:
parent
b52707f0ae
commit
9a632246de
@ -993,11 +993,6 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentLuckModifiers
|
||||
return ret;
|
||||
}
|
||||
|
||||
const HeroBonus * CGHeroInstance::getBonus( int from, int id ) const
|
||||
{
|
||||
return bonuses.getBonus(from, id);
|
||||
}
|
||||
|
||||
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
|
||||
{
|
||||
if(what == 3)
|
||||
@ -1154,19 +1149,6 @@ si32 CGHeroInstance::manaRegain() const
|
||||
return 1 + getSecSkillLevel(8) + valOfBonuses(HeroBonus::MANA_REGENERATION); //1 + Mysticism level
|
||||
}
|
||||
|
||||
int CGHeroInstance::valOfBonuses( HeroBonus::BonusType type, int subtype /*= -1*/ ) const
|
||||
{
|
||||
return bonuses.valOfBonuses(type, subtype) + ownerBonuses()->valOfBonuses(type, subtype);
|
||||
}
|
||||
|
||||
bool CGHeroInstance::hasBonusOfType(HeroBonus::BonusType type, int subtype /*= -1*/) const
|
||||
{
|
||||
if(!this) //to allow calls on NULL and avoid checking duplication
|
||||
return false; //if hero doesn't exist then bonus neither can
|
||||
else
|
||||
return bonuses.hasBonusOfType(type, subtype) || ownerBonuses()->hasBonusOfType(type, subtype);
|
||||
}
|
||||
|
||||
si32 CGHeroInstance::getArtPos(int aid) const
|
||||
{
|
||||
for(std::map<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
|
||||
@ -1218,21 +1200,6 @@ bool CGHeroInstance::hasArt( ui32 aid ) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGHeroInstance::getModifiersWDescr( std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype /*= -1*/ ) const
|
||||
{
|
||||
bonuses.getModifiersWDescr(out, type, subtype);
|
||||
ownerBonuses()->getModifiersWDescr(out, type, subtype);
|
||||
}
|
||||
|
||||
const BonusList * CGHeroInstance::ownerBonuses() const
|
||||
{
|
||||
const PlayerState *p = cb->getPlayerState(tempOwner);
|
||||
if(!p)
|
||||
return NULL;
|
||||
else
|
||||
return &p->bonuses;
|
||||
}
|
||||
|
||||
int CGHeroInstance::getBoatType() const
|
||||
{
|
||||
int alignment = type->heroType / 6;
|
||||
@ -1261,15 +1228,16 @@ int CGHeroInstance::getSpellCost(const CSpell *sp) const
|
||||
return sp->costs[getSpellSchoolLevel(sp)];
|
||||
}
|
||||
|
||||
int CGHeroInstance::getBonusesCount(int from, int id) const
|
||||
void CGHeroInstance::getParents(TCNodes &out, const CBonusSystemNode *source) const
|
||||
{
|
||||
int ret = 0;
|
||||
const PlayerState *p = cb->getPlayerState(tempOwner);
|
||||
if(!p)
|
||||
{
|
||||
//occurs when initializing starting hero and heroes from the pool
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const HeroBonus &hb, bonuses)
|
||||
if(hb.source == from && hb.id == id)
|
||||
ret++;
|
||||
|
||||
return ret;
|
||||
out.push_back(p);
|
||||
}
|
||||
|
||||
void CGDwelling::initObj()
|
||||
|
@ -232,7 +232,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_EXPORT CGHeroInstance : public CArmedInstance, public IBoatGenerator
|
||||
class DLL_EXPORT CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -273,7 +273,7 @@ public:
|
||||
}
|
||||
} patrol;
|
||||
|
||||
BonusList bonuses;
|
||||
//BonusList bonuses;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@ -311,17 +311,8 @@ public:
|
||||
int getCurrentLuck(int stack=-1, bool town=false) const;
|
||||
int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
|
||||
|
||||
const BonusList *ownerBonuses() const;
|
||||
const HeroBonus *getBonus(int from, int id) const;
|
||||
int getBonusesCount(int from, int id) const;
|
||||
int valOfBonuses(HeroBonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then any
|
||||
bool hasBonusOfType(HeroBonus::BonusType type, int subtype = -1) const; //determines if hero has a bonus of given type (and optionally subtype)
|
||||
void getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype = -1) const; //out: pairs<modifier value, modifier description>
|
||||
template<int N> void getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, const HeroBonus::BonusType (&types)[N]) const //retreive array of types
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
getModifiersWDescr(out, types[i]);
|
||||
}
|
||||
|
||||
void getParents(TCNodes &out, const CBonusSystemNode *source = NULL) const;
|
||||
|
||||
std::vector<std::pair<int,std::string> > getCurrentLuckModifiers(int stack=-1, bool town=false) const; //args as above
|
||||
int getCurrentMorale(int stack=-1, bool town=false) const; //if stack - position of creature, if -1 then morale for hero is calculated; town - if bonuses from town (tavern) should be considered
|
||||
|
@ -2973,8 +2973,7 @@ bool CGameState::battleCanShoot(int ID, int dest)
|
||||
if(our->hasFeatureOfType(StackFeature::SHOOTER)//it's shooter
|
||||
&& our->owner != dst->owner
|
||||
&& dst->alive()
|
||||
&& (!curB->isStackBlocked(ID)
|
||||
|| ourHero->hasBonusOfType(HeroBonus::FREE_SHOOTING))
|
||||
&& (!curB->isStackBlocked(ID) || NBonus::hasOfType(ourHero, HeroBonus::FREE_SHOOTING))
|
||||
&& our->shots
|
||||
)
|
||||
return true;
|
||||
|
@ -105,7 +105,7 @@ struct DLL_EXPORT SThievesGuildInfo
|
||||
|
||||
};
|
||||
|
||||
struct DLL_EXPORT PlayerState
|
||||
struct DLL_EXPORT PlayerState : public CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
enum EStatus {INGAME, LOSER, WINNER};
|
||||
@ -118,7 +118,6 @@ public:
|
||||
std::vector<CGTownInstance *> towns;
|
||||
std::vector<CGHeroInstance *> availableHeroes; //heroes available in taverns
|
||||
std::vector<CGDwelling *> dwellings; //used for town growth
|
||||
BonusList bonuses; //player bonuses
|
||||
|
||||
ui8 status; //0 - in game, 1 - loser, 2 - winner <- uses EStatus enum
|
||||
ui8 daysWithoutCastle;
|
||||
@ -129,37 +128,6 @@ public:
|
||||
{
|
||||
h & color & serial & human & currentSelection & fogOfWarMap & resources & status;
|
||||
h & heroes & towns & availableHeroes & dwellings & bonuses & status & daysWithoutCastle;
|
||||
|
||||
// ui32 size;
|
||||
// if(h.saving) //write subids of available heroes
|
||||
// {
|
||||
// size = availableHeroes.size();
|
||||
// h & size;
|
||||
// for(size_t i=0; i < size; i++)
|
||||
// {
|
||||
// if(availableHeroes[i])
|
||||
// {
|
||||
// h & availableHeroes[i]->subID;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ui32 none = 0xffffffff;
|
||||
// h & none;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ui32 hid;
|
||||
// h & size;
|
||||
// for(size_t i=0; i < size; i++)
|
||||
// {
|
||||
// //fill availableHeroes with dummy hero instances, holding subids
|
||||
// h & hid;
|
||||
// availableHeroes.push_back(new CGHeroInstance);
|
||||
// availableHeroes[availableHeroes.size()-1]->subID = hid;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
#define VCMI_DLL
|
||||
#include "HeroBonus.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#define FOREACH_PARENT(pname) TCNodes parents; getParents(parents); BOOST_FOREACH(const CBonusSystemNode *pname, parents)
|
||||
|
||||
int BonusList::valOfBonuses( HeroBonus::BonusType type, int subtype /*= -1*/ ) const /*subtype -> subtype of bonus, if -1 then any */
|
||||
{
|
||||
@ -70,4 +73,92 @@ void BonusList::getModifiersWDescr( std::vector<std::pair<int,std::string> > &ou
|
||||
if(i->type == type && i->subtype == subtype)
|
||||
out.push_back(std::make_pair(i->val, i->description));
|
||||
}
|
||||
}
|
||||
|
||||
int CBonusSystemNode::valOfBonuses(HeroBonus::BonusType type, int subtype /*= -1*/) const
|
||||
{
|
||||
int ret = bonuses.valOfBonuses(type, subtype);
|
||||
|
||||
FOREACH_PARENT(p)
|
||||
ret += p->valOfBonuses(type, subtype);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CBonusSystemNode::hasBonusOfType(HeroBonus::BonusType type, int subtype /*= -1*/) const
|
||||
{
|
||||
if(!this) //to allow calls on NULL and avoid checking duplication
|
||||
return false; //if hero doesn't exist then bonus neither can
|
||||
|
||||
if(bonuses.hasBonusOfType(type, subtype))
|
||||
return true;
|
||||
|
||||
FOREACH_PARENT(p)
|
||||
if(p->hasBonusOfType(type, subtype))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const HeroBonus * CBonusSystemNode::getBonus(int from, int id) const
|
||||
{
|
||||
return bonuses.getBonus(from, id);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype /*= -1 */) const
|
||||
{
|
||||
bonuses.getModifiersWDescr(out, type, subtype);
|
||||
|
||||
FOREACH_PARENT(p)
|
||||
p->getModifiersWDescr(out, type, subtype);
|
||||
}
|
||||
|
||||
int CBonusSystemNode::getBonusesCount(int from, int id) const
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
BOOST_FOREACH(const HeroBonus &hb, bonuses)
|
||||
if(hb.source == from && hb.id == id)
|
||||
ret++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getParents(TCNodes &out, const CBonusSystemNode *source) const /*retreives list of parent nodes (nodes to inherit bonuses from) */
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int NBonus::valOf(const CBonusSystemNode *obj, HeroBonus::BonusType type, int subtype /*= -1*/)
|
||||
{
|
||||
if(obj)
|
||||
return obj->valOfBonuses(type, subtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NBonus::hasOfType(const CBonusSystemNode *obj, HeroBonus::BonusType type, int subtype /*= -1*/)
|
||||
{
|
||||
if(obj)
|
||||
return obj->hasBonusOfType(type, subtype);
|
||||
return false;
|
||||
}
|
||||
|
||||
const HeroBonus * NBonus::get(const CBonusSystemNode *obj, int from, int id)
|
||||
{
|
||||
if(obj)
|
||||
return obj->getBonus(from, id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void NBonus::getModifiersWDescr(const CBonusSystemNode *obj, std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype /*= -1 */)
|
||||
{
|
||||
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;
|
||||
}
|
@ -113,9 +113,13 @@ struct DLL_EXPORT HeroBonus
|
||||
|
||||
};
|
||||
|
||||
class CBonusSystemNode;
|
||||
|
||||
static const HeroBonus::BonusType MORALE_AFFECTING[] = {HeroBonus::MORALE, HeroBonus::MORALE_AND_LUCK};
|
||||
static const HeroBonus::BonusType LUCK_AFFECTING[] = {HeroBonus::LUCK, HeroBonus::MORALE_AND_LUCK};
|
||||
typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions
|
||||
typedef std::list<CBonusSystemNode*> TNodes;
|
||||
typedef std::list<const CBonusSystemNode*> TCNodes;
|
||||
|
||||
class BonusList : public std::list<HeroBonus>
|
||||
{
|
||||
@ -129,4 +133,39 @@ public:
|
||||
{
|
||||
h & static_cast<std::list<HeroBonus>&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_EXPORT CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
BonusList bonuses;
|
||||
|
||||
virtual void getParents(TCNodes &out, const CBonusSystemNode *source = NULL) const; //retreives list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
|
||||
|
||||
int valOfBonuses(HeroBonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then any
|
||||
bool hasBonusOfType(HeroBonus::BonusType type, int subtype = -1) const;//determines if hero has a bonus of given type (and optionally subtype)
|
||||
const HeroBonus * getBonus( int from, int id ) const;
|
||||
void getModifiersWDescr( std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype = -1 ) const; //out: pairs<modifier value, modifier description>
|
||||
int getBonusesCount(int from, int id) const;
|
||||
|
||||
template<int N> void getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, const HeroBonus::BonusType (&types)[N]) const //retreive array of types
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
getModifiersWDescr(out, types[i]);
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & bonuses;
|
||||
}
|
||||
};
|
||||
|
||||
namespace NBonus
|
||||
{
|
||||
//set of methods that may be safely called with NULL objs
|
||||
DLL_EXPORT int valOf(const CBonusSystemNode *obj, HeroBonus::BonusType type, int subtype = -1); //subtype -> subtype of bonus, if -1 then any
|
||||
DLL_EXPORT bool hasOfType(const CBonusSystemNode *obj, HeroBonus::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, std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype = -1 ); //out: pairs<modifier value, modifier description>
|
||||
DLL_EXPORT int getCount(const CBonusSystemNode *obj, int from, int id);
|
||||
};
|
@ -337,7 +337,6 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
|
||||
NEW_ROUND;
|
||||
//TODO: pre-tactic stuff, call scripts etc.
|
||||
|
||||
|
||||
//tactic round
|
||||
{
|
||||
NEW_ROUND;
|
||||
@ -362,7 +361,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
|
||||
|
||||
//check for bad morale => freeze
|
||||
if( curB.Morale(next) < 0 &&
|
||||
!((hero1->hasBonusOfType(HeroBonus::BLOCK_MORALE)) || (hero2->hasBonusOfType(HeroBonus::BLOCK_MORALE))) //checking if heroes have (or don't have) morale blocking bonuses)
|
||||
!(NBonus::hasOfType(hero1, HeroBonus::BLOCK_MORALE) || NBonus::hasOfType(hero2, HeroBonus::BLOCK_MORALE)) //checking if heroes have (or don't have) morale blocking bonuses)
|
||||
)
|
||||
{
|
||||
if( rand()%24 < (-curB.Morale(next))*2 )
|
||||
@ -509,7 +508,7 @@ askInterfaceForMove:
|
||||
&& !vstd::contains(next->state,WAITING)
|
||||
&& next->alive()
|
||||
&& curB.Morale(next) > 0
|
||||
&& !((hero1->hasBonusOfType(HeroBonus::BLOCK_MORALE)) || (hero2->hasBonusOfType(HeroBonus::BLOCK_MORALE)) ) //checking if heroes have (or don't have) morale blocking bonuses
|
||||
&& !(NBonus::hasOfType(hero1, HeroBonus::BLOCK_MORALE) || NBonus::hasOfType(hero2, HeroBonus::BLOCK_MORALE)) //checking if heroes have (or don't have) morale blocking bonuses
|
||||
)
|
||||
if(rand()%24 < curB.Morale(next)) //this stack hasn't got morale this turn
|
||||
goto askInterfaceForMove; //move this stack once more
|
||||
@ -3689,7 +3688,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
|| (h->mana < gs->curB->getSpellCost(s, h)) //not enough mana
|
||||
|| (ba.additionalInfo < 10) //it's adventure spell (not combat)
|
||||
|| (gs->curB->castSpells[ba.side]) //spell has been cast
|
||||
|| (secondHero->hasBonusOfType(HeroBonus::SPELL_IMMUNITY, s->id)) //non - casting hero provides immunity for this spell
|
||||
|| (NBonus::hasOfType(secondHero, HeroBonus::SPELL_IMMUNITY, s->id)) //non - casting hero provides immunity for this spell
|
||||
|| (gs->battleMaxSpellLevel() < s->level) //non - casting hero stops caster from casting this spell
|
||||
)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user