Quantcast

Parsing stacking equip effects works

Kevin Lyles [05-19-10 - 02:17]
Parsing stacking equip effects works
Filename
Regexps.lua
WeightsWatcher.lua
defaults.lua
diff --git a/Regexps.lua b/Regexps.lua
index 04ebf3e..59c0be8 100644
--- a/Regexps.lua
+++ b/Regexps.lua
@@ -11,6 +11,7 @@ local patternCategories = {
 	"generic",
 	"socketBonus",
 	"useEffect",
+	"stackingEquipEffect",
 }

 ww_regexes = {}
@@ -457,6 +458,119 @@ local CooldownUseAffixes = {
 	"^maximum +",
 }

+local StackingEquipMatchLines = {
+	"^equip: each .* stack",
+}
+
+local stackingEquipPreprocessLines = {
+	{"%. +each time you ", " SPLIT "},
+	{"%. +stacks ", ", stacking "},
+}
+
+local StackingEquipAffixes = {
+	"^equip: each time you +",
+	" t?on? an opponent,",
+	" the next",
+	"[%.,]",
+}
+
+local function parseStackingEquipEffectTriggers(trigger)
+	local triggerPatterns = {
+		{"^cast a ?(.*) spell$", "SpellCast"},
+		{"^deal ?(.*) damage$", "DamageDealt"},
+		{"^land a (.*) spell$", "SpellHit"},
+	}
+
+	for _, regex in ipairs(triggerPatterns) do
+		local pattern, triggerType = unpack(regex)
+		local start, _, triggerSubTypes = string.find(trigger, pattern)
+		if start then
+			local subTypes = {}
+			if not triggerSubTypes then
+				triggerSubTypes = ""
+			end
+			triggerSubTypes = triggerSubTypes:gsub(" or ", " OR ")
+			local start, finish, left = string.find(triggerSubTypes, "^([^A-Z]*) OR ")
+			while start do
+				table.insert(subTypes, left)
+				triggerSubTypes = triggerSubTypes:sub(finish + 1)
+				start, finish, left = string.find(triggerSubTypes, "^([^A-Z]*) OR ")
+			end
+			table.insert(subTypes, triggerSubTypes)
+			local triggers = {}
+			for _, subType in ipairs(subTypes) do
+				local trigger = triggerType
+				if subType == "" then
+					trigger = trigger:sub(1, 1):lower() .. trigger:sub(2)
+				end
+				for _, group in ipairs(triggerGroups[subType .. trigger]) do
+					triggers[group] = true
+				end
+			end
+
+			return triggers
+		end
+	end
+end
+
+local function parseStackingEquipEffect(text, section)
+	local start, _, trigger, stat, duration, numStacks = string.find(text, "^(.*) you gain (.*) for (.*) stacking up to (%d+) times$")
+	if not start then
+		return
+	end
+
+	triggers = parseStackingEquipEffectTriggers(trigger)
+	if not triggers then
+		return
+	end
+
+	stat = WeightsWatcher.singleStat(stat, section)
+	if not stat or not stat.stats then
+		return
+	end
+	local amount
+	for name, value in pairs(stat.stats) do
+		stat = name
+		amount = value
+	end
+
+	duration = WeightsWatcher.convertToSeconds(duration)
+	if not duration then
+		return
+	end
+
+	return {
+		triggers = triggers,
+		stat = stat,
+		value = amount,
+		duration = duration,
+		numStacks = tonumber(numStacks),
+	}
+end
+
+local function parseStackingEquipEffects(text, section)
+	local lines = {}
+	local start, finish, left = string.find(text, "^([^A-Z]*) SPLIT ")
+	while start do
+		table.insert(lines, left)
+		text = text:sub(finish + 1)
+		start, finish, left = string.find(text, "^([^A-Z]*) SPLIT ")
+	end
+	table.insert(lines, text)
+
+	local stats = {}
+
+	for _, line in pairs(lines) do
+		local stat = parseStackingEquipEffect(line, section)
+		if not stat then
+			return
+		end
+		table.insert(stats, stat)
+	end
+
+	return {stackingEquipEffects = stats}
+end
+
 local function parseStats(text, section)
 	for _, regex in ipairs(ww_regexes[section].MultipleStat) do
 		local pattern, func = unpack(regex)
@@ -486,6 +600,7 @@ EffectHandlers = {
 	{FishingMatchLines, {}, {}, FishingPreProcessLines, FishingAffixes, parseStats, "fishing"},
 	{UseEffectMatchLines, UseEffectIgnoreLines, UseEffectUnweightedLines, UseEffectPreprocessLines, UseEffectAffixes, parseStats, "useEffect"},
 	{CooldownUseMatchLines, {}, {}, CooldownUsePreprocessLines, CooldownUseAffixes, function(text) local stat = WeightsWatcher.useEffect(text) if stat then return {useEffect = stat} end end, "cooldownUseEffect"},
+	{StackingEquipMatchLines, {}, {}, stackingEquipPreprocessLines, StackingEquipAffixes, parseStackingEquipEffects, "stackingEquipEffect"},
 }

 function WeightsWatcher.twoStats(text, pattern, section)
@@ -885,7 +1000,7 @@ SingleStatLines = {
 	{"^([+-]?%d+) (armor)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "generic", "useEffect"}},
 	{"^([+-]?%d+) (agility)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}},
 	{"^([+-]?%d+) (intellect)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}},
-	{"^([+-]?%d+) (spirit)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "useEffect"}},
+	{"^([+-]?%d+) (spirit)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "stackingEquipEffect", "useEffect"}},
 	{"^([+-]?%d+) (stamina)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}},
 	{"^([+-]?%d+) (strength)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}},

@@ -1072,11 +1187,11 @@ SingleStatLines = {
 		function(text, pattern)
 			return WeightsWatcher.singleStatValueOnly(text, pattern, "mp5")
 		end,
-		{"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus"},
+		{"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "stackingEquipEffect"},
 	},
 	{"^([+-]?%d+) (%a[%a ]+ rating)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "useEffect"}},
-	{"^([+-]?%d+) (attack power)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "useEffect"}},
-	{"^([+-]?%d+) (spell power)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "useEffect"}},
+	{"^([+-]?%d+) (attack power)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "stackingEquipEffect", "useEffect"}},
+	{"^([+-]?%d+) (spell power)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "equipEffect", "food", "generic", "socketBonus", "stackingEquipEffect", "useEffect"}},
 	{"^([+-]?%d+) (%a+ resistance)$", WeightsWatcher.statNumFirst, {"enchant", "generic", "useEffect"}},
 	{"^([+-]?%d+) (all resistances)$", WeightsWatcher.statNumFirst, {"enchant", "equipEffect", "useEffect"}},
 	{"^([+-]?%d+) resist all$",
diff --git a/WeightsWatcher.lua b/WeightsWatcher.lua
index 25347c0..261906b 100644
--- a/WeightsWatcher.lua
+++ b/WeightsWatcher.lua
@@ -999,7 +999,7 @@ end

 function WeightsWatcher.getItemStats(link)
 	local textL, textR, pattern, func, start
-	local normalStats, nonStats, socketList, socketBonusStat, useEffects = WeightsWatcher.newStatTable(), {}, {}, WeightsWatcher.newStatTable(), {}
+	local normalStats, nonStats, socketList, socketBonusStat, useEffects, stackingEquipEffects = WeightsWatcher.newStatTable(), {}, {}, WeightsWatcher.newStatTable(), {}, {}
 	local ranged = false

 	-- Populate hidden tooltip
@@ -1039,6 +1039,11 @@ function WeightsWatcher.getItemStats(link)
 			if stats.useEffect then
 				table.insert(useEffects, stats.useEffect)
 			end
+			if stats.stackingEquipEffects then
+				for _, effect in ipairs(stats.stackingEquipEffects) do
+					table.insert(stackingEquipEffects, effect)
+				end
+			end
 		end
 	end

@@ -1053,6 +1058,7 @@ function WeightsWatcher.getItemStats(link)
 		sockets = socketList,
 		socketBonusStat = socketBonusStat,
 		useEffects = useEffects,
+		stackingEquipEffects = stackingEquipEffects,
 	}
 end

diff --git a/defaults.lua b/defaults.lua
index 8805e00..b576b9c 100644
--- a/defaults.lua
+++ b/defaults.lua
@@ -91,6 +91,17 @@ trackedStats = {
 	},
 }

+triggerGroups = {
+	["meleeDamageDealt"] = {"meleeDamage"},
+	["rangedDamageDealt"] = {"rangedDamage"},
+	["spellDamageDealt"] = {"harmfulSpell"},
+	["damagingSpellCast"] = {"harmfulSpell"},
+	["harmfulSpellHit"] = {"harmfulSpell"},
+	["spellCast"] = {"harmfulSpell", "helpfulSpell"},
+	["healingSpellCast"] = {"helpfulSpell"},
+	["helpfulSpellCast"] = {"helpfulSpell"},
+}
+
 classNames = {
 	["DEATHKNIGHT"] = "Death Knight",
 	["DRUID"] = "Druid",