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",