浏览代码

added TimesHeroLevelUpdater; renamed ScalingUpdater to GrowsWithLevelUpdater

Henning Koehler 8 年之前
父节点
当前提交
552bad08b3
共有 8 个文件被更改,包括 115 次插入47 次删除
  1. 2 4
      config/heroes/castle.json
  2. 20 13
      config/schemas/bonus.json
  3. 1 1
      config/schemas/hero.json
  4. 5 7
      lib/CHeroHandler.cpp
  5. 47 6
      lib/HeroBonus.cpp
  6. 21 6
      lib/HeroBonus.h
  7. 17 9
      lib/JsonNode.cpp
  8. 2 1
      lib/registerTypes/RegisterTypes.h

+ 2 - 4
config/heroes/castle.json

@@ -14,10 +14,8 @@
 				"archery" : {
 					"subtype" : "skill.archery",
 					"type" : "SECONDARY_SKILL_PREMY",
-					"updater" : {
-						"parameters" : [ 100 ],
-						"type" : "GROWS_WITH_LEVEL"
-					},
+					"updater" : "TIMES_HERO_LEVEL",
+					"val" : 5,
 					"valueType" : "PERCENT_TO_BASE"
 				}
 			}

+ 20 - 13
config/schemas/bonus.json

@@ -71,21 +71,28 @@
 			]
 		},
 		"updater" : {
-			"description" : "updater",
-			"type" : "object",
-			"required" : ["type", "parameters"],
-			"additionalProperties" : false,
-			"properties" : {
-				"type" : {
-					"type" : "string",
-					"description" : "type"
+			"anyOf" : [
+				{
+					"type" : "string"
 				},
-				"parameters": {
-					"type" : "array",
-					"description" : "parameters",
-					"additionalItems" : true
+				{
+					"description" : "updater",
+					"type" : "object",
+					"required" : ["type", "parameters"],
+					"additionalProperties" : false,
+					"properties" : {
+						"type" : {
+							"type" : "string",
+							"description" : "type"
+						},
+						"parameters": {
+							"type" : "array",
+							"description" : "parameters",
+							"additionalItems" : true
+						}
+					}
 				}
-			}
+			]
 		},
 		"sourceID": {
 			"type":"number",

+ 1 - 1
config/schemas/hero.json

@@ -115,7 +115,7 @@
 			"additionalItems" : true
 		},
 		"specialty": {
-			"oneOf" : [
+			"anyOf" : [
 				{
 					"type":"array",
 					"description": "Description of hero specialty using bonus system (deprecated)",

+ 5 - 7
lib/CHeroHandler.cpp

@@ -408,12 +408,12 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo
 			int stepSize = specCreature.level ? specCreature.level : 5;
 
 			bonus->subtype = PrimarySkill::ATTACK;
-			bonus->updater.reset(new ScalingUpdater(specCreature.getAttack(false), stepSize));
+			bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getAttack(false), stepSize));
 			result.push_back(bonus);
 
 			bonus = std::make_shared<Bonus>(*bonus);
 			bonus->subtype = PrimarySkill::DEFENSE;
-			bonus->updater.reset(new ScalingUpdater(specCreature.getDefence(false), stepSize));
+			bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefence(false), stepSize));
 			result.push_back(bonus);
 		}
 		break;
@@ -421,8 +421,7 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo
 		bonus->type = Bonus::SECONDARY_SKILL_PREMY;
 		bonus->valType = Bonus::PERCENT_TO_BASE;
 		bonus->subtype = spec.subtype;
-		bonus->val = 0;
-		bonus->updater.reset(new ScalingUpdater(spec.val * 20));
+		bonus->updater.reset(new TimesHeroLevelUpdater());
 		result.push_back(bonus);
 		break;
 	case 3: //spell damage bonus, level dependent but calculated elsewhere
@@ -548,8 +547,7 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyBonusToBonuses(const SSpecialtyBonu
 				break; // ignore - used to be overwritten based on SPECIAL_SECONDARY_SKILL
 			case Bonus::SPECIAL_SECONDARY_SKILL:
 				newBonus->type = Bonus::SECONDARY_SKILL_PREMY;
-				newBonus->updater = std::make_shared<ScalingUpdater>(newBonus->val * 20);
-				newBonus->val = 0; // for json printing
+				newBonus->updater = std::make_shared<TimesHeroLevelUpdater>();
 				result.push_back(newBonus);
 				break;
 			case Bonus::PRIMARY_SKILL:
@@ -561,7 +559,7 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyBonusToBonuses(const SSpecialtyBonu
 						const CCreature * cre = creatureLimiter->creature;
 						int creStat = newBonus->subtype == PrimarySkill::ATTACK ? cre->getAttack(false) : cre->getDefence(false);
 						int creLevel = cre->level ? cre->level : 5;
-						newBonus->updater = std::make_shared<ScalingUpdater>(creStat, creLevel);
+						newBonus->updater = std::make_shared<GrowsWithLevelUpdater>(creStat, creLevel);
 					}
 					result.push_back(newBonus);
 				}

+ 47 - 6
lib/HeroBonus.cpp

@@ -81,6 +81,11 @@ const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
 	{"GLOBAL_EFFECT", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)}
 }; //untested
 
+const std::map<std::string, TUpdaterPtr> bonusUpdaterMap =
+{
+	{"TIMES_HERO_LEVEL", std::make_shared<TimesHeroLevelUpdater>()}
+};
+
 ///CBonusProxy
 CBonusProxy::CBonusProxy(const IBonusBearer * Target, CSelector Selector)
 	: cachedLast(0),
@@ -1712,20 +1717,30 @@ IUpdater::~IUpdater()
 {
 }
 
+const std::shared_ptr<Bonus> IUpdater::update(const std::shared_ptr<Bonus> b, const CBonusSystemNode & context) const
+{
+	return b;
+}
+
 std::string IUpdater::toString() const
 {
 	return typeid(*this).name();
 }
 
-ScalingUpdater::ScalingUpdater() : valPer20(0), stepSize(1)
+JsonNode IUpdater::toJsonNode() const
 {
+	return JsonNode(JsonNode::JsonType::DATA_NULL);
 }
 
-ScalingUpdater::ScalingUpdater(int valPer20, int stepSize) : valPer20(valPer20), stepSize(stepSize)
+GrowsWithLevelUpdater::GrowsWithLevelUpdater() : valPer20(0), stepSize(1)
 {
 }
 
-const std::shared_ptr<Bonus> ScalingUpdater::update(const std::shared_ptr<Bonus> b, const CBonusSystemNode & context) const
+GrowsWithLevelUpdater::GrowsWithLevelUpdater(int valPer20, int stepSize) : valPer20(valPer20), stepSize(stepSize)
+{
+}
+
+const std::shared_ptr<Bonus> GrowsWithLevelUpdater::update(const std::shared_ptr<Bonus> b, const CBonusSystemNode & context) const
 {
 	if(context.getNodeType() == CBonusSystemNode::HERO)
 	{
@@ -1741,14 +1756,14 @@ const std::shared_ptr<Bonus> ScalingUpdater::update(const std::shared_ptr<Bonus>
 	return b;
 }
 
-std::string ScalingUpdater::toString() const
+std::string GrowsWithLevelUpdater::toString() const
 {
 	char buf[100];
-	sprintf(buf, "ScalingUpdater(valPer20=%d, stepSize=%d)", valPer20, stepSize);
+	sprintf(buf, "GrowsWithLevelUpdater(valPer20=%d, stepSize=%d)", valPer20, stepSize);
 	return std::string(buf);
 }
 
-JsonNode ScalingUpdater::toJsonNode() const
+JsonNode GrowsWithLevelUpdater::toJsonNode() const
 {
 	JsonNode root(JsonNode::JsonType::DATA_STRUCT);
 
@@ -1759,3 +1774,29 @@ JsonNode ScalingUpdater::toJsonNode() const
 
 	return root;
 }
+
+TimesHeroLevelUpdater::TimesHeroLevelUpdater()
+{
+}
+
+const std::shared_ptr<Bonus> TimesHeroLevelUpdater::update(const std::shared_ptr<Bonus> b, const CBonusSystemNode & context) const
+{
+	if(context.getNodeType() == CBonusSystemNode::HERO)
+	{
+		int level = static_cast<const CGHeroInstance &>(context).level;
+		std::shared_ptr<Bonus> newBonus = std::make_shared<Bonus>(*b);
+		newBonus->val *= level;
+		return newBonus;
+	}
+	return b;
+}
+
+std::string TimesHeroLevelUpdater::toString() const
+{
+	return "TimesHeroLevelUpdater";
+}
+
+JsonNode TimesHeroLevelUpdater::toJsonNode() const
+{
+	return JsonUtils::stringNode("TIMES_HERO_LEVEL");
+}

+ 21 - 6
lib/HeroBonus.h

@@ -1013,7 +1013,7 @@ extern DLL_LINKAGE const std::map<std::string, ui16> bonusDurationMap;
 extern DLL_LINKAGE const std::map<std::string, Bonus::LimitEffect> bonusLimitEffect;
 extern DLL_LINKAGE const std::map<std::string, TLimiterPtr> bonusLimiterMap;
 extern DLL_LINKAGE const std::map<std::string, TPropagatorPtr> bonusPropagatorMap;
-
+extern DLL_LINKAGE const std::map<std::string, TUpdaterPtr> bonusUpdaterMap;
 
 // BonusList template that requires full interface of CBonusSystemNode
 template <class InputIterator>
@@ -1030,23 +1030,23 @@ class DLL_LINKAGE IUpdater
 public:
 	virtual ~IUpdater();
 
-	virtual const std::shared_ptr<Bonus> update(const std::shared_ptr<Bonus> b, const CBonusSystemNode & context) const = 0;
+	virtual const std::shared_ptr<Bonus> update(const std::shared_ptr<Bonus> b, const CBonusSystemNode & context) const;
 	virtual std::string toString() const;
-	virtual JsonNode toJsonNode() const = 0;
+	virtual JsonNode toJsonNode() const;
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 	}
 };
 
-class DLL_LINKAGE ScalingUpdater : public IUpdater
+class DLL_LINKAGE GrowsWithLevelUpdater : public IUpdater
 {
 public:
 	int valPer20;
 	int stepSize;
 
-	ScalingUpdater();
-	ScalingUpdater(int valPer20, int stepSize = 1);
+	GrowsWithLevelUpdater();
+	GrowsWithLevelUpdater(int valPer20, int stepSize = 1);
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
@@ -1059,3 +1059,18 @@ public:
 	virtual std::string toString() const override;
 	virtual JsonNode toJsonNode() const override;
 };
+
+class DLL_LINKAGE TimesHeroLevelUpdater : public IUpdater
+{
+public:
+	TimesHeroLevelUpdater();
+
+	template <typename Handler> void serialize(Handler & h, const int version)
+	{
+		h & static_cast<IUpdater &>(*this);
+	}
+
+	const std::shared_ptr<Bonus> update(const std::shared_ptr<Bonus> b, const CBonusSystemNode & context) const override;
+	virtual std::string toString() const override;
+	virtual JsonNode toJsonNode() const override;
+};

+ 17 - 9
lib/JsonNode.cpp

@@ -651,17 +651,25 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
 	if(!value->isNull())
 	{
 		const JsonNode & updaterJson = *value;
-		if(updaterJson["type"].String() == "GROWS_WITH_LEVEL")
+		switch(updaterJson.getType())
 		{
-			std::shared_ptr<ScalingUpdater> updater = std::make_shared<ScalingUpdater>();
-			const JsonVector param = updaterJson["parameters"].Vector();
-			updater->valPer20 = param[0].Integer();
-			if(param.size() > 1)
-				updater->stepSize = param[1].Integer();
-			b->addUpdater(updater);
+		case JsonNode::JsonType::DATA_STRING:
+			b->addUpdater(parseByMap(bonusUpdaterMap, &updaterJson, "updater type "));
+			break;
+		case JsonNode::JsonType::DATA_STRUCT:
+			if(updaterJson["type"].String() == "GROWS_WITH_LEVEL")
+			{
+				std::shared_ptr<GrowsWithLevelUpdater> updater = std::make_shared<GrowsWithLevelUpdater>();
+				const JsonVector param = updaterJson["parameters"].Vector();
+				updater->valPer20 = param[0].Integer();
+				if(param.size() > 1)
+					updater->stepSize = param[1].Integer();
+				b->addUpdater(updater);
+			}
+			else
+				logMod->warn("Unknown updater type \"%s\"", updaterJson["type"].String());
+			break;
 		}
-		else
-			logMod->warn("Unknown updater type \"%s\"", updaterJson["type"].String());
 	}
 
 	return true;

+ 2 - 1
lib/registerTypes/RegisterTypes.h

@@ -136,7 +136,8 @@ void registerTypesMapObjectTypes(Serializer &s)
 
 #undef REGISTER_GENERIC_HANDLER
 
-	s.template registerType<IUpdater, ScalingUpdater>();
+	s.template registerType<IUpdater, GrowsWithLevelUpdater>();
+	s.template registerType<IUpdater, TimesHeroLevelUpdater>();
 	//new types (other than netpacks) must register here
 	//order of type registration is critical for loading old savegames
 }