mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Fixed #484. Preliminary support for bonus limiters/
This commit is contained in:
		| @@ -48,6 +48,7 @@ | |||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| #include "SDL_syswm.h" | #include "SDL_syswm.h" | ||||||
| #endif | #endif | ||||||
|  | #include <boost/foreach.hpp> | ||||||
|  |  | ||||||
| #if __MINGW32__ | #if __MINGW32__ | ||||||
| #undef main | #undef main | ||||||
| @@ -427,6 +428,19 @@ void processCommand(const std::string &message) | |||||||
| 		if(const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection)) | 		if(const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection)) | ||||||
| 			tlog0 << h->movement << "; max: " << h->maxMovePoints(true) << "/" << h->maxMovePoints(false) << std::endl; | 			tlog0 << h->movement << "; max: " << h->maxMovePoints(true) << "/" << h->maxMovePoints(false) << std::endl; | ||||||
| 	} | 	} | ||||||
|  | 	else if(cn == "bonuses") | ||||||
|  | 	{ | ||||||
|  | 		tlog0 << "Bonuses of " << adventureInt->selection->getHoverText() << std::endl | ||||||
|  | 			<< adventureInt->selection->bonuses << std::endl; | ||||||
|  |  | ||||||
|  | 		tlog0 << "\nInherited bonuses:\n"; | ||||||
|  | 		TCNodes parents; | ||||||
|  | 		adventureInt->selection->getParents(parents); | ||||||
|  | 		BOOST_FOREACH(const CBonusSystemNode *parent, parents) | ||||||
|  | 		{ | ||||||
|  | 			tlog0 << "\nBonuses from " << typeid(*parent).name() << std::endl << parent->bonuses << std::endl; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	else if(client && client->serv && client->serv->connected) //send to server | 	else if(client && client->serv && client->serv->connected) //send to server | ||||||
| 	{ | 	{ | ||||||
| 		PlayerMessage pm(LOCPLINT->playerID,message); | 		PlayerMessage pm(LOCPLINT->playerID,message); | ||||||
|   | |||||||
| @@ -128,6 +128,12 @@ void CCreature::addBonus(int val, int type, int subtype /*= -1*/) | |||||||
| 	bonuses.push_back(added); | 	bonuses.push_back(added); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool CCreature::isMyUpgrade(const CCreature *anotherCre) const | ||||||
|  | { | ||||||
|  | 	//TODO upgrade of upgrade? | ||||||
|  | 	return vstd::contains(upgrades, anotherCre->idNumber); | ||||||
|  | } | ||||||
|  |  | ||||||
| int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo() | int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo() | ||||||
| { | { | ||||||
| 	befi=i; | 	befi=i; | ||||||
| @@ -337,12 +343,7 @@ void CCreatureHandler::loadCreatures() | |||||||
| 			creatures.push_back(&ncre); | 			creatures.push_back(&ncre); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	 | ||||||
| 	// Map types names |  | ||||||
| #define BONUS_NAME(x) ( #x, Bonus::x ) |  | ||||||
| 	static const std::map<std::string, int> type_list = map_list_of BONUS_LIST; |  | ||||||
| #undef BONUS_NAME |  | ||||||
|  |  | ||||||
| 	////second part of reading cr_abils.txt//// | 	////second part of reading cr_abils.txt//// | ||||||
| 	bool contReading = true; | 	bool contReading = true; | ||||||
| 	while(contReading) //main reading loop | 	while(contReading) //main reading loop | ||||||
| @@ -363,10 +364,10 @@ void CCreatureHandler::loadCreatures() | |||||||
| 				reader >> creatureID; | 				reader >> creatureID; | ||||||
| 				reader >> type; | 				reader >> type; | ||||||
|  |  | ||||||
| 				std::map<std::string, int>::const_iterator it = type_list.find(type); | 				std::map<std::string, int>::const_iterator it = bonusNameMap.find(type); | ||||||
| 				CCreature *cre = creatures[creatureID]; | 				CCreature *cre = creatures[creatureID]; | ||||||
|  |  | ||||||
| 				if (it == type_list.end())  | 				if (it == bonusNameMap.end())  | ||||||
| 				{ | 				{ | ||||||
| 					if(type == "DOUBLE_WIDE") | 					if(type == "DOUBLE_WIDE") | ||||||
| 						cre->doubleWide = true; | 						cre->doubleWide = true; | ||||||
| @@ -403,8 +404,8 @@ void CCreatureHandler::loadCreatures() | |||||||
| 				std::string type; | 				std::string type; | ||||||
| 				reader >> creatureID; | 				reader >> creatureID; | ||||||
| 				reader >> type; | 				reader >> type; | ||||||
| 				std::map<std::string, int>::const_iterator it = type_list.find(type); | 				std::map<std::string, int>::const_iterator it = bonusNameMap.find(type); | ||||||
| 				if (it == type_list.end()) | 				if (it == bonusNameMap.end()) | ||||||
| 				{ | 				{ | ||||||
| 					if(type == "DOUBLE_WIDE") | 					if(type == "DOUBLE_WIDE") | ||||||
| 						creatures[creatureID]->doubleWide = false; | 						creatures[creatureID]->doubleWide = false; | ||||||
|   | |||||||
| @@ -55,9 +55,11 @@ public: | |||||||
| 	bool isEvil () const; | 	bool isEvil () const; | ||||||
| 	si32 maxAmount(const std::vector<si32> &res) const; //how many creatures can be bought | 	si32 maxAmount(const std::vector<si32> &res) const; //how many creatures can be bought | ||||||
| 	static int getQuantityID(const int & quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion | 	static int getQuantityID(const int & quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion | ||||||
|  | 	bool isMyUpgrade(const CCreature *anotherCre) const; | ||||||
|  |  | ||||||
| 	void addBonus(int val, int type, int subtype = -1); | 	void addBonus(int val, int type, int subtype = -1); | ||||||
|  |  | ||||||
|  |  | ||||||
| 	template<typename RanGen> | 	template<typename RanGen> | ||||||
| 	int getRandomAmount(RanGen &ranGen) | 	int getRandomAmount(RanGen &ranGen) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -973,50 +973,60 @@ void CGHeroInstance::initObj() | |||||||
| 		{ | 		{ | ||||||
| 			case 1:// creature speciality | 			case 1:// creature speciality | ||||||
| 				{ | 				{ | ||||||
|  | 					speciality.growthsWithLevel = true; | ||||||
|  |  | ||||||
| 					bonus.type = Bonus::SPECIAL_CREATURE_LEV; // general info to indicate type of growing bonus | 					bonus.type = Bonus::SPECIAL_CREATURE_LEV; // general info to indicate type of growing bonus | ||||||
| 					bonus.additionalInfo = it->additionalinfo; //base creature ID | 					bonus.additionalInfo = it->additionalinfo; //base creature ID | ||||||
| 					speciality.bonuses.push_back (bonus); | 					speciality.bonuses.push_back (bonus); | ||||||
|  |  | ||||||
| 					std::vector<CCreature*>* creatures = &VLC->creh->creatures; | 					const CCreature &specCreature = *VLC->creh->creatures[it->additionalinfo]; //creature in which we have specialty | ||||||
| 					int creLevel = (*creatures)[it->additionalinfo]->level; |  | ||||||
|  | 					int creLevel = specCreature.level; | ||||||
| 					if(!creLevel) //TODO: set fixed level for War Machines | 					if(!creLevel) //TODO: set fixed level for War Machines | ||||||
| 					{ | 					{ | ||||||
| 						if(it->additionalinfo == 146) | 						if(it->additionalinfo == 146) | ||||||
| 							creLevel = 5; //treat ballista as 5-level | 							creLevel = 5; //treat ballista as 5-level | ||||||
| 						else | 						else | ||||||
| 						{ | 						{ | ||||||
| 							tlog2 << "Warning: unknown level of " << (*creatures)[it->additionalinfo]->namePl << std::endl; | 							tlog2 << "Warning: unknown level of " << specCreature.namePl << std::endl; | ||||||
| 							continue; | 							continue; | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					speciality.growthsWithLevel = true; | 					int levelFactor = level / creLevel; //round down | ||||||
| 					bonus.type = Bonus::PRIMARY_SKILL; //TODO: limit to specific creature type | 					double primSkillModifier = levelFactor / 20.0; | ||||||
|  |  | ||||||
|  | 					bonus.limiter = new CCreatureTypeLimiter(specCreature); | ||||||
|  | 					bonus.type = Bonus::PRIMARY_SKILL;  | ||||||
| 					bonus.valType = Bonus::ADDITIVE_VALUE; | 					bonus.valType = Bonus::ADDITIVE_VALUE; | ||||||
| 					bonus.subtype = 1; //attack |  | ||||||
| 					bonus.val = level * (*creatures)[it->additionalinfo]->attack / creLevel /20; | 					bonus.subtype = PrimarySkill::ATTACK; | ||||||
|  | 					bonus.val = std::ceil(primSkillModifier * specCreature.attack); | ||||||
| 					speciality.bonuses.push_back (bonus); | 					speciality.bonuses.push_back (bonus); | ||||||
| 					bonus.subtype = 2; //defense |  | ||||||
| 					bonus.val = level * (*creatures)[it->additionalinfo]->defence / creLevel /20; | 					bonus.subtype = PrimarySkill::DEFENSE; | ||||||
|  | 					bonus.val = std::ceil(primSkillModifier * specCreature.defence); | ||||||
| 					speciality.bonuses.push_back (bonus); | 					speciality.bonuses.push_back (bonus); | ||||||
|  |  | ||||||
| 					bonus.type = Bonus::STACKS_SPEED; | 					bonus.type = Bonus::STACKS_SPEED; | ||||||
| 					bonus.val = 1; //+1 speed | 					bonus.val = 1; //+1 speed | ||||||
| 					speciality.bonuses.push_back (bonus); | 					speciality.bonuses.push_back (bonus); | ||||||
| 					for (std::set<ui32>::iterator i = (*creatures)[it->additionalinfo]->upgrades.begin(); |  | ||||||
| 						i != VLC->creh->creatures[it->additionalinfo]->upgrades.end(); i++) | // 					for (std::set<ui32>::iterator i = (*creatures)[it->additionalinfo]->upgrades.begin(); | ||||||
| 					{ | // 						i != VLC->creh->creatures[it->additionalinfo]->upgrades.end(); i++) | ||||||
| 						bonus.val = (*i); // for all direct upgrades of that creature | // 					{ | ||||||
| 						bonus.type = Bonus::PRIMARY_SKILL; | // 						bonus.val = (*i); // for all direct upgrades of that creature | ||||||
| 						bonus.subtype = 1; //attack | // 						bonus.type = Bonus::PRIMARY_SKILL; | ||||||
| 						bonus.val = level * (*creatures)[*i]->attack / (*creatures)[*i]->level /20; | // 						bonus.subtype = 1; //attack | ||||||
| 						speciality.bonuses.push_back (bonus); | // 						bonus.val = level * (*creatures)[*i]->attack / (*creatures)[*i]->level /20; | ||||||
| 						bonus.subtype = 2; //defense | // 						speciality.bonuses.push_back (bonus); | ||||||
| 						bonus.val = level * (*creatures)[*i]->defence / (*creatures)[*i]->level /20; | // 						bonus.subtype = 2; //defense | ||||||
| 						speciality.bonuses.push_back (bonus); | // 						bonus.val = level * (*creatures)[*i]->defence / (*creatures)[*i]->level /20; | ||||||
| 						bonus.type = Bonus::STACKS_SPEED; | // 						speciality.bonuses.push_back (bonus); | ||||||
| 						bonus.val = 1; //+1 speed | // 						bonus.type = Bonus::STACKS_SPEED; | ||||||
| 						speciality.bonuses.push_back (bonus); | // 						bonus.val = 1; //+1 speed | ||||||
| 					} | // 						speciality.bonuses.push_back (bonus); | ||||||
|  | // 					} | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| 			case 2://secondary skill | 			case 2://secondary skill | ||||||
|   | |||||||
| @@ -252,6 +252,7 @@ void CStackInstance::init() | |||||||
| 	type = NULL; | 	type = NULL; | ||||||
| 	idRand = -1; | 	idRand = -1; | ||||||
| 	armyObj = NULL; | 	armyObj = NULL; | ||||||
|  | 	nodeType = STACK; | ||||||
| } | } | ||||||
|  |  | ||||||
| int CStackInstance::getQuantityID() const  | int CStackInstance::getQuantityID() const  | ||||||
|   | |||||||
| @@ -117,11 +117,11 @@ class CObjectCaller : public IObjectCaller | |||||||
| public: | public: | ||||||
| 	void preInit() | 	void preInit() | ||||||
| 	{ | 	{ | ||||||
| 		T::preInit(); | 		//T::preInit(); | ||||||
| 	} | 	} | ||||||
| 	void postInit() | 	void postInit() | ||||||
| 	{ | 	{ | ||||||
| 		T::postInit(); | 		//T::postInit(); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -148,14 +148,14 @@ public: | |||||||
|  |  | ||||||
| 	void preInit() | 	void preInit() | ||||||
| 	{ | 	{ | ||||||
| 		for (size_t i = 0; i < apps.size(); i++) | // 		for (size_t i = 0; i < apps.size(); i++) | ||||||
| 			apps[i]->preInit(); | // 			apps[i]->preInit(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void postInit() | 	void postInit() | ||||||
| 	{ | 	{ | ||||||
| 		for (size_t i = 0; i < apps.size(); i++) | // 		for (size_t i = 0; i < apps.size(); i++) | ||||||
| 			apps[i]->postInit(); | // 			apps[i]->postInit(); | ||||||
| 	} | 	} | ||||||
| } *objCaller = NULL; | } *objCaller = NULL; | ||||||
|  |  | ||||||
| @@ -2365,7 +2365,7 @@ int3 CGameState::guardingCreaturePosition (int3 pos) const | |||||||
| 			if (map->isInTheMap(pos))  | 			if (map->isInTheMap(pos))  | ||||||
| 			{ | 			{ | ||||||
| 				TerrainTile &tile = map->terrain[pos.x][pos.y][pos.z]; | 				TerrainTile &tile = map->terrain[pos.x][pos.y][pos.z]; | ||||||
| 				if (tile.visitable)  | 				if (tile.visitable && (tile.tertype == TerrainTile::water) == (posTile.tertype == TerrainTile::water))  | ||||||
| 				{ | 				{ | ||||||
| 					BOOST_FOREACH (CGObjectInstance* obj, tile.visitableObjects)  | 					BOOST_FOREACH (CGObjectInstance* obj, tile.visitableObjects)  | ||||||
| 					{ | 					{ | ||||||
|   | |||||||
| @@ -5,10 +5,16 @@ | |||||||
| #include "../hch/CSpellHandler.h" | #include "../hch/CSpellHandler.h" | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include "../hch/CCreatureHandler.h" | #include "../hch/CCreatureHandler.h" | ||||||
|  | #include <boost/assign/list_of.hpp> | ||||||
|  | #include "CCreatureSet.h" | ||||||
|  |  | ||||||
| #define FOREACH_CONST_PARENT(pname, source) 	TCNodes parents; getParents(parents, source); BOOST_FOREACH(const CBonusSystemNode *pname, parents) | #define FOREACH_CONST_PARENT(pname, source) 	TCNodes parents; getParents(parents, source); BOOST_FOREACH(const CBonusSystemNode *pname, parents) | ||||||
| #define FOREACH_PARENT(pname, source) 	TNodes parents; getParents(parents, source); BOOST_FOREACH(CBonusSystemNode *pname, parents) | #define FOREACH_PARENT(pname, source) 	TNodes parents; getParents(parents, source); BOOST_FOREACH(CBonusSystemNode *pname, parents) | ||||||
|  |  | ||||||
|  | #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 | ||||||
|  |  | ||||||
| int DLL_EXPORT BonusList::totalValue() const | int DLL_EXPORT BonusList::totalValue() const | ||||||
| { | { | ||||||
| 	int base = 0; | 	int base = 0; | ||||||
| @@ -75,6 +81,19 @@ void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector, | |||||||
| 			out.push_back(*i); | 			out.push_back(*i); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void BonusList::limit(const CBonusSystemNode &node) | ||||||
|  | { | ||||||
|  | 	for(const_iterator i = begin(); i != end(); i++) | ||||||
|  | 	{ | ||||||
|  | 		if(i->limiter && i->limiter->limit(*i, node)) | ||||||
|  | 		{ | ||||||
|  | 			const_iterator toErase = i; | ||||||
|  | 			i--; | ||||||
|  | 			erase(toErase); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const | int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const | ||||||
| { | { | ||||||
| 	CSelector s = Selector::type(type); | 	CSelector s = Selector::type(type); | ||||||
| @@ -161,6 +180,9 @@ void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, con | |||||||
| 	bonuses.getBonuses(out, selector); | 	bonuses.getBonuses(out, selector); | ||||||
| 	FOREACH_CONST_PARENT(p, root ? root : this) | 	FOREACH_CONST_PARENT(p, root ? root : this) | ||||||
| 		p->getBonuses(out, selector, root ? root : this); | 		p->getBonuses(out, selector, root ? root : this); | ||||||
|  | 	 | ||||||
|  | 	if(!root) | ||||||
|  | 		out.limit(*this); | ||||||
| } | } | ||||||
|  |  | ||||||
| BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const | BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const | ||||||
| @@ -175,6 +197,9 @@ void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, con | |||||||
| 	bonuses.getBonuses(out, selector, limit); | 	bonuses.getBonuses(out, selector, limit); | ||||||
| 	FOREACH_CONST_PARENT(p, root ? root : this) | 	FOREACH_CONST_PARENT(p, root ? root : this) | ||||||
| 		p->getBonuses(out, selector, limit, root ? root : this); | 		p->getBonuses(out, selector, limit, root ? root : this); | ||||||
|  |  | ||||||
|  | 	if(!root) | ||||||
|  | 		out.limit(*this); | ||||||
| } | } | ||||||
|  |  | ||||||
| BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const | BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const | ||||||
| @@ -245,6 +270,16 @@ ui16 CBonusSystemNode::MaxHealth() const | |||||||
| 	return valOfBonuses(Bonus::STACK_HEALTH); | 	return valOfBonuses(Bonus::STACK_HEALTH); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | CBonusSystemNode::CBonusSystemNode() | ||||||
|  | { | ||||||
|  | 	nodeType = UNKNOWN; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CBonusSystemNode::~CBonusSystemNode() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/) | int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/) | ||||||
| { | { | ||||||
| 	if(obj) | 	if(obj) | ||||||
| @@ -346,4 +381,65 @@ namespace Selector | |||||||
| 		dummy.subtype = subtype; | 		dummy.subtype = subtype; | ||||||
| 		return sel(dummy); | 		return sel(dummy); | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | DLL_EXPORT std::ostream & operator<<(std::ostream &out, const BonusList &bonusList) | ||||||
|  | { | ||||||
|  | 	int i = 0; | ||||||
|  | 	BOOST_FOREACH(const Bonus &b, bonusList) | ||||||
|  | 	{ | ||||||
|  | 		out << "Bonus " << i++ << "\n" << b << std::endl; | ||||||
|  | 	} | ||||||
|  | 	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 << "\tType: " << i->first << " \t"; | ||||||
|  |  | ||||||
|  | #define printField(field) out << "\t" #field ": " << (int)bonus.field << "\n" | ||||||
|  | 	printField(val); | ||||||
|  | 	printField(subtype); | ||||||
|  | 	printField(duration); | ||||||
|  | 	printField(source); | ||||||
|  | 	printField(id); | ||||||
|  | 	printField(additionalInfo); | ||||||
|  | 	printField(turnsRemain); | ||||||
|  | 	printField(valType); | ||||||
|  | 	printField(effectRange); | ||||||
|  | #undef printField | ||||||
|  |  | ||||||
|  | 	return out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ILimiter::~ILimiter() | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool ILimiter::limit(const Bonus &b, const CBonusSystemNode &node) const /*return true to drop the bonus */ | ||||||
|  | { | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool CCreatureTypeLimiter::limit(const Bonus &b, const CBonusSystemNode &node) const | ||||||
|  | { | ||||||
|  | 	if(node.nodeType != CBonusSystemNode::STACK) | ||||||
|  | 		return true; | ||||||
|  |  | ||||||
|  | 	const CCreature *c = (static_cast<const CStackInstance *>(&node))->type; | ||||||
|  |  | ||||||
|  | 	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) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CCreatureTypeLimiter::CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades /*= true*/) | ||||||
|  | 	:creature(&Creature), includeUpgrades(IncludeUpgrades) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CCreatureTypeLimiter::CCreatureTypeLimiter() | ||||||
|  | { | ||||||
|  | 	creature = NULL; | ||||||
|  | 	includeUpgrades = false; | ||||||
| } | } | ||||||
| @@ -19,17 +19,17 @@ | |||||||
| typedef ui8 TBonusType; | typedef ui8 TBonusType; | ||||||
| typedef si32 TBonusSubtype; | typedef si32 TBonusSubtype; | ||||||
|  |  | ||||||
|  | class CCreature; | ||||||
| class CSpell; | class CSpell; | ||||||
| struct Bonus; | struct Bonus; | ||||||
| class CBonusSystemNode; | class CBonusSystemNode; | ||||||
|  | class ILimiter; | ||||||
|  |  | ||||||
| typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions | typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions | ||||||
| typedef std::set<CBonusSystemNode*> TNodes; | typedef std::set<CBonusSystemNode*> TNodes; | ||||||
| typedef std::set<const CBonusSystemNode*> TCNodes; | typedef std::set<const CBonusSystemNode*> TCNodes; | ||||||
| typedef boost::function<bool(const Bonus&)> CSelector; | typedef boost::function<bool(const Bonus&)> CSelector; | ||||||
|  |  | ||||||
|  |  | ||||||
| namespace PrimarySkill | namespace PrimarySkill | ||||||
| { | { | ||||||
| 	enum { ATTACK, DEFENSE, SPELL_POWER, KNOWLEDGE}; | 	enum { ATTACK, DEFENSE, SPELL_POWER, KNOWLEDGE}; | ||||||
| @@ -223,6 +223,8 @@ struct DLL_EXPORT Bonus | |||||||
| 	si32 additionalInfo; | 	si32 additionalInfo; | ||||||
| 	ui8 effectRange; //if not NO_LIMIT, bonus will be ommitted by default | 	ui8 effectRange; //if not NO_LIMIT, bonus will be ommitted by default | ||||||
|  |  | ||||||
|  | 	ILimiter *limiter; | ||||||
|  |  | ||||||
| 	std::string description;  | 	std::string description;  | ||||||
|  |  | ||||||
| 	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, std::string Desc, si32 Subtype=-1) | ||||||
| @@ -232,6 +234,7 @@ struct DLL_EXPORT Bonus | |||||||
| 		turnsRemain = 0; | 		turnsRemain = 0; | ||||||
| 		valType = ADDITIVE_VALUE; | 		valType = ADDITIVE_VALUE; | ||||||
| 		effectRange = NO_LIMIT; | 		effectRange = NO_LIMIT; | ||||||
|  | 		limiter = NULL; | ||||||
| 	} | 	} | ||||||
| 	Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, si32 Subtype=-1, ui8 ValType = ADDITIVE_VALUE) | 	Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, si32 Subtype=-1, ui8 ValType = ADDITIVE_VALUE) | ||||||
| 		:duration(Dur), type(Type), subtype(Subtype), source(Src), val(Val), id(ID), valType(ValType) | 		:duration(Dur), type(Type), subtype(Subtype), source(Src), val(Val), id(ID), valType(ValType) | ||||||
| @@ -239,6 +242,7 @@ struct DLL_EXPORT Bonus | |||||||
| 		additionalInfo = -1; | 		additionalInfo = -1; | ||||||
| 		turnsRemain = 0; | 		turnsRemain = 0; | ||||||
| 		effectRange = NO_LIMIT; | 		effectRange = NO_LIMIT; | ||||||
|  | 		limiter = NULL; | ||||||
| 	} | 	} | ||||||
| 	Bonus() | 	Bonus() | ||||||
| 	{ | 	{ | ||||||
| @@ -247,6 +251,7 @@ struct DLL_EXPORT Bonus | |||||||
| 		turnsRemain = 0; | 		turnsRemain = 0; | ||||||
| 		valType = ADDITIVE_VALUE; | 		valType = ADDITIVE_VALUE; | ||||||
| 		effectRange = NO_LIMIT; | 		effectRange = NO_LIMIT; | ||||||
|  | 		limiter = NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| // 	//comparison | // 	//comparison | ||||||
| @@ -263,7 +268,7 @@ struct DLL_EXPORT Bonus | |||||||
|  |  | ||||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | 	template <typename Handler> void serialize(Handler &h, const int version) | ||||||
| 	{ | 	{ | ||||||
| 		h & duration & type & subtype & source & val & id & description & additionalInfo & turnsRemain & valType & effectRange; | 		h & duration & type & subtype & source & val & id & description & additionalInfo & turnsRemain & valType & effectRange & limiter; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static bool OneDay(const Bonus &hb) | 	static bool OneDay(const Bonus &hb) | ||||||
| @@ -307,6 +312,8 @@ struct DLL_EXPORT Bonus | |||||||
| 	std::string Description() const; | 	std::string Description() const; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus); | ||||||
|  |  | ||||||
| class BonusList : public std::list<Bonus> | class BonusList : public std::list<Bonus> | ||||||
| { | { | ||||||
| public: | public: | ||||||
| @@ -319,16 +326,35 @@ public: | |||||||
| 	DLL_EXPORT Bonus * getFirst(const CSelector &select); | 	DLL_EXPORT Bonus * getFirst(const CSelector &select); | ||||||
| 	DLL_EXPORT const Bonus * getFirst(const CSelector &select) const; | 	DLL_EXPORT const Bonus * getFirst(const CSelector &select) const; | ||||||
|  |  | ||||||
|  | 	void limit(const CBonusSystemNode &node); //erases bonuses using limitor | ||||||
|  |  | ||||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | 	template <typename Handler> void serialize(Handler &h, const int version) | ||||||
| 	{ | 	{ | ||||||
| 		h & static_cast<std::list<Bonus>&>(*this); | 		h & static_cast<std::list<Bonus>&>(*this); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | DLL_EXPORT std::ostream & operator<<(std::ostream &out, const BonusList &bonusList); | ||||||
|  |  | ||||||
|  | class DLL_EXPORT ILimiter | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	virtual ~ILimiter(); | ||||||
|  |  | ||||||
|  | 	virtual bool limit(const Bonus &b, const CBonusSystemNode &node) const; //return true to drop the bonus | ||||||
|  |  | ||||||
|  | 	template <typename Handler> void serialize(Handler &h, const int version) | ||||||
|  | 	{} | ||||||
|  | }; | ||||||
|  |  | ||||||
| class DLL_EXPORT CBonusSystemNode | class DLL_EXPORT CBonusSystemNode | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	BonusList bonuses; | 	BonusList bonuses; | ||||||
|  | 	ui8 nodeType; | ||||||
|  |  | ||||||
|  | 	CBonusSystemNode(); | ||||||
|  | 	virtual ~CBonusSystemNode(); | ||||||
|  |  | ||||||
| 	//new bonusing node interface | 	//new bonusing node interface | ||||||
| 	// * selector is predicate that tests if HeroBonus matches our criteria | 	// * selector is predicate that tests if HeroBonus matches our criteria | ||||||
| @@ -366,8 +392,13 @@ public: | |||||||
|  |  | ||||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | 	template <typename Handler> void serialize(Handler &h, const int version) | ||||||
| 	{ | 	{ | ||||||
| 		h & bonuses; | 		h & bonuses & nodeType; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	enum ENodeTypes | ||||||
|  | 	{ | ||||||
|  | 		UNKNOWN, STACK | ||||||
|  | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| namespace NBonus | namespace NBonus | ||||||
| @@ -450,6 +481,23 @@ public: | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | class CCreatureTypeLimiter : public ILimiter //affect only stacks of given creature (and optionally it's upgrades) | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	const CCreature *creature; | ||||||
|  | 	ui8 includeUpgrades; | ||||||
|  |  | ||||||
|  | 	CCreatureTypeLimiter(); | ||||||
|  | 	CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades = true); | ||||||
|  |  | ||||||
|  | 	bool limit(const Bonus &b, const CBonusSystemNode &node) const; | ||||||
|  |  | ||||||
|  | 	template <typename Handler> void serialize(Handler &h, const int version) | ||||||
|  | 	{ | ||||||
|  | 		h & creature & includeUpgrades; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
| namespace Selector | namespace Selector | ||||||
| { | { | ||||||
| 	extern DLL_EXPORT CSelectFieldEqual<TBonusType> type; | 	extern DLL_EXPORT CSelectFieldEqual<TBonusType> type; | ||||||
| @@ -466,3 +514,5 @@ namespace Selector | |||||||
| 	bool DLL_EXPORT matchesType(const CSelector &sel, TBonusType type); | 	bool DLL_EXPORT matchesType(const CSelector &sel, TBonusType type); | ||||||
| 	bool DLL_EXPORT matchesTypeSubtype(const CSelector &sel, TBonusType type, TBonusSubtype subtype); | 	bool DLL_EXPORT matchesTypeSubtype(const CSelector &sel, TBonusType type, TBonusSubtype subtype); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | extern DLL_EXPORT const std::map<std::string, int> bonusNameMap; | ||||||
| @@ -737,9 +737,9 @@ DLL_EXPORT void HeroLevelUp::applyGs( CGameState *gs ) | |||||||
| 						break; | 						break; | ||||||
| 						case 2: | 						case 2: | ||||||
| 							it->val = (level * (*creatures)[it->additionalInfo]->defence)/creLevel /20; | 							it->val = (level * (*creatures)[it->additionalInfo]->defence)/creLevel /20; | ||||||
| 						break; | 							break; | ||||||
| 					} | 					} | ||||||
| 				break; | 					break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ | |||||||
| template<typename Serializer> DLL_EXPORT | template<typename Serializer> DLL_EXPORT | ||||||
| void registerTypes1(Serializer &s) | void registerTypes1(Serializer &s) | ||||||
| { | { | ||||||
|  | 	//map objects | ||||||
| 	s.template registerType<CGHeroPlaceholder>(); | 	s.template registerType<CGHeroPlaceholder>(); | ||||||
| 	s.template registerType<CGHeroInstance>(); | 	s.template registerType<CGHeroInstance>(); | ||||||
| 	s.template registerType<CGTownInstance>(); | 	s.template registerType<CGTownInstance>(); | ||||||
| @@ -64,6 +65,9 @@ void registerTypes1(Serializer &s) | |||||||
| 	s.template registerType<CGLighthouse>(); | 	s.template registerType<CGLighthouse>(); | ||||||
| 	s.template registerType<CGMarket>(); | 	s.template registerType<CGMarket>(); | ||||||
| 	s.template registerType<CGBlackMarket>(); | 	s.template registerType<CGBlackMarket>(); | ||||||
|  | 	//end of objects | ||||||
|  | 	s.template registerType<ILimiter>(); | ||||||
|  | 	s.template registerType<CCreatureTypeLimiter>(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<typename Serializer> DLL_EXPORT  | template<typename Serializer> DLL_EXPORT  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user