mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Tweaked CBonusTypeHandler
This commit is contained in:
		| @@ -8,6 +8,9 @@ | ||||
|  * | ||||
|  */ | ||||
| #include "StdInc.h" | ||||
|  | ||||
| #define INSTANTIATE_CBonusTypeHandler_HERE | ||||
|  | ||||
| #include "CBonusTypeHandler.h" | ||||
|  | ||||
| #include "JsonNode.h" | ||||
| @@ -17,31 +20,32 @@ | ||||
| #include "CCreatureHandler.h" | ||||
| #include "spells/CSpellHandler.h" | ||||
|  | ||||
| template class std::vector<CBonusType>; | ||||
|  | ||||
| ///MacroString | ||||
|  | ||||
| MacroString::MacroString(const std::string &format) | ||||
| MacroString::MacroString(const std::string & format) | ||||
| { | ||||
| 	static const std::string MACRO_START = "${"; | ||||
| 	static const std::string MACRO_END = "}"; | ||||
| 	static const size_t MACRO_START_L = 2; | ||||
| 	static const size_t MACRO_END_L = 1; | ||||
| 	 | ||||
| 	size_t end_pos = 0;	 | ||||
|  | ||||
| 	size_t end_pos = 0; | ||||
| 	size_t start_pos = std::string::npos; | ||||
| 	 | ||||
| 	do | ||||
| 	{ | ||||
| 		start_pos = format.find(MACRO_START, end_pos); | ||||
| 		 | ||||
| 		if (!(start_pos == std::string::npos)) | ||||
|  | ||||
| 		if(!(start_pos == std::string::npos)) | ||||
| 		{ | ||||
| 			//chunk before macro | ||||
| 			items.push_back(Item(Item::STRING,format.substr(end_pos, start_pos-end_pos))); | ||||
| 			 | ||||
| 			items.push_back(Item(Item::STRING, format.substr(end_pos, start_pos - end_pos))); | ||||
|  | ||||
| 			start_pos += MACRO_START_L; | ||||
| 			end_pos = format.find(MACRO_END, start_pos); | ||||
| 			 | ||||
| 			if (end_pos == std::string::npos) | ||||
|  | ||||
| 			if(end_pos == std::string::npos) | ||||
| 			{ | ||||
| 				logBonus->warnStream() << "Format error in: " << format; | ||||
| 				end_pos = start_pos; | ||||
| @@ -49,36 +53,36 @@ MacroString::MacroString(const std::string &format) | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				items.push_back(Item(Item::MACRO,format.substr(start_pos,end_pos-start_pos))); | ||||
| 				items.push_back(Item(Item::MACRO, format.substr(start_pos, end_pos - start_pos))); | ||||
| 				end_pos += MACRO_END_L; | ||||
| 			} | ||||
| 		}		 | ||||
| 		} | ||||
| 	} | ||||
| 	while (start_pos != std::string::npos); | ||||
| 	 | ||||
| 	while(start_pos != std::string::npos); | ||||
|  | ||||
| 	//no more macros | ||||
| 	items.push_back(Item(Item::STRING,format.substr(end_pos))); | ||||
| 	items.push_back(Item(Item::STRING, format.substr(end_pos))); | ||||
| } | ||||
|  | ||||
| std::string MacroString::build(const GetValue& getValue) const | ||||
| std::string MacroString::build(const GetValue & getValue) const | ||||
| { | ||||
| 	std::string result; | ||||
| 	 | ||||
| 	for(const Item &i : items) | ||||
|  | ||||
| 	for(const Item & i : items) | ||||
| 	{ | ||||
| 		switch (i.type) | ||||
| 		switch(i.type) | ||||
| 		{ | ||||
| 			case Item::MACRO: | ||||
| 			{ | ||||
| 				result += getValue(i.value); | ||||
| 				break; | ||||
| 			}			 | ||||
| 			case Item::STRING: | ||||
| 			{ | ||||
| 				result += i.value; | ||||
| 				break; | ||||
| 			}			 | ||||
| 		}		 | ||||
| 		case Item::MACRO: | ||||
| 		{ | ||||
| 			result += getValue(i.value); | ||||
| 			break; | ||||
| 		} | ||||
| 		case Item::STRING: | ||||
| 		{ | ||||
| 			result += i.value; | ||||
| 			break; | ||||
| 		} | ||||
| 		} | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
| @@ -88,12 +92,12 @@ std::string MacroString::build(const GetValue& getValue) const | ||||
| CBonusType::CBonusType() | ||||
| { | ||||
| 	hidden = true; | ||||
| 	icon = nameTemplate = descriptionTemplate = "";  | ||||
| 	icon = nameTemplate = descriptionTemplate = ""; | ||||
| } | ||||
|  | ||||
| CBonusType::~CBonusType() | ||||
| { | ||||
| 	 | ||||
|  | ||||
| } | ||||
|  | ||||
| void CBonusType::buildMacros() | ||||
| @@ -110,11 +114,11 @@ CBonusTypeHandler::CBonusTypeHandler() | ||||
| 	//register predefined bonus types | ||||
|  | ||||
| 	#define BONUS_NAME(x) \ | ||||
| 		do{\ | ||||
| 			bonusTypes.push_back(CBonusType());\ | ||||
| 		}while (0); | ||||
| 		 | ||||
| 	 | ||||
| 	do { \ | ||||
| 		bonusTypes.push_back(CBonusType()); \ | ||||
| 	} while(0); | ||||
|  | ||||
|  | ||||
| 	BONUS_LIST; | ||||
| 	#undef BONUS_NAME | ||||
|  | ||||
| @@ -126,190 +130,199 @@ CBonusTypeHandler::~CBonusTypeHandler() | ||||
| 	//dtor | ||||
| } | ||||
|  | ||||
| std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus>& bonus, const IBonusBearer *bearer, bool description) const | ||||
| {	 | ||||
| 	auto getValue = [=](const std::string &name) -> std::string | ||||
| std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonus, const IBonusBearer * bearer, bool description) const | ||||
| { | ||||
| 	auto getValue = [=](const std::string & name) -> std::string | ||||
| 	{ | ||||
| 		if (name == "val") | ||||
| 		if(name == "val") | ||||
| 		{ | ||||
| 			return boost::lexical_cast<std::string>(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))); | ||||
| 			 return boost::lexical_cast<std::string>(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))); | ||||
| 		} | ||||
| 		else if (name == "subtype.creature") | ||||
| 		else if(name == "subtype.creature") | ||||
| 		{ | ||||
| 			const CreatureID cre(bonus->subtype); | ||||
| 			return cre.toCreature()->namePl; | ||||
| 			 const CreatureID cre(bonus->subtype); | ||||
| 			 return cre.toCreature()->namePl; | ||||
| 		} | ||||
| 		else if (name == "subtype.spell") | ||||
| 		else if(name == "subtype.spell") | ||||
| 		{ | ||||
| 			const SpellID sp(bonus->subtype); | ||||
| 			return sp.toSpell()->name; | ||||
| 		}		 | ||||
| 		else if (name == "MR") | ||||
| 			 const SpellID sp(bonus->subtype); | ||||
| 			 return sp.toSpell()->name; | ||||
| 		} | ||||
| 		else if(name == "MR") | ||||
| 		{ | ||||
| 			 return boost::lexical_cast<std::string>(bearer->magicResistance()); | ||||
| 		}			 | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			logBonus->warnStream() << "Unknown macro in bonus config: " << name; | ||||
| 			return "[error]"; | ||||
| 			 logBonus->warnStream() << "Unknown macro in bonus config: " << name; | ||||
| 			 return "[error]"; | ||||
| 		} | ||||
| 	}; | ||||
| 	 | ||||
| 	const CBonusType& bt = bonusTypes[bonus->type];	 | ||||
|  | ||||
| 	const CBonusType & bt = bonusTypes[bonus->type]; | ||||
| 	if(bt.hidden) | ||||
| 		return ""; | ||||
| 	const MacroString& macro = description ? bt.description : bt.name; | ||||
| 	 | ||||
| 	return macro.build(getValue);	 | ||||
| 	const MacroString & macro = description ? bt.description : bt.name; | ||||
|  | ||||
| 	return macro.build(getValue); | ||||
| } | ||||
|  | ||||
| std::string CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus>& bonus) const | ||||
| std::string CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const | ||||
| { | ||||
| 	std::string fileName; | ||||
| 	bool fullPath = false; | ||||
|  | ||||
| 	switch (bonus->type) | ||||
| 	switch(bonus->type) | ||||
| 	{ | ||||
| 		case Bonus::SECONDARY_SKILL_PREMY: | ||||
| 			if (bonus->subtype == SecondarySkill::RESISTANCE) | ||||
| 			{ | ||||
| 				fileName = "E_DWARF.bmp"; | ||||
| 			} | ||||
| 			break; | ||||
| 		case Bonus::SPELL_IMMUNITY: | ||||
| 	case Bonus::SECONDARY_SKILL_PREMY: | ||||
| 		if(bonus->subtype == SecondarySkill::RESISTANCE) | ||||
| 		{ | ||||
| 			fullPath = true; | ||||
| 			const CSpell * sp = SpellID(bonus->subtype).toSpell(); | ||||
| 			fileName = sp->getIconImmune(); | ||||
| 			fileName = "E_DWARF.bmp"; | ||||
| 		} | ||||
| 		break; | ||||
| 	case Bonus::SPELL_IMMUNITY: | ||||
| 	{ | ||||
| 		fullPath = true; | ||||
| 		const CSpell * sp = SpellID(bonus->subtype).toSpell(); | ||||
| 		fileName = sp->getIconImmune(); | ||||
| 		break; | ||||
| 	} | ||||
| 	case Bonus::FIRE_IMMUNITY: | ||||
| 		switch(bonus->subtype) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			fileName = "E_SPFIRE.bmp"; | ||||
| 			break;//all | ||||
| 		case 1: | ||||
| 			fileName = "E_SPFIRE1.bmp"; | ||||
| 			break;//not positive | ||||
| 		case 2: | ||||
| 			fileName = "E_FIRE.bmp"; | ||||
| 			break;//direct damage | ||||
| 		} | ||||
| 		break; | ||||
| 	case Bonus::WATER_IMMUNITY: | ||||
| 		switch(bonus->subtype) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			fileName = "E_SPWATER.bmp"; | ||||
| 			break;//all | ||||
| 		case 1: | ||||
| 			fileName = "E_SPWATER1.bmp"; | ||||
| 			break;//not positive | ||||
| 		case 2: | ||||
| 			fileName = "E_SPCOLD.bmp"; | ||||
| 			break;//direct damage | ||||
| 		} | ||||
| 		break; | ||||
| 	case Bonus::AIR_IMMUNITY: | ||||
| 		switch(bonus->subtype) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			fileName = "E_SPAIR.bmp"; | ||||
| 			break;//all | ||||
| 		case 1: | ||||
| 			fileName = "E_SPAIR1.bmp"; | ||||
| 			break;//not positive | ||||
| 		case 2: | ||||
| 			fileName = "E_LIGHT.bmp"; | ||||
| 			break;//direct damage | ||||
| 		} | ||||
| 		break; | ||||
| 	case Bonus::EARTH_IMMUNITY: | ||||
| 		switch(bonus->subtype) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			fileName = "E_SPEATH.bmp"; | ||||
| 			break;//all | ||||
| 		case 1: | ||||
| 		case 2://no specific icon for direct damage immunity | ||||
| 			fileName = "E_SPEATH1.bmp"; | ||||
| 			break;//not positive | ||||
| 		} | ||||
| 		break; | ||||
| 	case Bonus::LEVEL_SPELL_IMMUNITY: | ||||
| 	{ | ||||
| 		if(vstd::iswithin(bonus->val, 1, 5)) | ||||
| 		{ | ||||
| 			fileName = "E_SPLVL" + boost::lexical_cast<std::string>(bonus->val) + ".bmp"; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 	case Bonus::GENERAL_DAMAGE_REDUCTION: | ||||
| 	{ | ||||
| 		switch(bonus->subtype) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			fileName = "DamageReductionMelee.bmp"; | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			fileName = "DamageReductionRanged.bmp"; | ||||
| 			break; | ||||
| 		} | ||||
| 		case Bonus::FIRE_IMMUNITY: | ||||
| 			switch (bonus->subtype) | ||||
| 			{ | ||||
| 				case 0: | ||||
| 					fileName =  "E_SPFIRE.bmp"; break; //all | ||||
| 				case 1: | ||||
| 					fileName =  "E_SPFIRE1.bmp"; break; //not positive | ||||
| 				case 2: | ||||
| 					fileName =  "E_FIRE.bmp"; break; //direct damage | ||||
| 			} | ||||
| 			break; | ||||
| 		case Bonus::WATER_IMMUNITY: | ||||
| 			switch (bonus->subtype) | ||||
| 			{ | ||||
| 				case 0: | ||||
| 					fileName =  "E_SPWATER.bmp"; break; //all | ||||
| 				case 1: | ||||
| 					fileName =  "E_SPWATER1.bmp"; break; //not positive | ||||
| 				case 2: | ||||
| 					fileName =  "E_SPCOLD.bmp"; break; //direct damage | ||||
| 			} | ||||
| 			break; | ||||
| 		case Bonus::AIR_IMMUNITY: | ||||
| 			switch (bonus->subtype) | ||||
| 			{ | ||||
| 				case 0: | ||||
| 					fileName =  "E_SPAIR.bmp"; break; //all | ||||
| 				case 1: | ||||
| 					fileName =  "E_SPAIR1.bmp"; break; //not positive | ||||
| 				case 2: | ||||
| 					fileName = "E_LIGHT.bmp"; break;//direct damage | ||||
| 			} | ||||
| 			break; | ||||
| 		case Bonus::EARTH_IMMUNITY: | ||||
| 			switch (bonus->subtype) | ||||
| 			{ | ||||
| 				case 0: | ||||
| 					fileName =  "E_SPEATH.bmp"; break; //all | ||||
| 				case 1: | ||||
| 				case 2: //no specific icon for direct damage immunity | ||||
| 					fileName =  "E_SPEATH1.bmp"; break; //not positive | ||||
| 			} | ||||
| 			break; | ||||
| 		case Bonus::LEVEL_SPELL_IMMUNITY: | ||||
| 		{ | ||||
| 			if (vstd::iswithin(bonus->val, 1 , 5)) | ||||
| 			{ | ||||
| 				fileName = "E_SPLVL" + boost::lexical_cast<std::string>(bonus->val) + ".bmp"; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		case Bonus::GENERAL_DAMAGE_REDUCTION: | ||||
| 		{ | ||||
| 			switch (bonus->subtype) | ||||
| 			{ | ||||
| 				case 0: | ||||
| 					fileName = "DamageReductionMelee.bmp"; break; | ||||
| 				case 1: | ||||
| 					fileName = "DamageReductionRanged.bmp"; break; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		 | ||||
| 		default:  | ||||
| 		{ | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 			const CBonusType& bt = bonusTypes[bonus->type]; | ||||
| 			 | ||||
| 	default: | ||||
| 		{ | ||||
| 			const CBonusType & bt = bonusTypes[bonus->type]; | ||||
| 			fileName = bt.icon; | ||||
| 			fullPath = true; | ||||
| 			break; | ||||
| 		}		 | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	if(!fileName.empty() && !fullPath) | ||||
| 		fileName = "zvs/Lib1.res/" + fileName; | ||||
| 	return fileName;	 | ||||
| 	return fileName; | ||||
| } | ||||
|  | ||||
|  | ||||
| void CBonusTypeHandler::load() | ||||
| { | ||||
| 	const JsonNode gameConf(ResourceID("config/gameConfig.json")); | ||||
| 	const JsonNode config(JsonUtils::assembleFromFiles(gameConf["bonuses"].convertTo<std::vector<std::string> >())); | ||||
| 	const JsonNode config(JsonUtils::assembleFromFiles(gameConf["bonuses"].convertTo<std::vector<std::string>>())); | ||||
| 	load(config); | ||||
| } | ||||
|  | ||||
| void CBonusTypeHandler::load(const JsonNode& config) | ||||
| void CBonusTypeHandler::load(const JsonNode & config) | ||||
| { | ||||
| 	for(auto & node : config.Struct()) | ||||
| 	{ | ||||
| 		auto it = bonusNameMap.find(node.first); | ||||
| 		 | ||||
|  | ||||
| 		if(it == bonusNameMap.end()) | ||||
| 		{ | ||||
| 			//TODO: new bonus | ||||
| //			CBonusType bt; | ||||
| //			loadItem(node.second, bt); | ||||
| //			 | ||||
| // | ||||
| //			auto new_id = bonusTypes.size(); | ||||
| //			 | ||||
| // | ||||
| //			bonusTypes.push_back(bt); | ||||
| 			 | ||||
|  | ||||
| 			logBonus->warnStream() << "Adding new bonuses not implemented (" << node.first << ")"; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			CBonusType& bt = bonusTypes[it->second]; | ||||
| 			 | ||||
| 			CBonusType & bt = bonusTypes[it->second]; | ||||
|  | ||||
| 			loadItem(node.second, bt); | ||||
| 			logBonus->traceStream() << "Loaded bonus type " << node.first; | ||||
| 		}	 | ||||
| 	}		 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBonusTypeHandler::loadItem(const JsonNode& source, CBonusType& dest) | ||||
| void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest) | ||||
| { | ||||
| 	dest.nameTemplate = source["name"].String(); | ||||
| 	dest.descriptionTemplate = source["description"].String(); | ||||
| 	dest.hidden = source["hidden"].Bool(); //Null -> false | ||||
| 	 | ||||
| 	const JsonNode& graphics = source["graphics"]; | ||||
| 	 | ||||
|  | ||||
| 	const JsonNode & graphics = source["graphics"]; | ||||
|  | ||||
| 	if(!graphics.isNull()) | ||||
| 	{ | ||||
| 		dest.icon = graphics["icon"].String(); | ||||
| 	}	 | ||||
| 	} | ||||
| 	dest.buildMacros(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -33,12 +33,13 @@ class MacroString | ||||
| 	}; | ||||
| 	std::vector<Item> items; | ||||
| public: | ||||
| 	typedef std::function <std::string(const std::string&)> GetValue; | ||||
| 	typedef std::function<std::string(const std::string &)> GetValue; | ||||
|  | ||||
| 	MacroString(){}; | ||||
| 	MacroString(const std::string &format); | ||||
| 	MacroString() = default; | ||||
| 	~MacroString() = default; | ||||
| 	explicit MacroString(const std::string & format); | ||||
|  | ||||
| 	std::string build(const GetValue& getValue) const; | ||||
| 	std::string build(const GetValue & getValue) const; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CBonusType | ||||
| @@ -47,8 +48,7 @@ public: | ||||
| 	CBonusType(); | ||||
| 	~CBonusType(); | ||||
|  | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	template <typename Handler> void serialize(Handler & h, const int version) | ||||
| 	{ | ||||
| 		h & icon; | ||||
| 		h & nameTemplate; | ||||
| @@ -58,7 +58,6 @@ public: | ||||
| 		if (!h.saving) | ||||
| 			buildMacros(); | ||||
| 	} | ||||
| protected: | ||||
|  | ||||
| private: | ||||
| 	void buildMacros(); | ||||
| @@ -71,27 +70,30 @@ private: | ||||
| 	bool hidden; | ||||
| }; | ||||
|  | ||||
|  | ||||
| class DLL_LINKAGE CBonusTypeHandler : public IBonusTypeHandler | ||||
| { | ||||
| public: | ||||
| 	CBonusTypeHandler(); | ||||
| 	virtual ~CBonusTypeHandler(); | ||||
|  | ||||
| 	std::string bonusToString(const std::shared_ptr<Bonus>& bonus, const IBonusBearer *bearer, bool description) const override; | ||||
| 	std::string bonusToGraphics(const std::shared_ptr<Bonus>& bonus) const override; | ||||
| 	std::string bonusToString(const std::shared_ptr<Bonus> & bonus, const IBonusBearer * bearer, bool description) const override; | ||||
| 	std::string bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const override; | ||||
|  | ||||
| 	void load(); | ||||
| 	void load(const JsonNode& config); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	template <typename Handler> void serialize(Handler & h, const int version) | ||||
| 	{ | ||||
| 		h & bonusTypes; | ||||
| 		//for now always use up to date configuration | ||||
| 		//once modded bonus type will be implemented, serialize only them | ||||
| 		std::vector<CBonusType> ignore; | ||||
| 		h & ignore; | ||||
| 	} | ||||
| private: | ||||
|  | ||||
| 	void loadItem(const JsonNode &source, CBonusType &dest); | ||||
| 	void load(); | ||||
| 	void load(const JsonNode & config); | ||||
| 	void loadItem(const JsonNode & source, CBonusType & dest); | ||||
|  | ||||
| 	std::vector<CBonusType> bonusTypes; //index = BonusTypeID | ||||
|  | ||||
| }; | ||||
|  | ||||
| #ifndef INSTANTIATE_CBonusTypeHandler_HERE | ||||
| extern template class std::vector<CBonusType>; | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user