瀏覽代碼

Parse spell range on load instead of on every cast attempt

Ivan Savenko 1 年之前
父節點
當前提交
a4fa409d1f
共有 3 個文件被更改,包括 69 次插入57 次删除
  1. 6 54
      lib/spells/BattleSpellMechanics.cpp
  2. 60 2
      lib/spells/CSpellHandler.cpp
  3. 3 1
      lib/spells/CSpellHandler.h

+ 6 - 54
lib/spells/BattleSpellMechanics.cpp

@@ -505,62 +505,14 @@ std::set<BattleHex> BattleSpellMechanics::spellRangeInHexes(BattleHex centralHex
 	using namespace SRSLPraserHelpers;
 
 	std::set<BattleHex> ret;
-	std::string rng = owner->getLevelInfo(getRangeLevel()).range + ','; //copy + artificial comma for easier handling
+	std::vector<int> rng = owner->getLevelInfo(getRangeLevel()).range;
 
-	if(rng.size() >= 2 && rng[0] != 'X') //there is at least one hex in range (+artificial comma)
+	for(auto & elem : rng)
 	{
-		std::string number1;
-		std::string number2;
-		int beg = 0;
-		int end = 0;
-		bool readingFirst = true;
-		for(auto & elem : rng)
-		{
-			if(std::isdigit(elem) ) //reading number
-			{
-				if(readingFirst)
-					number1 += elem;
-				else
-					number2 += elem;
-			}
-			else if(elem == ',') //comma
-			{
-				//calculating variables
-				if(readingFirst)
-				{
-					beg = std::stoi(number1);
-					number1 = "";
-				}
-				else
-				{
-					end = std::stoi(number2);
-					number2 = "";
-				}
-				//obtaining new hexes
-				std::set<ui16> curLayer;
-				if(readingFirst)
-				{
-					curLayer = getInRange(centralHex, beg, beg);
-				}
-				else
-				{
-					curLayer = getInRange(centralHex, beg, end);
-					readingFirst = true;
-				}
-				//adding obtained hexes
-				for(const auto & curLayer_it : curLayer)
-				{
-					ret.insert(curLayer_it);
-				}
-
-			}
-			else if(elem == '-') //dash
-			{
-				beg = std::stoi(number1);
-				number1 = "";
-				readingFirst = false;
-			}
-		}
+		std::set<ui16> curLayer = getInRange(centralHex, elem, elem);
+		//adding obtained hexes
+		for(const auto & curLayer_it : curLayer)
+			ret.insert(curLayer_it);
 	}
 
 	return ret;

+ 60 - 2
lib/spells/CSpellHandler.cpp

@@ -557,7 +557,7 @@ CSpell::TargetInfo::TargetInfo(const CSpell * spell, const int level, spells::Mo
 	const auto & levelInfo = spell->getLevelInfo(level);
 
 	smart = levelInfo.smartTarget;
-	massive = levelInfo.range == "X";
+	massive = levelInfo.range.empty();
 	clearAffected = levelInfo.clearAffected;
 	clearTarget = levelInfo.clearTarget;
 }
@@ -677,6 +677,64 @@ const std::vector<std::string> & CSpellHandler::getTypeNames() const
 	return typeNames;
 }
 
+std::vector<int> CSpellHandler::spellRangeInHexes(std::string input) const
+{
+	std::set<BattleHex> ret;
+	std::string rng = input + ','; //copy + artificial comma for easier handling
+
+	if(rng.size() >= 2 && rng[0] != 'X') //there is at least one hex in range (+artificial comma)
+	{
+		std::string number1;
+		std::string number2;
+		int beg = 0;
+		int end = 0;
+		bool readingFirst = true;
+		for(auto & elem : rng)
+		{
+			if(std::isdigit(elem) ) //reading number
+			{
+				if(readingFirst)
+					number1 += elem;
+				else
+					number2 += elem;
+			}
+			else if(elem == ',') //comma
+			{
+				//calculating variables
+				if(readingFirst)
+				{
+					beg = std::stoi(number1);
+					number1 = "";
+				}
+				else
+				{
+					end = std::stoi(number2);
+					number2 = "";
+				}
+				//obtaining new hexes
+				std::set<ui16> curLayer;
+				if(readingFirst)
+				{
+					ret.insert(beg);
+				}
+				else
+				{
+					for(int i = beg; i <= end; ++i)
+						ret.insert(i);
+				}
+			}
+			else if(elem == '-') //dash
+			{
+				beg = std::stoi(number1);
+				number1 = "";
+				readingFirst = false;
+			}
+		}
+	}
+
+	return std::vector<int>(ret.begin(), ret.end());
+}
+
 std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index)
 {
 	assert(identifier.find(':') == std::string::npos);
@@ -931,7 +989,7 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
 		levelObject.smartTarget   = levelNode["targetModifier"]["smart"].Bool();
 		levelObject.clearTarget   = levelNode["targetModifier"]["clearTarget"].Bool();
 		levelObject.clearAffected = levelNode["targetModifier"]["clearAffected"].Bool();
-		levelObject.range         = levelNode["range"].String();
+		levelObject.range         = spellRangeInHexes(levelNode["range"].String());
 
 		for(const auto & elem : levelNode["effects"].Struct())
 		{

+ 3 - 1
lib/spells/CSpellHandler.h

@@ -110,7 +110,7 @@ public:
 		bool smartTarget = true;
 		bool clearTarget = false;
 		bool clearAffected = false;
-		std::string range = "0";
+		std::vector<int> range = { 0 };
 
 		//TODO: remove these two when AI will understand special effects
 		std::vector<std::shared_ptr<Bonus>> effects; //deprecated
@@ -305,6 +305,8 @@ bool DLL_LINKAGE isInScreenRange(const int3 &center, const int3 &pos); //for spe
 
 class DLL_LINKAGE CSpellHandler: public CHandlerBase<SpellID, spells::Spell, CSpell, spells::Service>
 {
+	std::vector<int> spellRangeInHexes(std::string rng) const;
+
 public:
 	///IHandler base
 	std::vector<JsonNode> loadLegacyData() override;