浏览代码

Added full parser for Bonus structure, as described in http://wiki.vcmi.eu/index.php?title=Bonus_Format
Untested.
Limiters / propagators are not yet supported.

DjWarmonger 13 年之前
父节点
当前提交
d56e7c568a
共有 3 个文件被更改,包括 175 次插入25 次删除
  1. 28 0
      lib/HeroBonus.cpp
  2. 34 24
      lib/HeroBonus.h
  3. 113 1
      lib/JsonNode.cpp

+ 28 - 0
lib/HeroBonus.cpp

@@ -20,6 +20,34 @@
 	const std::map<std::string, int> bonusNameMap = boost::assign::map_list_of BONUS_LIST;
 #undef BONUS_NAME
 
+#define BONUS_VALUE(x) ( #x, Bonus::x )
+	const std::map<std::string, int> bonusValueMap = boost::assign::map_list_of BONUS_VALUE_LIST;
+#undef BONUS_VALUE
+
+#define BONUS_SOURCE(x) ( #x, Bonus::x )
+	const std::map<std::string, int> bonusSourceMap = boost::assign::map_list_of BONUS_SOURCE_LIST;
+#undef BONUS_SOURCE
+
+#define BONUS_ITEM(x) ( #x, Bonus::x )
+
+const std::map<std::string, int> bonusDurationMap = boost::assign::map_list_of 
+	BONUS_ITEM(PERMANENT)
+	BONUS_ITEM(ONE_BATTLE)
+	BONUS_ITEM(ONE_DAY)
+	BONUS_ITEM(ONE_WEEK)
+	BONUS_ITEM(N_TURNS)
+	BONUS_ITEM(N_DAYS)
+	BONUS_ITEM(UNITL_BEING_ATTACKED)
+	BONUS_ITEM(UNTIL_ATTACK)
+	BONUS_ITEM(STACK_GETS_TURN)
+	BONUS_ITEM(COMMANDER_KILLED);
+
+const std::map<std::string, int> bonusLimitEffect = boost::assign::map_list_of
+	BONUS_ITEM(NO_LIMIT)
+	BONUS_ITEM(ONLY_DISTANCE_FIGHT)
+	BONUS_ITEM(ONLY_MELEE_FIGHT)
+	BONUS_ITEM(ONLY_ENEMY_ARMY);
+
 #define BONUS_LOG_LINE(x) tlog5 << x << std::endl
 
 int CBonusSystemNode::treeChanged = 1;

+ 34 - 24
lib/HeroBonus.h

@@ -176,6 +176,33 @@ typedef boost::function<bool(const Bonus*)> CSelector;
 	BONUS_NAME(SPOILS_OF_WAR) /*val * 10^-6 * gained exp resources of subtype will be given to hero after battle*/\
 	BONUS_NAME(BLOCK)
 
+#define BONUS_SOURCE_LIST \
+	BONUS_SOURCE(ARTIFACT)\
+	BONUS_SOURCE(ARTIFACT_INSTANCE)\
+	BONUS_SOURCE(OBJECT)\
+	BONUS_SOURCE(CREATURE_ABILITY)\
+	BONUS_SOURCE(TERRAIN_NATIVE)\
+	BONUS_SOURCE(TERRAIN_OVERLAY)\
+	BONUS_SOURCE(SPELL_EFFECT)\
+	BONUS_SOURCE(TOWN_STRUCTURE)\
+	BONUS_SOURCE(HERO_BASE_SKILL)\
+	BONUS_SOURCE(SECONDARY_SKILL)\
+	BONUS_SOURCE(HERO_SPECIAL)\
+	BONUS_SOURCE(ARMY)\
+	BONUS_SOURCE(CAMPAIGN_BONUS)\
+	BONUS_SOURCE(SPECIAL_WEEK)\
+	BONUS_SOURCE(STACK_EXPERIENCE)\
+	BONUS_SOURCE(COMMANDER) /*TODO: consider using simply STACK_INSTANCE */\
+	BONUS_SOURCE(OTHER) /*used for defensive stance and default value of spell level limit*/
+
+#define BONUS_VALUE_LIST \
+	BONUS_VALUE(ADDITIVE_VALUE)\
+	BONUS_VALUE(BASE_NUMBER)\
+	BONUS_VALUE(PERCENT_TO_ALL)\
+	BONUS_VALUE(PERCENT_TO_BASE)\
+	BONUS_VALUE(INDEPENDENT_MAX) /*used for SPELL bonus*/ \
+	BONUS_VALUE(INDEPENDENT_MIN) //used for SECONDARY_SKILL_PREMY bonus
+
 /// Struct for handling bonuses of several types. Can be transferred to any hero
 struct DLL_LINKAGE Bonus
 {
@@ -200,23 +227,9 @@ struct DLL_LINKAGE Bonus
 	};
 	enum BonusSource
 	{
-		ARTIFACT,
-		ARTIFACT_INSTANCE,
-		OBJECT,
-		CREATURE_ABILITY,
-		TERRAIN_NATIVE,
-		TERRAIN_OVERLAY,
-		SPELL_EFFECT,
-		TOWN_STRUCTURE,
-		HERO_BASE_SKILL,
-		SECONDARY_SKILL,
-		HERO_SPECIAL,
-		ARMY,
-		CAMPAIGN_BONUS,
-		SPECIAL_WEEK,
-		STACK_EXPERIENCE,
-		COMMANDER, //TODO: consider using simply STACK_INSTANCE
-		OTHER /*used for defensive stance and default value of spell level limit*/
+#define BONUS_SOURCE(x) x,
+		BONUS_SOURCE_LIST
+#undef BONUS_SOURCE
 	};
 
 	enum LimitEffect
@@ -228,12 +241,9 @@ struct DLL_LINKAGE Bonus
 
 	enum ValueType
 	{
-		ADDITIVE_VALUE,
-		BASE_NUMBER,
-		PERCENT_TO_ALL,
-		PERCENT_TO_BASE,
-		INDEPENDENT_MAX, //used for SPELL bonus
-		INDEPENDENT_MIN //used for SECONDARY_SKILL_PREMY bonus
+#define BONUS_VALUE(x) x,
+		BONUS_VALUE_LIST
+#undef BONUS_VALUE
 	};
 
 	ui16 duration; //uses BonusDuration values
@@ -854,7 +864,7 @@ namespace Selector
 	bool DLL_LINKAGE positiveSpellEffects(const Bonus *b);
 }
 
-extern DLL_LINKAGE const std::map<std::string, int> bonusNameMap;
+extern DLL_LINKAGE const std::map<std::string, int> bonusNameMap, bonusValueMap, bonusSourceMap, bonusDurationMap, bonusLimitEffect;
 
 // BonusList template that requires full interface of CBonusSystemNode
 template <class InputIterator>

+ 113 - 1
lib/JsonNode.cpp

@@ -889,7 +889,119 @@ Bonus * ParseBonus (const JsonVector &ability_vec) //TODO: merge with AddAbility
 	b->val = ability_vec[1].Float();
 	b->subtype = ability_vec[2].Float();
 	b->additionalInfo = ability_vec[3].Float();
-	b->duration = Bonus::PERMANENT;
+	b->duration = Bonus::PERMANENT; //TODO: handle flags (as integer)
 	b->turnsRemain = 0;
 	return b;
 }
+
+Bonus * ParseBonus (const JsonNode &ability)
+{
+	Bonus * b = new Bonus();
+	const JsonNode *value;
+
+	std::string type = ability["type"].String();
+	auto it = bonusNameMap.find(type);
+	if (it == bonusNameMap.end())
+	{
+		tlog1 << "Error: invalid ability type " << type << std::endl;
+		return b;
+	}
+	b->type = it->second;
+
+	value = &ability["subtype"];
+	if (!value->isNull())
+		b->subtype = value->Float();
+
+	value = &ability["val"];
+	if (!value->isNull())
+		b->val = value->Float();
+
+	value = &ability["valueType"];
+	if (!value->isNull())
+	{
+		std::string type = value->String();
+		auto it = bonusValueMap.find(type);
+		if (it == bonusValueMap.end())
+		{
+			tlog1 << "Error: invalid value type " << type << std::endl;
+		}
+		else
+		{
+			b->valType = it->second;
+		}
+	}
+
+	value = &ability["additionalInfo"];
+	if (!value->isNull())
+		b->additionalInfo = value->Float();
+
+	value = &ability["turns"];
+	if (!value->isNull())
+		b->turnsRemain = value->Float();
+
+	value = &ability["sourceID"];
+	if (!value->isNull())
+		b->sid = value->Float();
+
+	value = &ability["description"];
+	if (!value->isNull())
+		b->description = value->String();
+
+	
+	value = &ability["effectRange"];
+	if (!value->isNull())
+	{
+		std::string type = value->String();
+		auto it = bonusLimitEffect.find(type);
+		if (it == bonusLimitEffect.end())
+		{
+			tlog1 << "Error: invalid effect range " << type << std::endl;
+		}
+		else
+		{
+			b->effectRange = it->second;
+		}
+	}
+
+	
+	value = &ability["duration"];
+	if (!value->isNull())
+	{
+		std::string type = value->String();
+		auto it = bonusDurationMap.find(type);
+		if (it == bonusDurationMap.end())
+		{
+			tlog1 << "Error: invalid duration type " << type << std::endl;
+		}
+		else
+		{
+			b->duration = it->second;
+		}
+	}
+
+	value = &ability["source"];
+	if (!value->isNull())
+	{
+		std::string type = value->String();
+		auto it = bonusSourceMap.find(type);
+		if (it == bonusSourceMap.end())
+		{
+			tlog1 << "Error: invalid source type " << type << std::endl;
+		}
+		else
+		{
+			b->source = it->second;
+		}
+	}
+
+	//TODO:
+
+	//value = &ability["limiter"];
+	//if (!value->isNull())
+	//	b->limiter = value->Float();
+
+	//value = &ability["propagator"];
+	//if (!value->isNull())
+	//	b->propagator = value->Float();
+	return b;
+}