瀏覽代碼

Implemented visit mode "limiter". Fixed h3m variable loading

Ivan Savenko 2 年之前
父節點
當前提交
a3b2354481

+ 2 - 0
lib/mapObjects/CGTownBuilding.cpp

@@ -396,6 +396,8 @@ bool CTownRewardableBuilding::wasVisitedBefore(const CGHeroInstance * contextHer
 			return contextHero->hasBonusFrom(BonusSource::TOWN_STRUCTURE, Bonus::getSid32(town->town->faction->getIndex(), bID));
 		case Rewardable::VISIT_HERO:
 			return visitors.find(contextHero->id) != visitors.end();
+		case Rewardable::VISIT_LIMITER:
+			return configuration.visitLimiter.heroAllowed(contextHero);
 		default:
 			return false;
 	}

+ 5 - 0
lib/mapObjects/CRewardableObject.cpp

@@ -188,6 +188,8 @@ bool CRewardableObject::wasVisitedBefore(const CGHeroInstance * contextHero) con
 			return contextHero->hasBonusFrom(BonusSource::OBJECT, ID);
 		case Rewardable::VISIT_HERO:
 			return contextHero->visitedObjects.count(ObjectInstanceID(id));
+		case Rewardable::VISIT_LIMITER:
+			return configuration.visitLimiter.heroAllowed(contextHero);
 		default:
 			return false;
 	}
@@ -200,6 +202,7 @@ bool CRewardableObject::wasVisited(PlayerColor player) const
 		case Rewardable::VISIT_UNLIMITED:
 		case Rewardable::VISIT_BONUS:
 		case Rewardable::VISIT_HERO:
+		case Rewardable::VISIT_LIMITER:
 			return false;
 		case Rewardable::VISIT_ONCE:
 		case Rewardable::VISIT_PLAYER:
@@ -217,6 +220,8 @@ bool CRewardableObject::wasVisited(const CGHeroInstance * h) const
 			return h->hasBonusFrom(BonusSource::OBJECT, ID);
 		case Rewardable::VISIT_HERO:
 			return h->visitedObjects.count(ObjectInstanceID(id));
+		case Rewardable::VISIT_LIMITER:
+			return configuration.visitLimiter.heroAllowed(h);
 		default:
 			return wasVisited(h->tempOwner);
 	}

+ 4 - 2
lib/mapping/MapFormatH3M.cpp

@@ -34,6 +34,7 @@
 #include "../mapObjects/CGCreature.h"
 #include "../mapObjects/MapObjects.h"
 #include "../mapObjects/ObjectTemplate.h"
+#include "../modding/ModScope.h"
 #include "../spells/CSpellHandler.h"
 
 #include <boost/crc.hpp>
@@ -1156,7 +1157,7 @@ CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position, std::share
 		{
 			auto defaultAllowed = VLC->skillh->getDefaultAllowed();
 
-			for(int skillID = 0; skillID < VLC->skillh->size(); ++skillID)
+			for(int skillID = features.skillsCount; skillID < defaultAllowed.size(); ++skillID)
 				if(defaultAllowed[skillID])
 					allowedAbilities.insert(SecondarySkill(skillID));
 		}
@@ -1170,7 +1171,8 @@ CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position, std::share
 			anyOfList.push_back(entry);
 		}
 		JsonNode variable;
-		variable.Vector() = anyOfList;
+		variable["anyOf"].Vector() = anyOfList;
+		variable.setMeta(ModScope::scopeGame()); // list may include skills from all mods
 
 		rewardable->configuration.presetVariable("secondarySkill", "gainedSkill", variable);
 	}

+ 1 - 1
lib/rewardable/Configuration.cpp

@@ -38,7 +38,7 @@ JsonNode Rewardable::Configuration::getPresetVariable(const std::string & catego
 {
 	std::string variableID = category + '@' + name;
 
-	if (variables.values.count(variableID))
+	if (variables.preset.count(variableID))
 		return variables.preset.at(variableID);
 	else
 		return JsonNode();

+ 5 - 1
lib/rewardable/Configuration.h

@@ -26,6 +26,7 @@ enum EVisitMode
 	VISIT_ONCE,      // only once, first to visit get all the rewards
 	VISIT_HERO,      // every hero can visit object once
 	VISIT_BONUS,     // can be visited by any hero that don't have bonus from this object
+	VISIT_LIMITER,   // can be visited by heroes that don't fulfill provided limiter
 	VISIT_PLAYER     // every player can visit object once
 };
 
@@ -46,7 +47,7 @@ enum class EEventType
 };
 
 const std::array<std::string, 3> SelectModeString{"selectFirst", "selectPlayer", "selectRandom"};
-const std::array<std::string, 5> VisitModeString{"unlimited", "once", "hero", "bonus", "player"};
+const std::array<std::string, 6> VisitModeString{"unlimited", "once", "hero", "bonus", "limiter", "player"};
 
 struct DLL_LINKAGE ResetInfo
 {
@@ -135,6 +136,9 @@ struct DLL_LINKAGE Configuration
 	/// List of variables shoread between all limiters and rewards
 	Rewardable::Variables variables;
 
+	/// Limiter that will be used to determine that object is visited. Only if visit mode is set to "limiter"
+	Rewardable::Limiter visitLimiter;
+
 	/// if true - player can refuse visiting an object (e.g. Tomb)
 	bool canRefuse = false;
 

+ 12 - 7
lib/rewardable/Info.cpp

@@ -108,6 +108,7 @@ void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRan
 	limiter.daysPassed = JsonRandom::loadValue(source["daysPassed"], rng, variables);
 	limiter.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng, variables);
 	limiter.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng, variables);
+	limiter.canLearnSkills = source["canLearnSkills"].Bool();
 
 	limiter.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, variables);
 	limiter.manaPoints = JsonRandom::loadValue(source["manaPoints"], rng, variables);
@@ -185,31 +186,32 @@ void Rewardable::Info::configureVariables(Rewardable::Configuration & object, CR
 		for(const auto & entry : category.second.Struct())
 		{
 			JsonNode preset = object.getPresetVariable(category.first, entry.first);
+			const JsonNode & input = preset.isNull() ? entry.second : preset;
 			int32_t value = -1;
 
 			if (category.first == "number")
-				value = JsonRandom::loadValue(entry.second, rng, object.variables.values);
+				value = JsonRandom::loadValue(input, rng, object.variables.values);
 
 			if (category.first == "artifact")
-				value = JsonRandom::loadArtifact(entry.second, rng, object.variables.values).getNum();
+				value = JsonRandom::loadArtifact(input, rng, object.variables.values).getNum();
 
 			if (category.first == "spell")
-				value = JsonRandom::loadSpell(entry.second, rng, object.variables.values).getNum();
+				value = JsonRandom::loadSpell(input, rng, object.variables.values).getNum();
 
 			// TODO
 			//	if (category.first == "creature")
-			//		value = JsonRandom::loadCreature(entry.second, rng, object.variables.values).type->getId();
+			//		value = JsonRandom::loadCreature(input, rng, object.variables.values).type->getId();
 
 			// TODO
 			//	if (category.first == "resource")
-			//		value = JsonRandom::loadResource(entry.second, rng, object.variables.values).getNum();
+			//		value = JsonRandom::loadResource(input, rng, object.variables.values).getNum();
 
 			// TODO
 			//	if (category.first == "primarySkill")
-			//		value = JsonRandom::loadCreature(entry.second, rng, object.variables.values).getNum();
+			//		value = JsonRandom::loadCreature(input, rng, object.variables.values).getNum();
 
 			if (category.first == "secondarySkill")
-				value = JsonRandom::loadSecondary(entry.second, rng, object.variables.values).getNum();
+				value = JsonRandom::loadSecondary(input, rng, object.variables.values).getNum();
 
 			object.initVariable(category.first, entry.first, value);
 		}
@@ -328,6 +330,9 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRand
 			break;
 		}
 	}
+
+	configureLimiter(object, rng, object.visitLimiter, parameters["visitLimiter"]);
+
 }
 
 bool Rewardable::Info::givesResources() const

+ 3 - 0
lib/rewardable/Limiter.cpp

@@ -101,6 +101,9 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 	if(manaPoints > hero->mana)
 		return false;
 
+	if (canLearnSkills && !hero->canLearnSkill())
+		return false;
+
 	if(manaPercentage > 100 * hero->mana / hero->manaLimit())
 		return false;
 

+ 3 - 0
lib/rewardable/Limiter.h

@@ -44,6 +44,9 @@ struct DLL_LINKAGE Limiter final
 	/// percentage of mana points that hero needs to have
 	si32 manaPercentage;
 
+	/// Number of free secondary slots that hero needs to have
+	bool canLearnSkills;
+
 	/// resources player needs to have in order to trigger reward
 	TResources resources;
 

+ 2 - 2
scripting/lua/api/netpacks/SetResources.cpp

@@ -102,7 +102,7 @@ int SetResourcesProxy::getAmount(lua_State * L)
 	if(!S.tryGet(1, object))
 		return S.retVoid();
 
-	auto type = EGameResID::INVALID;
+	auto type = EGameResID::NONE;
 
 	if(!S.tryGet(2, type))
 		return S.retVoid();
@@ -122,7 +122,7 @@ int SetResourcesProxy::setAmount(lua_State * L)
 	if(!S.tryGet(1, object))
 		return S.retVoid();
 
-	auto type = EGameResID::INVALID;
+	auto type = EGameResID::NONE;
 
 	if(!S.tryGet(2, type))
 		return S.retVoid();