mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Exposed more of existing limiters for modders (#449)
* Exposed alignment, faction and terrain limiters * Limiters toString() use now boost:format
This commit is contained in:
		
				
					committed by
					
						 ArseniyShestakov
						ArseniyShestakov
					
				
			
			
				
	
			
			
			
						parent
						
							ad2c429d8f
						
					
				
				
					commit
					d9d01f0b68
				
			
							
								
								
									
										3
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -69,3 +69,6 @@ Piotr Wójcik aka Chocimier, <chocimier@tlen.pl> | ||||
|  | ||||
| Henning Koehler, <henning.koehler.nz@gmail.com> | ||||
|    * skill modding, bonus updaters | ||||
|  | ||||
| Andrzej Żak aka godric3 | ||||
|    * minor bug fixes and modding features | ||||
|   | ||||
| @@ -34,6 +34,7 @@ MODS: | ||||
| * Map object sounds can now be configured via json | ||||
| * Added bonus updaters for hero specialties | ||||
| * Added allOf, anyOf and noneOf qualifiers for bonus limiters | ||||
| * Added bonus limiters: alignment, faction and terrain | ||||
|  | ||||
| SOUND: | ||||
| * Fixed many mising or wrong pickup and visit sounds for map objects | ||||
|   | ||||
| @@ -282,6 +282,16 @@ bool CStack::canBeHealed() const | ||||
| 		   && !hasBonusOfType(Bonus::SIEGE_WEAPON); | ||||
| } | ||||
|  | ||||
| bool CStack::isOnNativeTerrain() const | ||||
| { | ||||
| 	return type->isItNativeTerrain(battle->getTerrainType()); | ||||
| } | ||||
|  | ||||
| bool CStack::isOnTerrain(int terrain) const | ||||
| { | ||||
| 	return battle->getTerrainType() == terrain; | ||||
| } | ||||
|  | ||||
| const CCreature * CStack::unitType() const | ||||
| { | ||||
| 	return type; | ||||
|   | ||||
| @@ -47,6 +47,8 @@ public: | ||||
| 	std::string getName() const; //plural or singular | ||||
|  | ||||
| 	bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines | ||||
| 	bool isOnNativeTerrain() const; | ||||
| 	bool isOnTerrain(int terrain) const; | ||||
|  | ||||
| 	ui32 level() const; | ||||
| 	si32 magicResistance() const override; //include aura of resistance | ||||
|   | ||||
| @@ -16,11 +16,13 @@ | ||||
| #include "CCreatureHandler.h" | ||||
| #include "CCreatureSet.h" | ||||
| #include "CHeroHandler.h" | ||||
| #include "CTownHandler.h" | ||||
| #include "CGeneralTextHandler.h" | ||||
| #include "CSkillHandler.h" | ||||
| #include "CStack.h" | ||||
| #include "CArtHandler.h" | ||||
| #include "StringConstants.h" | ||||
| #include "battle/BattleInfo.h" | ||||
|  | ||||
| #define FOREACH_PARENT(pname) 	TNodes lparents; getParents(lparents); for(CBonusSystemNode *pname : lparents) | ||||
| #define FOREACH_CPARENT(pname) 	TCNodes lparents; getParents(lparents); for(const CBonusSystemNode *pname : lparents) | ||||
| @@ -68,7 +70,8 @@ const std::map<std::string, TLimiterPtr> bonusLimiterMap = | ||||
| { | ||||
| 	{"SHOOTER_ONLY", std::make_shared<HasAnotherBonusLimiter>(Bonus::SHOOTER)}, | ||||
| 	{"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)}, | ||||
| 	{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)} | ||||
| 	{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)}, | ||||
| 	{"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()} | ||||
| }; | ||||
|  | ||||
| const std::map<std::string, TPropagatorPtr> bonusPropagatorMap = | ||||
| @@ -1623,11 +1626,9 @@ void CCreatureTypeLimiter::setCreature (CreatureID id) | ||||
|  | ||||
| std::string CCreatureTypeLimiter::toString() const | ||||
| { | ||||
| 	char buf[100]; | ||||
| 	sprintf(buf, "CCreatureTypeLimiter(creature=%s, includeUpgrades=%s)", | ||||
| 		creature->identifier.c_str(), | ||||
| 		(includeUpgrades ? "true" : "false")); | ||||
| 	return std::string(buf); | ||||
| 	boost::format fmt("CCreatureTypeLimiter(creature=%s, includeUpgrades=%s)"); | ||||
| 	fmt % creature->identifier % (includeUpgrades ? "true" : "false"); | ||||
| 	return fmt.str(); | ||||
| } | ||||
|  | ||||
| JsonNode CCreatureTypeLimiter::toJsonNode() const | ||||
| @@ -1671,15 +1672,19 @@ int HasAnotherBonusLimiter::limit(const BonusLimitationContext &context) const | ||||
|  | ||||
| std::string HasAnotherBonusLimiter::toString() const | ||||
| { | ||||
| 	char buf[100]; | ||||
|  | ||||
| 	std::string typeName = vstd::findKey(bonusNameMap, type); | ||||
| 	if(isSubtypeRelevant) | ||||
| 		sprintf(buf, "HasAnotherBonusLimiter(type=%s, subtype=%d)",	typeName.c_str(), subtype); | ||||
| 	{ | ||||
| 		boost::format fmt("HasAnotherBonusLimiter(type=%s, subtype=%d)"); | ||||
| 		fmt % typeName % subtype; | ||||
| 		return fmt.str(); | ||||
| 	} | ||||
| 	else | ||||
| 		sprintf(buf, "HasAnotherBonusLimiter(type=%s)",	typeName.c_str()); | ||||
|  | ||||
| 	return std::string(buf); | ||||
| 	{ | ||||
| 		boost::format fmt("HasAnotherBonusLimiter(type=%s)"); | ||||
| 		fmt % typeName; | ||||
| 		return fmt.str(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| JsonNode HasAnotherBonusLimiter::toJsonNode() const | ||||
| @@ -1721,24 +1726,48 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest) | ||||
| 	return nodeType == dest->getNodeType(); | ||||
| } | ||||
|  | ||||
| CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter(int TerrainType) | ||||
| CreatureTerrainLimiter::CreatureTerrainLimiter(int TerrainType) | ||||
| 	: terrainType(TerrainType) | ||||
| { | ||||
| } | ||||
|  | ||||
| CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter() | ||||
| CreatureTerrainLimiter::CreatureTerrainLimiter() | ||||
| 	: terrainType(-1) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| int CreatureNativeTerrainLimiter::limit(const BonusLimitationContext &context) const | ||||
| int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const | ||||
| { | ||||
| 	const CCreature *c = retrieveCreature(&context.node); | ||||
| 	return !c || !c->isItNativeTerrain(terrainType); //drop bonus for non-creatures or non-native residents | ||||
| 	const CStack *stack = retrieveStackBattle(&context.node); | ||||
| 	if(stack) | ||||
| 	{ | ||||
| 		if(terrainType == -1)//terrainType not specified = native | ||||
| 			return !stack->isOnNativeTerrain(); | ||||
| 		return !stack->isOnTerrain(terrainType); | ||||
| 	} | ||||
| 	return true; | ||||
| 	//TODO neutral creatues | ||||
| } | ||||
|  | ||||
| std::string CreatureTerrainLimiter::toString() const | ||||
| { | ||||
| 	boost::format fmt("CreatureTerrainLimiter(terrainType=%s)"); | ||||
| 	fmt % (terrainType >= 0 ? GameConstants::TERRAIN_NAMES[terrainType] : "native"); | ||||
| 	return fmt.str(); | ||||
| } | ||||
|  | ||||
| JsonNode CreatureTerrainLimiter::toJsonNode() const | ||||
| { | ||||
| 	JsonNode root(JsonNode::JsonType::DATA_STRUCT); | ||||
|  | ||||
| 	root["type"].String() = "CREATURE_TERRAIN_LIMITER"; | ||||
| 	if(terrainType >= 0) | ||||
| 		root["parameters"].Vector().push_back(JsonUtils::stringNode(GameConstants::TERRAIN_NAMES[terrainType])); | ||||
|  | ||||
| 	return root; | ||||
| } | ||||
|  | ||||
| CreatureFactionLimiter::CreatureFactionLimiter(int Faction) | ||||
| 	: faction(Faction) | ||||
| { | ||||
| @@ -1755,6 +1784,23 @@ int CreatureFactionLimiter::limit(const BonusLimitationContext &context) const | ||||
| 	return !c || c->faction != faction; //drop bonus for non-creatures or non-native residents | ||||
| } | ||||
|  | ||||
| std::string CreatureFactionLimiter::toString() const | ||||
| { | ||||
| 	boost::format fmt("CreatureFactionLimiter(faction=%s)"); | ||||
| 	fmt %  VLC->townh->factions[faction]->identifier; | ||||
| 	return fmt.str(); | ||||
| } | ||||
|  | ||||
| JsonNode CreatureFactionLimiter::toJsonNode() const | ||||
| { | ||||
| 	JsonNode root(JsonNode::JsonType::DATA_STRUCT); | ||||
|  | ||||
| 	root["type"].String() = "CREATURE_FACTION_LIMITER"; | ||||
| 	root["parameters"].Vector().push_back(JsonUtils::stringNode(VLC->townh->factions[faction]->identifier)); | ||||
|  | ||||
| 	return root; | ||||
| } | ||||
|  | ||||
| CreatureAlignmentLimiter::CreatureAlignmentLimiter() | ||||
| 	: alignment(-1) | ||||
| { | ||||
| @@ -1784,6 +1830,23 @@ int CreatureAlignmentLimiter::limit(const BonusLimitationContext &context) const | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::string CreatureAlignmentLimiter::toString() const | ||||
| { | ||||
| 	boost::format fmt("CreatureAlignmentLimiter(alignment=%s)"); | ||||
| 	fmt % EAlignment::names[alignment]; | ||||
| 	return fmt.str(); | ||||
| } | ||||
|  | ||||
| JsonNode CreatureAlignmentLimiter::toJsonNode() const | ||||
| { | ||||
| 	JsonNode root(JsonNode::JsonType::DATA_STRUCT); | ||||
|  | ||||
| 	root["type"].String() = "CREATURE_ALIGNMENT_LIMITER"; | ||||
| 	root["parameters"].Vector().push_back(JsonUtils::stringNode(EAlignment::names[alignment])); | ||||
|  | ||||
| 	return root; | ||||
| } | ||||
|  | ||||
| RankRangeLimiter::RankRangeLimiter(ui8 Min, ui8 Max) | ||||
| 	:minRank(Min), maxRank(Max) | ||||
| { | ||||
|   | ||||
| @@ -965,14 +965,16 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CreatureNativeTerrainLimiter : public ILimiter //applies only to creatures that are on their native terrain | ||||
| class DLL_LINKAGE CreatureTerrainLimiter : public ILimiter //applies only to creatures that are on specified terrain, default native terrain | ||||
| { | ||||
| public: | ||||
| 	int terrainType; | ||||
| 	CreatureNativeTerrainLimiter(); | ||||
| 	CreatureNativeTerrainLimiter(int TerrainType); | ||||
| 	CreatureTerrainLimiter(); | ||||
| 	CreatureTerrainLimiter(int TerrainType); | ||||
|  | ||||
| 	int limit(const BonusLimitationContext &context) const override; | ||||
| 	virtual std::string toString() const override; | ||||
| 	virtual JsonNode toJsonNode() const override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| @@ -989,6 +991,8 @@ public: | ||||
| 	CreatureFactionLimiter(int TerrainType); | ||||
|  | ||||
| 	int limit(const BonusLimitationContext &context) const override; | ||||
| 	virtual std::string toString() const override; | ||||
| 	virtual JsonNode toJsonNode() const override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| @@ -1005,6 +1009,8 @@ public: | ||||
| 	CreatureAlignmentLimiter(si8 Alignment); | ||||
|  | ||||
| 	int limit(const BonusLimitationContext &context) const override; | ||||
| 	virtual std::string toString() const override; | ||||
| 	virtual JsonNode toJsonNode() const override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "CModHandler.h" | ||||
| #include "CGeneralTextHandler.h" | ||||
| #include "JsonDetail.h" | ||||
| #include "StringConstants.h" | ||||
|  | ||||
| using namespace JsonDetail; | ||||
|  | ||||
| @@ -645,6 +646,35 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter) | ||||
| 					return bonusLimiter; | ||||
| 				} | ||||
| 			} | ||||
| 			else if(limiterType == "CREATURE_ALIGNMENT_LIMITER") | ||||
| 			{ | ||||
| 				int alignment = vstd::find_pos(EAlignment::names, parameters[0].String()); | ||||
| 				if(alignment == -1) | ||||
| 					logMod->error("Error: invalid alignment %s.", parameters[0].String()); | ||||
| 				else | ||||
| 					return std::make_shared<CreatureAlignmentLimiter>(alignment); | ||||
| 			} | ||||
| 			else if(limiterType == "CREATURE_FACTION_LIMITER") | ||||
| 			{ | ||||
| 				std::shared_ptr<CreatureFactionLimiter> factionLimiter = std::make_shared<CreatureFactionLimiter>(); | ||||
| 				VLC->modh->identifiers.requestIdentifier("faction", parameters[0], [=](si32 faction) | ||||
| 				{ | ||||
| 					factionLimiter->faction = faction; | ||||
| 				}); | ||||
| 				return factionLimiter; | ||||
| 			} | ||||
| 			else if(limiterType == "CREATURE_TERRAIN_LIMITER") | ||||
| 			{ | ||||
| 				std::shared_ptr<CreatureTerrainLimiter> terrainLimiter = std::make_shared<CreatureTerrainLimiter>(); | ||||
| 				if(parameters.size()) | ||||
| 				{ | ||||
| 					VLC->modh->identifiers.requestIdentifier("terrain", parameters[0], [=](si32 terrain) | ||||
| 					{ | ||||
| 						terrainLimiter->terrainType = terrain; | ||||
| 					}); | ||||
| 				} | ||||
| 				return terrainLimiter; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				logMod->error("Error: invalid customizable limiter type %s.", limiterType); | ||||
|   | ||||
| @@ -525,7 +525,7 @@ BattleInfo * BattleInfo::setupBattle(int3 tile, ETerrainType terrain, BFieldType | ||||
| 	//overlay premies given | ||||
|  | ||||
| 	//native terrain bonuses | ||||
| 	auto nativeTerrain = std::make_shared<CreatureNativeTerrainLimiter>(curB->terrainType); | ||||
| 	auto nativeTerrain = std::make_shared<CreatureTerrainLimiter>(); | ||||
|  | ||||
| 	curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::STACKS_SPEED, Bonus::TERRAIN_NATIVE, 1, 0, 0)->addLimiter(nativeTerrain)); | ||||
| 	curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::PRIMARY_SKILL, Bonus::TERRAIN_NATIVE, 1, 0, PrimarySkill::ATTACK)->addLimiter(nativeTerrain)); | ||||
|   | ||||
| @@ -185,7 +185,7 @@ void registerTypesMapObjects2(Serializer &s) | ||||
| 	s.template registerType<ILimiter, AllOfLimiter>(); | ||||
| 	s.template registerType<ILimiter, CCreatureTypeLimiter>(); | ||||
| 	s.template registerType<ILimiter, HasAnotherBonusLimiter>(); | ||||
| 	s.template registerType<ILimiter, CreatureNativeTerrainLimiter>(); | ||||
| 	s.template registerType<ILimiter, CreatureTerrainLimiter>(); | ||||
| 	s.template registerType<ILimiter, CreatureFactionLimiter>(); | ||||
| 	s.template registerType<ILimiter, CreatureAlignmentLimiter>(); | ||||
| 	s.template registerType<ILimiter, RankRangeLimiter>(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user