Browse Source

Additional properties for limiter

nordsoft 2 năm trước cách đây
mục cha
commit
6a7b23c007

+ 32 - 4
docs/modders/Map_Objects/Rewardable.md

@@ -72,7 +72,7 @@ Rewardable object is defined similarly to other objects, with key difference bei
       // additional list of conditions. Limiter will be valid if any of these conditions are true
       "anyOf" : [
         {
-          // See "Configurable Properties" section for additiona parameters
+          // See "Configurable Properties" section for additional parameters
           <additional properties>
         }
       ]
@@ -80,12 +80,12 @@ Rewardable object is defined similarly to other objects, with key difference bei
       // additional list of conditions. Limiter will be valid only if none of these conditions are true
       "noneOf" : [
         {
-          // See "Configurable Properties" section for additiona parameters
+          // See "Configurable Properties" section for additional parameters
           <additional properties>
         }
       ]
 
-      // See "Configurable Properties" section for additiona parameters
+      // See "Configurable Properties" section for additional parameters
       <additional properties>
     }
     
@@ -95,7 +95,7 @@ Rewardable object is defined similarly to other objects, with key difference bei
     // object will be disappeared after taking reward is set to true
     "removeObject": false
 
-    // See "Configurable Properties" section for additiona parameters
+    // See "Configurable Properties" section for additional parameters
     <additional properties>
   }
 ],
@@ -450,4 +450,32 @@ Keep in mind, that all randomization is performed on map load and on object rese
     "spell" : "townPortal",
     "schoolLevel": 3
 }
+```
+
+### Player color
+- Can be used as limiter
+- Can NOT be used as reward
+- Only players with specific color can pass the limiter
+- If not specified or empty all colors may pass the limiter
+
+```jsonc
+"colors" : [ "red", "blue", "tan", "green", "orange", "purple", "teal", "pink" ]
+```
+
+### Hero types
+- Can be used as limiter
+- Can NOT be used as reward
+- Only specific heroes can pass the limiter
+
+```jsonc
+"heroes" : [ "orrin" ]
+```
+
+### Hero classes
+- Can be used as limiter
+- Can NOT be used as reward
+- Only heroes belonging to specific classes can pass the limiter
+
+```jsonc
+"heroClasses" : [ "battlemage" ]
 ```

+ 41 - 0
lib/JsonRandom.cpp

@@ -22,6 +22,7 @@
 #include "CCreatureSet.h"
 #include "spells/CSpellHandler.h"
 #include "CSkillHandler.h"
+#include "CHeroHandler.h"
 #include "IGameCallback.h"
 #include "mapObjects/IObjectInterface.h"
 #include "modding/IdentifierStorage.h"
@@ -282,6 +283,46 @@ namespace JsonRandom
 		return ret;
 	}
 
+	std::vector<PlayerColor> loadColors(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::vector<PlayerColor> ret;
+		std::set<std::string> def;
+		
+		for(auto & color : GameConstants::PLAYER_COLOR_NAMES)
+			def.insert(color);
+		
+		for(auto & entry : value.Vector())
+		{
+			auto key = loadKey(entry, rng, def);
+			auto pos = vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, key);
+			if(pos < 0)
+				logMod->warn("Unable to determine player color %s", key);
+			else
+				ret.emplace_back(pos);
+		}
+		return ret;
+	}
+
+	std::vector<HeroTypeID> loadHeroes(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::vector<HeroTypeID> ret;
+		for(auto & entry : value.Vector())
+		{
+			ret.push_back(VLC->heroTypes()->getByIndex(VLC->identifiers()->getIdentifier("hero", entry.String()).value())->getId());
+		}
+		return ret;
+	}
+
+	std::vector<HeroClassID> loadHeroClasses(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::vector<HeroClassID> ret;
+		for(auto & entry : value.Vector())
+		{
+			ret.push_back(VLC->heroClasses()->getByIndex(VLC->identifiers()->getIdentifier("heroClass", entry.String()).value())->getId());
+		}
+		return ret;
+	}
+
 	CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng)
 	{
 		CStackBasicDescriptor stack;

+ 4 - 0
lib/JsonRandom.h

@@ -48,6 +48,10 @@ namespace JsonRandom
 	DLL_LINKAGE std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng);
 	DLL_LINKAGE std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value);
 
+	DLL_LINKAGE std::vector<PlayerColor> loadColors(const JsonNode & value, CRandomGenerator & rng);
+	DLL_LINKAGE std::vector<HeroTypeID> loadHeroes(const JsonNode & value, CRandomGenerator & rng);
+	DLL_LINKAGE std::vector<HeroClassID> loadHeroClasses(const JsonNode & value, CRandomGenerator & rng);
+
 	DLL_LINKAGE std::vector<Bonus> loadBonuses(const JsonNode & value);
 	//DLL_LINKAGE std::vector<Component> loadComponents(const JsonNode & value);
 }

+ 4 - 0
lib/rewardable/Info.cpp

@@ -122,6 +122,10 @@ void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRan
 	limiter.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng);
 	limiter.spells  = JsonRandom::loadSpells(source["spells"], rng, spells);
 	limiter.creatures = JsonRandom::loadCreatures(source["creatures"], rng);
+	
+	limiter.players = JsonRandom::loadColors(source["colors"], rng);
+	limiter.heroes = JsonRandom::loadHeroes(source["heroes"], rng);
+	limiter.heroClasses = JsonRandom::loadHeroClasses(source["heroClasses"], rng);
 
 	limiter.allOf  = configureSublimiters(object, rng, source["allOf"] );
 	limiter.anyOf  = configureSublimiters(object, rng, source["anyOf"] );

+ 14 - 0
lib/rewardable/Limiter.cpp

@@ -16,6 +16,7 @@
 #include "../mapObjects/CGHeroInstance.h"
 #include "../serializer/JsonSerializeFormat.h"
 #include "../constants/StringConstants.h"
+#include "../CHeroHandler.h"
 #include "../CSkillHandler.h"
 #include "../ArtifactUtils.h"
 
@@ -112,6 +113,16 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 			return false;
 	}
 	
+	if(!players.empty() && !vstd::contains(players, hero->getOwner()))
+		return false;
+	
+	if(!heroes.empty() && !vstd::contains(heroes, hero->type->getId()))
+		return false;
+	
+	if(!heroClasses.empty() && !vstd::contains(heroClasses, hero->type->heroClass->getId()))
+		return false;
+		
+	
 	for(const auto & sublimiter : noneOf)
 	{
 		if (sublimiter->heroAllowed(hero))
@@ -143,6 +154,9 @@ void Rewardable::Limiter::serializeJson(JsonSerializeFormat & handler)
 	handler.serializeInt("manaPercentage", manaPercentage);
 	handler.serializeInt("heroExperience", heroExperience);
 	handler.serializeInt("heroLevel", heroLevel);
+	handler.serializeIdArray("hero", heroes);
+	handler.serializeIdArray("heroClass", heroClasses);
+	handler.serializeIdArray("color", players);
 	handler.serializeInt("manaPoints", manaPoints);
 	handler.serializeIdArray("artifacts", artifacts);
 	handler.enterArray("creatures").serializeStruct(creatures);

+ 10 - 0
lib/rewardable/Limiter.h

@@ -60,6 +60,13 @@ struct DLL_LINKAGE Limiter
 
 	/// creatures that hero needs to have
 	std::vector<CStackBasicDescriptor> creatures;
+	
+	/// only heroes/hero classes from list could pass limiter
+	std::vector<HeroTypeID> heroes;
+	std::vector<HeroClassID> heroClasses;
+	
+	/// only player colors can pass limiter
+	std::vector<PlayerColor> players;
 
 	/// sub-limiters, all must pass for this limiter to pass
 	LimitersList allOf;
@@ -91,6 +98,9 @@ struct DLL_LINKAGE Limiter
 		h & allOf;
 		h & anyOf;
 		h & noneOf;
+		h & heroes;
+		h & heroClasses;
+		h & players;
 	}
 	
 	void serializeJson(JsonSerializeFormat & handler);