Quellcode durchsuchen

Implemented basic loading from JSON

Ivan Savenko vor 11 Jahren
Ursprung
Commit
419a2797c8
5 geänderte Dateien mit 195 neuen und 6 gelöschten Zeilen
  1. 2 1
      lib/CDefObjInfoHandler.h
  2. 13 0
      lib/CModHandler.cpp
  3. 1 0
      lib/CModHandler.h
  4. 177 3
      lib/CObjectConstructor.cpp
  5. 2 2
      lib/CObjectConstructor.h

+ 2 - 1
lib/CDefObjInfoHandler.h

@@ -16,6 +16,7 @@
 class CBinaryReader;
 class CLegacyConfigParser;
 class JsonNode;
+class CRandomGenerator;
 
 class DLL_LINKAGE ObjectTemplate
 {
@@ -128,7 +129,7 @@ public:
 
 	virtual CGObjectInstance * create(ObjectTemplate tmpl) const = 0;
 
-	virtual void configureObject(CGObjectInstance * object) const = 0;
+	virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;
 
 	virtual const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const = 0;
 };

+ 13 - 0
lib/CModHandler.cpp

@@ -120,6 +120,19 @@ void CIdentifierStorage::tryRequestIdentifier(std::string type, const JsonNode &
 	requestIdentifier(ObjectCallback(name.meta, pair.first, type, pair.second, callback, true));
 }
 
+boost::optional<si32> CIdentifierStorage::getIdentifier(std::string scope, std::string type, std::string name, bool silent)
+{
+	auto pair = splitString(name, ':'); // remoteScope:name
+	auto idList = getPossibleIdentifiers(ObjectCallback(scope, pair.first, type, pair.second, std::function<void(si32)>(), silent));
+
+	if (idList.size() == 1)
+		return idList.front().id;
+	if (!silent)
+		logGlobal->errorStream() << "Failed to resolve identifier " << name << " from mod " << scope;
+
+	return boost::optional<si32>();
+}
+
 boost::optional<si32> CIdentifierStorage::getIdentifier(std::string type, const JsonNode & name, bool silent)
 {
 	auto pair = splitString(name.String(), ':'); // remoteScope:name

+ 1 - 0
lib/CModHandler.h

@@ -70,6 +70,7 @@ public:
 	void tryRequestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback);
 
 	/// get identifier immediately. If identifier is not know and not silent call will result in error message
+	boost::optional<si32> getIdentifier(std::string scope, std::string type, std::string name, bool silent = false);
 	boost::optional<si32> getIdentifier(std::string type, const JsonNode & name, bool silent = false);
 	boost::optional<si32> getIdentifier(const JsonNode & name, bool silent = false);
 

+ 177 - 3
lib/CObjectConstructor.cpp

@@ -1,6 +1,10 @@
 #include "StdInc.h"
 #include "CObjectConstructor.h"
 
+#include "CRandomGenerator.h"
+#include "StringConstants.h"
+#include "CCreatureHandler.h"
+
 /*
  * CObjectConstructor.cpp, part of VCMI engine
  *
@@ -11,54 +15,224 @@
  *
  */
 
+namespace {
+	si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0)
+	{
+		if (value.isNull())
+			return defaultValue;
+		if (value.getType() == JsonNode::DATA_FLOAT)
+			return value.Float();
+		si32 min = value["min"].Float();
+		si32 max = value["max"].Float();
+		return rng.getIntRange(min, max)();
+	}
+
+	TResources loadResources(const JsonNode & value, CRandomGenerator & rng)
+	{
+		TResources ret;
+		for (size_t i=0; i<GameConstants::RESOURCE_QUANTITY; i++)
+		{
+			ret[i] = loadValue(value[GameConstants::RESOURCE_NAMES[i]], rng);
+		}
+		return ret;
+	}
+
+	std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::vector<si32> ret;
+		for (auto & name : PrimarySkill::names)
+		{
+			ret.push_back(loadValue(value[name], rng));
+		}
+		return ret;
+	}
+
+	std::map<SecondarySkill, si32> loadSecondary(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::map<SecondarySkill, si32> ret;
+		for (auto & pair : value.Struct())
+		{
+			SecondarySkill id(VLC->modh->identifiers.getIdentifier(pair.second.meta, "skill", pair.first).get());
+			ret[id] = loadValue(pair.second, rng);
+		}
+		return ret;
+	}
+
+	std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::vector<ArtifactID> ret;
+		for (const JsonNode & entry : value.Vector())
+		{
+			ArtifactID art(VLC->modh->identifiers.getIdentifier("artifact", entry).get());
+			ret.push_back(art);
+		}
+		return ret;
+	}
+
+	std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::vector<SpellID> ret;
+		for (const JsonNode & entry : value.Vector())
+		{
+			SpellID spell(VLC->modh->identifiers.getIdentifier("spell", entry).get());
+			ret.push_back(spell);
+		}
+		return ret;
+	}
+
+	std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng)
+	{
+		std::vector<CStackBasicDescriptor> ret;
+		for (auto & pair : value.Struct())
+		{
+			CStackBasicDescriptor stack;
+			stack.type = VLC->creh->creatures[VLC->modh->identifiers.getIdentifier(pair.second.meta, "creature", pair.first).get()];
+			stack.count = loadValue(pair.second, rng);
+			ret.push_back(stack);
+		}
+		return ret;
+	}
+
+	std::vector<Bonus> loadBonuses(const JsonNode & value)
+	{
+		std::vector<Bonus> ret;
+		for (const JsonNode & entry : value.Vector())
+		{
+			Bonus * bonus = JsonUtils::parseBonus(entry);
+			ret.push_back(*bonus);
+			delete bonus;
+		}
+		return ret;
+	}
+
+	std::vector<Component> loadComponents(const JsonNode & value)
+	{
+		//TODO
+	}
+
+	MetaString loadMessage(const JsonNode & value)
+	{
+		MetaString ret;
+		if (value.getType() == JsonNode::DATA_FLOAT)
+			ret.addTxt(MetaString::ADVOB_TXT, value.Float());
+		else
+			ret << value.String();
+		return ret;
+	}
+
+	bool testForKey(const JsonNode & value, const std::string & key)
+	{
+		for( auto & reward : value["rewards"].Vector() )
+		{
+			if (!reward[key].isNull())
+				return true;
+		}
+		return false;
+	}
+}
+
 void CRandomRewardObjectInfo::init(const JsonNode & objectConfig)
 {
 	parameters = objectConfig;
 }
 
-void CRandomRewardObjectInfo::configureObject(CObjectWithReward * object) const
+void CRandomRewardObjectInfo::configureObject(CObjectWithReward * object, CRandomGenerator & rng) const
 {
+	for (const JsonNode & reward : parameters["rewards"].Vector())
+	{
+		const JsonNode & limiter = reward["limiter"];
+		CVisitInfo info;
+		// load limiter
+		info.limiter.numOfGrants = loadValue(limiter["numOfGrants"], rng);
+		info.limiter.dayOfWeek = loadValue(limiter["dayOfWeek"], rng);
+		info.limiter.minLevel = loadValue(limiter["minLevel"], rng);
+		info.limiter.resources = loadResources(limiter["resources"], rng);
+
+		info.limiter.primary = loadPrimary(limiter["primary"], rng);
+		info.limiter.secondary = loadSecondary(limiter["secondary"], rng);
+		info.limiter.artifacts = loadArtifacts(limiter["artifacts"], rng);
+		info.limiter.creatures = loadCreatures(limiter["creatures"], rng);
+
+		info.reward.resources = loadResources(reward["resources"], rng);
+
+		info.reward.gainedExp = loadValue(reward["gainedExp"], rng);
+		info.reward.gainedLevels = loadValue(reward["gainedLevels"], rng);
+
+		info.reward.manaDiff = loadValue(reward["manaPoints"], rng);
+		info.reward.manaPercentage = loadValue(reward["manaPercentage"], rng, -1);
+
+		info.reward.movePoints = loadValue(reward["movePoints"], rng);
+		info.reward.movePercentage = loadValue(reward["movePercentage"], rng, -1);
+
+		info.reward.bonuses = loadBonuses(reward["bonuses"]);
+
+		info.reward.primary = loadPrimary(reward["primary"], rng);
+		info.reward.secondary = loadSecondary(reward["secondary"], rng);
+
+		info.reward.artifacts = loadArtifacts(reward["artifacts"], rng);
+		info.reward.spells = loadSpells(reward["spells"], rng);
+		info.reward.creatures = loadCreatures(reward["creatures"], rng);
+	}
+
+	object->onSelect  = loadMessage(parameters["onSelectMessage"]);
+	object->onVisited = loadMessage(parameters["onVisitedMessage"]);
+	object->onEmpty   = loadMessage(parameters["onEmptyMessage"]);
+
+	//TODO: visitMode and selectMode
 
+	object->soundID = parameters["soundID"].Float();
+	object->resetDuration = parameters["resetDuration"].Float();
+	object->canRefuse =parameters["canRefuse"].Bool();
 }
 
 bool CRandomRewardObjectInfo::givesResources() const
 {
+	return testForKey(parameters, "resources");
 }
 
 bool CRandomRewardObjectInfo::givesExperience() const
 {
+	return testForKey(parameters, "gainedExp") || testForKey(parameters, "gainedLevels");
 }
 
 bool CRandomRewardObjectInfo::givesMana() const
 {
+	return testForKey(parameters, "manaPoints") || testForKey(parameters, "manaPercentage");
 }
 
 bool CRandomRewardObjectInfo::givesMovement() const
 {
+	return testForKey(parameters, "movePoints") || testForKey(parameters, "movePercentage");
 }
 
 bool CRandomRewardObjectInfo::givesPrimarySkills() const
 {
+	return testForKey(parameters, "primary");
 }
 
 bool CRandomRewardObjectInfo::givesSecondarySkills() const
 {
+	return testForKey(parameters, "secondary");
 }
 
 bool CRandomRewardObjectInfo::givesArtifacts() const
 {
+	return testForKey(parameters, "artifacts");
 }
 
 bool CRandomRewardObjectInfo::givesCreatures() const
 {
+	return testForKey(parameters, "spells");
 }
 
 bool CRandomRewardObjectInfo::givesSpells() const
 {
+	return testForKey(parameters, "creatures");
 }
 
 bool CRandomRewardObjectInfo::givesBonuses() const
 {
+	return testForKey(parameters, "bonuses");
 }
 
 CObjectWithRewardConstructor::CObjectWithRewardConstructor()
@@ -77,9 +251,9 @@ CGObjectInstance * CObjectWithRewardConstructor::create(ObjectTemplate tmpl) con
 	return ret;
 }
 
-void CObjectWithRewardConstructor::configureObject(CGObjectInstance * object) const
+void CObjectWithRewardConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
 {
-	objectInfo.configureObject(dynamic_cast<CObjectWithReward*>(object));
+	objectInfo.configureObject(dynamic_cast<CObjectWithReward*>(object), rng);
 }
 
 const IObjectInfo * CObjectWithRewardConstructor::getObjectInfo(ObjectTemplate tmpl) const

+ 2 - 2
lib/CObjectConstructor.h

@@ -33,7 +33,7 @@ public:
 
 	bool givesBonuses() const override;
 
-	void configureObject(CObjectWithReward * object) const;
+	void configureObject(CObjectWithReward * object, CRandomGenerator & rng) const;
 
 	CRandomRewardObjectInfo()
 	{}
@@ -51,7 +51,7 @@ public:
 
 	CGObjectInstance * create(ObjectTemplate tmpl) const override;
 
-	void configureObject(CGObjectInstance * object) const override;
+	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
 
 	const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const override;
 };