1
0
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:
Michał W. Urbańczyk 2010-04-03 03:33:46 +00:00
parent b52707f0ae
commit 9a632246de
7 changed files with 147 additions and 92 deletions

View File

@ -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()

View File

@ -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

View File

@ -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;

View File

@ -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;
// }
// }
}
};

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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
)
{