mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Changes towards better bonus system.
This commit is contained in:
		| @@ -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 | ||||
| 				) | ||||
| 			{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user