diff --git a/GemIds.lua b/GemIds.lua index 12c5bf6..857c55e 100644 --- a/GemIds.lua +++ b/GemIds.lua @@ -1,5 +1,3 @@ -WeightsWatcher = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceHook-2.1") - local L = ww_localizedStats -- format: diff --git a/Locales/enUS/base.lua b/Locales/enUS/base.lua index c57a1de..e1271fb 100644 --- a/Locales/enUS/base.lua +++ b/Locales/enUS/base.lua @@ -44,7 +44,6 @@ L["ALWAYS_MATCH_SOCKET"] = "Even if the socket bonus is worthless" L["ALWAYS_MATCH_SOCKET_TT"] = "Forces ideal gems to obey their socket color (even if the socket bonus has a 0 or negative score for that weight)" L["NORMALIZE"] = "Normalize weights" L["NORMALIZE_TT"] = "Divides item scores by the total of all stats' values in that weight" -L["IDEAL_USE_UPTIME"] = "Percent of ideal use effect uptime:" L["DISPLAY_OPTS"] = "Display Options" L["SHOW_WTS"] = "Show weights:" L["SHOW_IDEAL_WTS"] = "Show ideally-gemmed weights:" diff --git a/Locales/enUS/enUS.xml b/Locales/enUS/enUS.xml index 96c59ee..3e4f4e3 100644 --- a/Locales/enUS/enUS.xml +++ b/Locales/enUS/enUS.xml @@ -5,6 +5,15 @@ <Script file="stats.lua"/> <Script file="slots.lua"/> <Script file="classes-specs.lua"/> - <Script file="triggers.lua"/> + <Script file="patterns-base.lua"/> + <Script file="patterns-equip-stats.lua"/> + <Script file="patterns-elixirs.lua"/> + <Script file="patterns-food.lua"/> + <Script file="patterns-enchants.lua"/> + <Script file="patterns-fishing.lua"/> + <Script file="patterns-use-effects.lua"/> + <Script file="patterns-cooldown-use-effects.lua"/> + <Script file="patterns-stacking-equip-effects.lua"/> + <Script file="patterns.lua"/> <Script file="dropdown-options.lua"/> </Ui> \ No newline at end of file diff --git a/Locales/enUS/patterns-base.lua b/Locales/enUS/patterns-base.lua new file mode 100644 index 0000000..6ddf9a1 --- /dev/null +++ b/Locales/enUS/patterns-base.lua @@ -0,0 +1,18 @@ +if GetLocale() ~= "enUS" then + return +end + +local function sockets(text) + return {socket = text} +end + +local function socketBonuses(text, section) + local stat = WeightsWatcher.singleStat(text, section) + if stat and stat.stats then + return {socketBonusStat = stat.stats} + end +end + +ww_sockets = {{" socket$"}, {}, {}, {}, {" socket$"}, sockets, "socket"} +ww_generic = {{"^[^:]+$"}, {}, {}, {}, {}, WeightsWatcher.parseStats, "generic"} +ww_socketBonuses = {{"^socket bonus: "}, {}, {}, {}, {"^socket bonus: "}, socketBonuses, "socketBonus"} diff --git a/Locales/enUS/patterns-cooldown-use-effects.lua b/Locales/enUS/patterns-cooldown-use-effects.lua new file mode 100644 index 0000000..ab38ba3 --- /dev/null +++ b/Locales/enUS/patterns-cooldown-use-effects.lua @@ -0,0 +1,40 @@ +if GetLocale() ~= "enUS" then + return +end + +ww_localization["IDEAL_USE_UPTIME"] = "Percent of ideal use effect uptime:" + +local CooldownUseMatchLines = { + "^use: grants? .* cooldown%)$", + "^use: increases? .* cooldown%)$", +} + +local CooldownUsePreprocessLines = { + {" (arcane spell) power ", " %1 damage "}, + {" (fire spell) power ", " %1 damage "}, + {" (frost spell) power ", " %1 damage "}, + {" (holy spell) power ", " %1 damage "}, + {" (nature spell) power ", " %1 damage "}, + {" (shadow spell) power ", " %1 damage "}, + {" your stats ", " all stats "}, + {" dodge by ", " dodge rating by "}, +} + +local CooldownUseAffixes = { + "^use: +", + "^grants? +", + "^increases? +", + "^your +", + "^the target's +", + "^maximum +", +} + +local function cooldownUseEffect(text) + local stat = WeightsWatcher.useEffect(text) + + if stat then + return {useEffect = stat} + end +end + +ww_cooldownUseEffects = {CooldownUseMatchLines, {}, {}, CooldownUsePreprocessLines, CooldownUseAffixes, cooldownUseEffect, "cooldownUseEffect"} diff --git a/Locales/enUS/patterns-elixirs.lua b/Locales/enUS/patterns-elixirs.lua new file mode 100644 index 0000000..e5b62db --- /dev/null +++ b/Locales/enUS/patterns-elixirs.lua @@ -0,0 +1,55 @@ +if GetLocale() ~= "enUS" then + return +end + +local ElixirMatchLines = { + " battle elixir%.", + " guardian elixir%.", +} + +local ElixirUnweightedLines = { + " walk across water ", + " of your spell targets ", +} + +local ElixirPreprocessLines = { + {" and your ", " and "}, + {" and restores ", " and "}, + {" and grants ", " and "}, + {" critical rating ", " critical strike rating "}, + {" maximum health ", " health "}, + {" the chance that the player will reflect hostile spells cast on them by (%d+)%% for %d+ hrs%. +will automatically reflect the first offensive spell cast against the user", " %1%% spell reflect"}, + {" goes up by ", " by "}, +} + +local ElixirAffixes = { + "^use: +", + "^increases +", + "^your size is increased and +", + "^your +", + "^the player's +", + "^mana regeneration by +", + "^regenerate +", + " +%(1 sec cooldown%)$", + " +%([12] min cooldown%)$", + " +this effect persists through death, but only works [io]n [%a ',:]+%.$", + " +this effect only works [io]n [%a ',:]+%.$", + "[\r\n]+only active [io]n [%a ',:]+%.$", + " +effect persists through death%.$", + " +this$", + " +you can only have the effect of one flask at a time%.$", + " +counts as both a battle and guardian elixir%.$", + " +battle elixir%.$", + " +guardian elixir%.$", + " +%d+ ho?u?rs?%.$", + " +%d+ minu?t?e?s?%.$", + " +for$", + " +lasts$", + " +effect$", + " +when consumed%.$", + " +and size$", + " +to match your new size%.$", + "%.$", +} + +ww_elixirs = {ElixirMatchLines, {}, ElixirUnweightedLines, ElixirPreprocessLines, ElixirAffixes, WeightsWatcher.parseStats, "elixir"} diff --git a/Locales/enUS/patterns-enchants.lua b/Locales/enUS/patterns-enchants.lua new file mode 100644 index 0000000..b0ff6d5 --- /dev/null +++ b/Locales/enUS/patterns-enchants.lua @@ -0,0 +1,106 @@ +if GetLocale() ~= "enUS" then + return +end + +local EnchantMatchLines = { + "^use: permanently ", + "^use: teaches you how to permanently enchant ", + "^use: attaches ", + "^use: enchants? ", +} + +local EnchantUnweightedLines = { + " sometimes ", + " chance ", + " often ", + " damage to ", + " occasionally ", +} + +local EnchantPreprocessLines = { + {" socket ", " prismatic socket "}, + {" and increase?i?n?g? ", " and "}, + {" and your ", " and "}, + {" melee weapon to do (%d+) additional points? of damage", " %1 melee damage"}, + {" armor value ", " armor "}, + {" a slight movement speed increase", " a minor movement speed increase"}, + {"^use: attaches a permanent scope to a bow or gun that increases its damage by ", "increases ranged weapon damage by "}, + {" resistance to (%a+) by ", " %1 resistance by "}, + {" resistance to all schools of magic by ", " all resistances by "}, + {" to all ", " all "}, +} + +local EnchantAffixes = { + "^use: +", + "^teaches you how to +", + "^permanently +", + "^enchants? +", + "^attache?s? +", + "^an? +", + "^chain to your weapon, +", + "^counterweight to a two%-handed sword, mace, axe or polearm increasing the wielder's +", + "^permanent scope to a bow or gun +", + "weapon to increase its +", + "^spurs to your +", + + "^boots +", + "^bracers? +", + "^cloak +", + "^gloves +", + "^shield +", + "^piece of +", + "^chest armor +", + "^two%-handed +", + "^melee weapon +", + "^weapon +", + "^staff +", + "^ring +", + + "^%a+ l?e?g? ?armor onto pants +", + "^embroiders spellthread into pants, +", + "lightweight titanium plating to a shield, +", + + "^increasing +", + + "^[st]o +", + "^that +", + "^they +", + "^it +", + + "^increases? +", + "^provides? +", + "^adds? +", + "^gives? +", + "^grants? +", + "^regenerates? +", + "^restores? +", + + "^your +", + "^the +", + "^[bw]earer's +", + " of the [bw]earer", + "^both +", + "^its +", + + " +%(1 sec cooldown%)$", + " +only use?able on items level %d+ and above%.$", + " +requires a level %d+ or higher l?e?v?e?l? ?item%.$", + " +must be level %d+ or lower to gain this benefit%.$", + " +wearer must be level %d+ or higher%.$", + "[\r\n]+%a+ing [%a ]+ causes [%a ]+ to become soulbound%.$", + "[\r\n]+can only be attached to [%a ]+ in your inventory%.$", + " +only the enchanter's rings can be enchanted,? and enchanting a ring will cause it to become soulbound%.$", + -- TODO: flag this somehow and handle it in scoring + " +does not stack with other similar effects%.", + + "^eternal belt buckle onto a belt, adding a +", + " +to the belt%.$", + " +t?of? an item worn on the %a[%a ,]+ or %a+", + " +on a pair of gloves", + "additional points? of +", + "^mana regeneration by +", + + "%.$", +} + +ww_enchants = {EnchantMatchLines, {}, EnchantUnweightedLines, EnchantPreprocessLines, EnchantAffixes, WeightsWatcher.parseStats, "enchant"} diff --git a/Locales/enUS/patterns-equip-stats.lua b/Locales/enUS/patterns-equip-stats.lua new file mode 100644 index 0000000..4c2bbac --- /dev/null +++ b/Locales/enUS/patterns-equip-stats.lua @@ -0,0 +1,41 @@ +if GetLocale() ~= "enUS" then + return +end + +local EquipStatsMatchLines = { + "^equip: increases [^t].* by ", + "^equip: increases your effective stealth level", + "^equip: increases effective stealth level", + "^equip: improves [^t].* by ", + "^equip: restores ", + "^equip: increases the block value of your shield by ", + "^equip: [+-]?%d+ all resistances%.$", + "^equip: [+-]?%d+ armor%.$", +} + +local EquipStatsUnweightedLines = { + " when fighting ", + " spell power of ", + " pet[' ]", + " you kill a target ", + " against ", + " while ", + " periodic damage done by ", + " you use ", +} + +local EquipStatsPreprocessLines = { + {" effective stealth level%.$", " effective stealth level by 1."}, +} + +local EquipStatsAffixes = { + "^equip: +", + "^increases +", + "^improves +", + "^restores +", + "^your +", + " +does not work for players above level %d+%.$", + "%.$", +} + +ww_equipStats = {EquipStatsMatchLines, {}, EquipStatsUnweightedLines, EquipStatsPreprocessLines, EquipStatsAffixes, WeightsWatcher.parseStats, "equipEffect"} diff --git a/Locales/enUS/patterns-fishing.lua b/Locales/enUS/patterns-fishing.lua new file mode 100644 index 0000000..c004e10 --- /dev/null +++ b/Locales/enUS/patterns-fishing.lua @@ -0,0 +1,29 @@ +if GetLocale() ~= "enUS" then + return +end + +local FishingMatchLines = { + " fishing ", +} + +local FishingPreProcessLines = { + {" skill increased ", " "}, + {" for 10 min%. %(10 min cooldown%)$", ""}, +} + +local FishingAffixes = { + "^use: +", + "^equip: +", + "^replaces the fishing line on your fishing pole with a %a[%a ]+%a line, increasing +", + "^when applied to your fishing pole, increases +", + "^makes you slightly tipsy and increases your skill in +", + "^attach a lure to your equipped fishing pole, increasing +", + "%.$", + "utes$", + " +3 min", + " +10 min$", + " +1 hour$", + " +for$", +} + +ww_fishing = {FishingMatchLines, {}, {}, FishingPreProcessLines, FishingAffixes, WeightsWatcher.parseStats, "fishing"} diff --git a/Locales/enUS/patterns-food.lua b/Locales/enUS/patterns-food.lua new file mode 100644 index 0000000..11d339c --- /dev/null +++ b/Locales/enUS/patterns-food.lua @@ -0,0 +1,64 @@ +if GetLocale() ~= "enUS" then + return +end + +local FoodMatchLines = { + "^use: restores .* over ", + "^use: restores .* per seco?n?d? for ", + "^use: restores .* every seco?n?d? for ", + "^use: set out a %a+ feast ", + " drunk", + " drinker's desire ", + " smooo+th", +} + +local FoodIgnoreLines = { + " must remain seated while %a+ing%.$", + " usable only inside %a[%a ]+%.$", + " %(%d+ min cooldown%)$", + " nearby party members ", + "can only be consumed underwater%.", +} + +local FoodUnweightedLines = { + " you will become well fed and can track ", + " you are likely to grow in size%.", + " discover the fortune hidden in your meal!$", +} + +local FoodPreprocessLines = { + {" of your (%a+) ", " %1 "}, + {" every seco?n?d? for ", " over "}, + {" per seco?n?d? for ", " over "}, + {", but decreases ", " and decreases "}, +} + +local FoodAffixes = { + "^use: +", + "^set out a great feast that will feed your party! +", + "^set out a bountiful feast to feed a very hungry party%. +", + "^restores %d+%%? %a+ over %d+ sec%. *", + "^restores %d+%%? health and %d*%%? ?mana over %d+ sec%. *", + "^restores %d+ %a+ over %d+ sec, but at a cost%. +", + "^must remain seated while %a+ing%. +", + "^if you spend at least %d+ seco?n?d?s? %a+ing you will become \"?well fed\"? and +", + "^if you spend at least %d+ seco?n?d?s? %a+ing you will become enlightened and +", + "^if you eat for %d+ seconds will +", + "^gain +", + "^also +", + "^increases? +", + "^your +", + "^restores +", + " +green means it's good!$", + " +and gets you pretty drunk%.$", + " +and gets you drunk to boot[%.!]$", + " +standard alcohol%.$", + " +strong alcohol%.$", + " +also packs quite a kick%.%.%.$", + " +smooo+th%.$", + " +and increases the drinker's desire to converse%.$", + " +for %d+ min%.?$", + " +for %d+ hours?%.$", +} + +ww_food = {FoodMatchLines, FoodIgnoreLines, FoodUnweightedLines, FoodPreprocessLines, FoodAffixes, WeightsWatcher.parseStats, "food"} diff --git a/Locales/enUS/patterns-stacking-equip-effects.lua b/Locales/enUS/patterns-stacking-equip-effects.lua new file mode 100644 index 0000000..299da0f --- /dev/null +++ b/Locales/enUS/patterns-stacking-equip-effects.lua @@ -0,0 +1,138 @@ +if GetLocale() ~= "enUS" then + return +end + +ww_localization["Triggers"] = "Triggers" + +ww_triggerDisplayNames = { + ["meleeDamage"] = "Melee damage dealt", + ["rangedDamage"] = "Ranged damage dealt", + ["harmfulSpell"] = "Harmful spell cast", + ["helpfulSpell"] = "Helpful spell cast", +} + +local triggerGroups = { + ["meleeDamageDealt"] = {"meleeDamage"}, + ["rangedDamageDealt"] = {"rangedDamage"}, + ["spellDamageDealt"] = {"harmfulSpell"}, + ["damagingSpellCast"] = {"harmfulSpell"}, + ["harmfulSpellHit"] = {"harmfulSpell"}, + ["spellCast"] = {"harmfulSpell", "helpfulSpell"}, + ["healingSpellCast"] = {"helpfulSpell"}, + ["helpfulSpellCast"] = {"helpfulSpell"}, +} + +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 + +ww_stackingEquipEffects = {StackingEquipMatchLines, {}, {}, stackingEquipPreprocessLines, StackingEquipAffixes, parseStackingEquipEffects, "stackingEquipEffect"} diff --git a/Locales/enUS/patterns-use-effects.lua b/Locales/enUS/patterns-use-effects.lua new file mode 100644 index 0000000..0f3bb1b --- /dev/null +++ b/Locales/enUS/patterns-use-effects.lua @@ -0,0 +1,56 @@ +if GetLocale() ~= "enUS" then + return +end + +local UseEffectMatchLines = { + "^use: ", +} + +local UseEffectIgnoreLines = { + "^use: heal", + "^use: a strong alcoholic beverage", + "^use: transform", + "^use: a sample of ", + "^use: a typical alcoholic beverage", + " if they have free room ", + "^use: a weak alcohol", + "^use: throw into ", + "^use: a strangely glowing alcoholic beverage", + "^use: instantly restores ", +} + +local UseEffectUnweightedLines = { + "^[^%d]+ %(%d[%a%d ]+ cooldown%)$", + "^use: absorbs ", + "^use: coats a weapon with poison ", +} + +local UseEffectPreprocessLines = { + {" decreases your ", " decreases "}, + {" all magical resistances ", " all resistances "}, + {" additional ", " "}, + {" maximum health ", " health "}, + {" all attributes ", " all stats "}, +} + +local UseEffectAffixes = { + "^use: +", + "^a powerful ale that +", + "^increases +", + "^the target's +", + "^the player's +", + "^your +", + "^restores +", + "^gives the gift of the wild to all party and raid members, increasing +", + " +%([14] sec cooldown%)$", + " +only one scroll effect can be active at a time%.$", + " +for 5 min%.$", + " +30 mins?%.$", + " +1 hour%.$", + " +for$", + " +lasts$", + " +for all party and raid members$", + "%.$", +} + +ww_useEffects = {UseEffectMatchLines, UseEffectIgnoreLines, UseEffectUnweightedLines, UseEffectPreprocessLines, UseEffectAffixes, WeightsWatcher.parseStats, "useEffect"} diff --git a/Locales/enUS/patterns.lua b/Locales/enUS/patterns.lua new file mode 100644 index 0000000..71c4775 --- /dev/null +++ b/Locales/enUS/patterns.lua @@ -0,0 +1,790 @@ +if GetLocale() ~= "enUS" then + return +end + +ww_EffectHandlers = { + ww_equipStats, + ww_sockets, + ww_generic, + ww_socketBonuses, + ww_food, + ww_enchants, + ww_elixirs, + ww_fishing, + ww_useEffects, + ww_cooldownUseEffects, + ww_stackingEquipEffects, +} + +function WeightsWatcher.damageRange(textL, textR) + local stats + local start, _, minimum, maximum = string.find(textL, "^%+?(%d+) %- (%d+) %a* ?damage$") + if start then + stats = WeightsWatcher.newStatTable() + maximum = tonumber(maximum) + stats["average melee weapon damage"] = (minimum + maximum) / 2 + stats["maximum melee weapon damage"] = maximum + else + local start, _, damage = string.find(textL, "^(%d+) damage$") + if start then + stats = WeightsWatcher.newStatTable() + damage = tonumber(damage) + stats["average melee weapon damage"] = damage + stats["maximum melee weapon damage"] = damage + else + -- item 7730 + local start, _, damage = string.find(textL, "^%+(%d+) frost damage$") + if start then + stats = WeightsWatcher.newStatTable() + damage = tonumber(damage) + stats["average melee weapon damage"] = damage + stats["maximum melee weapon damage"] = damage + end + end + end + if stats and textR then + local start, _, speed = string.find(textR, "^speed (%d+%.?%d*)$") + if start then + stats["melee weapon speed"] = tonumber(speed) + end + end + return stats +end + +function WeightsWatcher.convertToSeconds(duration) + local start, _, hours = string.find(duration, "^(%d+) ho?u?rs?$") + if start then + return hours * 3600 + end + local start, _, minutes, seconds = string.find(duration, "^(%d+) minu?t?e?s? (%d+) seco?n?d?s?$") + if start then + return minutes * 60 + seconds + end + local start, _, minutes = string.find(duration, "^(%d+) minu?t?e?s?$") + if start then + return minutes * 60 + end + local start, _, seconds = string.find(duration, "^(%d+) seco?n?d?s?$") + if start then + return tonumber(seconds) + end +end + +function WeightsWatcher.useEffect(text) + local start, _, stat, value, duration, cooldown = string.find(text, "^(%a+ ?%a+ ?%a+ ?%a+) by ([+-]?%d+) for (%d+ %a+ ?%d* ?%a*)%. +%((%d+ %a+ ?%d* ?%a*) cooldown%)$") + if not start then + start, _, value, stat, duration, cooldown = string.find(text, "^([+-]?%d+) (%a+ ?%a+ ?%a+ ?%a+) for (%d+ %a+ ?%d* ?%a*)%. +%((%d+ %a+ ?%d* ?%a*) cooldown%)$") + end + if start then + cooldown = WeightsWatcher.convertToSeconds(cooldown) + duration = WeightsWatcher.convertToSeconds(duration) + return { + stat = stat, + value = value, + duration = duration, + cooldown = cooldown, + } + end +end + +ww_Preprocess = { + {"|c[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]([^|]+)|r", "%1"}, + {" +$", ""}, +} + +ww_ignoredInvalidStats = { + "item level", + "requires level", + "all stats", + "all resistances", +} + +ww_IgnoredLines = { + "^$", + -- Reputation and materials requirements + "^requires ", + "^ [^ ]", + "^%a[%a' -]+ %(%d/%d%)$", + "^classes: ", + "^\n", + "^\".+\"$", + "^races: ", + "^duration: ", + "^conjured item$", + "^use: right click to ", + "^this item begins a quest$", + "^already known$", + -- Zone names + "^alterac valley$", + "^black temple$", + "^blackrock depths$", + "^blade's edge mountains$", + "^isle of conquest$", + "^karazhan$", + "^shadowmoon valley", + "^strand of the ancients$", + "^tempest keep$", + "^the battle for mount hyjal$", + "^the black morass$", + "^the oculus$", + "^wintergrasp$", + "^zul'aman$", +} + +ww_TempIgnoredLines = { + "^item level %d+$", + "^use: restores %d+ to %d+ %a+", + "^use: teaches .* %(rank %d+%)%.$", + "^%d+ slot ", + "^use: heals %d+ damage over %d+ sec%.$", + -- Profession patterns + "^use: teaches you how to make ", + "^use: teaches you how to cut ", + "^use: teaches you how to craft ", + "^use: teaches you how to sew ", + "^use: teaches you how to cook ", + "^use: teaches you how to forge ", + "^use: teaches you how to transmute ", + "^use: teaches you how to create ", + "^use: teaches you how to bake ", + "^use: teaches you how to be ", + "^use: teaches you how to summon ", + "^use: teaches you how to brew ", + "^use: teaches you how to inscribe ", + "^use: teaches you how to ride ", + "^use: teaches you how to burn ", + "^use: teaches you how to deep fry ", + "^use: teaches you how to purify ", + "^use: teaches you how to shatter ", + "^use: teaches you how to smelt ", + "^use: teaches you how to turn ", +} + +ww_UnweightedLines = { + "^%(%d%) set: ", + "^set: ", -- In-game only? + -- Some relics that boost stats for certain abilities only + "^equip: increases the %a[%a ]+ of your %a[%a ]+ by ", + -- Use effects that have a cooldown + "cooldown", + "chance t?on? ", + "^use: .*enchants? ", + "^equip: you", + "^equip: causes your ", +} + +ww_MultipleStatLines = { + {"^([^,]+) and ([^,]+)$", WeightsWatcher.twoStats, {"elixir", "enchant", "food", "generic", "useEffect"}}, + {"^([+-]?%d+ )(%a[%a ]+%a) and (%a[%a ]+%a)$", WeightsWatcher.multipleStatsOneNumber, {"elixir", "food"}}, + {"^([%a%d][%a%d ]+[%a%d]), ([%a%d][%a%d ]+[%a%d]),? and ([%a%d][%a%d ]+[%a%d])$", + function(text, pattern, section) + local start, _, stat1, stat2, stat3 = string.find(text, pattern) + if start then + stat1 = WeightsWatcher.singleStat(stat1, section) + stat2 = WeightsWatcher.singleStat(stat2, section) + stat3 = WeightsWatcher.singleStat(stat3, section) + if stat1 and stat2 and stat3 then + return stat1.stats + stat2.stats + stat3.stats + end + end + end, + {"elixir", "food", "useEffect"}, + }, + -- used by some enchants + {"^(%a[%a ]+ rating )and (%a[%a ]+ rating )by( %d+)$", + function(text, pattern, section) + local start, _, stat1, stat2, value = string.find(text, pattern) + if start then + stat1 = WeightsWatcher.singleStat(stat1 .. "by" .. value, section) + stat2 = WeightsWatcher.singleStat(stat2 .. "by" .. value, section) + if stat1 and stat2 then + return stat1.stats + stat2.stats + else + ww_unparsed_lines[text][pattern].parsedTo = {stat1, stat2} + end + end + end, + {"enchant"}, + }, + {"^(%a[%a ]+ )and (%a[%a ]+ )rating by( %d+)$", + function(text, pattern, section) + local start, _, stat1, stat2, value = string.find(text, pattern) + if start then + stat1 = WeightsWatcher.singleStat(stat1 .. "rating by" .. value, section) + stat2 = WeightsWatcher.singleStat(stat2 .. "rating by" .. value, section) + if stat1 and stat2 then + return stat1.stats + stat2.stats + else + ww_unparsed_lines[text][pattern].parsedTo = {stat1, stat2} + end + end + end, + {"enchant"}, + }, + {"^(%a+), (%a+),? and (%a+) spell power by (%d+)$", + function(text, pattern) + local start, _, stat1, stat2, stat3, value = string.find(text, pattern) + if start then + value = tonumber(value) + local stats = WeightsWatcher.newStatTable() + stats[stat1 .. " spell damage"] = value + stats[stat2 .. " spell damage"] = value + stats[stat3 .. " spell damage"] = value + return stats + end + end, + {"elixir"}, + }, + {"^spell damage caused by (%a+), (%a+),? and (%a+) spells by up to (%d+)$", + function(text, pattern) + local start, _, stat1, stat2, stat3, value = string.find(text, pattern) + if start then + value = tonumber(value) + local stats = WeightsWatcher.newStatTable() + stats[stat1 .. " spell damage"] = value + stats[stat2 .. " spell damage"] = value + stats[stat3 .. " spell damage"] = value + return stats + end + end, + {"elixir"}, + }, + {"^(%a+) and (%a+) spell power by (%d+)$", + function(text, pattern) + local start, _, stat1, stat2, value = string.find(text, pattern) + if start then + value = tonumber(value) + local stats = WeightsWatcher.newStatTable() + stats[stat1 .. " spell damage"] = value + stats[stat2 .. " spell damage"] = value + return stats + end + end, + {"enchant"}, + }, + {"^([+-]?%d+) mana and health every 5 seco?n?d?s?$", + function(text, pattern) + local start, _, value = string.find(text, pattern) + if start then + value = tonumber(value) + local stats = WeightsWatcher.newStatTable() + stats["mp5"] = value + stats["hp5"] = value + return stats + end + end, + {"enchant"}, + }, + {"^([+-]?%d+) health and mana every 5 seco?n?d?s?$", + function(text, pattern) + local start, _, value = string.find(text, pattern) + if start then + value = tonumber(value) + local stats = WeightsWatcher.newStatTable() + stats["mp5"] = value + stats["hp5"] = value + return stats + end + end, + {"enchant"}, + }, + -- Convert this and following to re-use the parser? + -- item 10779 + {"(%a[%a ]+) by (%d+), (%a[%a ]+) by (%d+),? and your normal health regeneration by (%d+)", + function(text, pattern) + local start, _, stat1, val1, stat2, val2, val3 = string.find(text, pattern) + if start then + local stats = WeightsWatcher.newStatTable() + stats[stat1] = tonumber(val1) + stats[stat2] = tonumber(val2) + stats["hp5"] = tonumber(val3) + return stats + end + end, + {"equipEffect"}, + }, + {"^(%a+), (%a+), and (%a+) by (%d+)$", + function(text, pattern) + local start, _, stat1, stat2, stat3, value = string.find(text, pattern) + if start then + value = tonumber(value) + local stats = WeightsWatcher.newStatTable() + stats[stat1] = value + stats[stat2] = value + stats[stat3] = value + return stats + end + end, + {"enchant"}, + }, + -- currently used only by items 31864 and 31872 + {"^([^,]+) & ([^,]+)$", WeightsWatcher.twoStats, {"generic"}}, + -- currently only used by item 28363 + {"^([^,]+), ([^,]+)$", WeightsWatcher.twoStats, {"generic"}}, + {"^chance to resist (%a+) and (%a+) effects by (%d+)%%$", + function(text, pattern) + local start, _, effect1, effect2, value = string.find(text, pattern) + if start then + value = tonumber(value) + local stats = WeightsWatcher.newStatTable() + stats[effect1 .. " resist chance (percent)"] = value + stats[effect2 .. " resist chance (percent)"] = value + return stats + end + end, + {"equipEffect"}, + }, +} + +ww_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", "stackingEquipEffect", "useEffect"}}, + {"^([+-]?%d+) (stamina)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}}, + {"^([+-]?%d+) (strength)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}}, + + + {"^the (block value) of your shield by (%d+)$", WeightsWatcher.statNameFirst, {"equipEffect"}}, + {"^shield (block rating) by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"equipEffect"}}, + {"^(all stats) are reduced by (%d+)$", + function(text, pattern) + local start, _, name, value = string.find(text, pattern) + if start then + return WeightsWatcher.newStatTable({[name] = -tonumber(value)}) + end + end, + {"food"}, + }, + {"^reduces (%a[%a ]+) by (%d+)$", + function(text, pattern) + local start, _, name, value = string.find(text, pattern) + if start then + return WeightsWatcher.newStatTable({[name] = -tonumber(value)}) + end + end, + {"food"}, + }, + {"^resistance to all schools of magic by ([+-]?%d+)$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "all resistances") + end, + {"elixir"}, + }, + {"^(%a+ spell )power by ([+-]?%d+)$", + function(text, pattern) + local start, _, name, value = string.find(text, pattern) + if start then + return WeightsWatcher.newStatTable({[name .. "damage"] = tonumber(value)}) + end + end, + {"elixir", "enchant"}, + }, + {"^resilience by ([+-]?%d+)$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "resilience rating") + end, + {"enchant"}, + }, + {"^mounted movement speed by ([+-]?%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "mount speed (percent)") + end, + {"enchant"}, + }, + {"^mount speed by ([+-]?%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "mount speed (percent)") + end, + {"enchant", "equipEffect"}, + }, + {"^([+-]?%d+) additional (armor)$", WeightsWatcher.statNumFirst, {"enchant"}}, + {"^stealth$", + function(text, pattern) + return WeightsWatcher.newStatTable({["increased stealth"] = 1}) + end, + {"enchant"}, + }, + {"^stealth slightly$", + function(text, pattern) + return WeightsWatcher.newStatTable({["increased stealth"] = 1}) + end, + {"enchant"}, + }, + {"^effective stealth level by (%d+)$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "increased stealth") + end, + {"equipEffect"}, + }, + {"^threat from all attacks and spells by (%d+)%%$", + function(text, pattern) + local start, _, value = string.find(text, pattern) + if start then + return WeightsWatcher.newStatTable({["threat (percent)"] = value}) + end + end, + {"enchant"}, + }, + {"^threat caused by (%d+)%%$", + function(text, pattern) + local start, _, value = string.find(text, pattern) + if start then + return WeightsWatcher.newStatTable({["threat (percent)"] = value}) + end + end, + {"enchant"}, + }, + {"^decrease threat from all attacks and spells by (%d+)%%$", + function(text, pattern) + local start, _, value = string.find(text, pattern) + if start then + return WeightsWatcher.newStatTable({["threat reduction (percent)"] = value}) + end + end, + {"enchant"}, + }, + {"^([+-]?%d+) additional (block value)$", WeightsWatcher.statNumFirst, {"enchant"}}, + {"^reducing the duration of disarm effects by ([+-]?%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "disarm duration reduction (percent)") + end, + {"enchant"}, + }, + {"^prismatic socket$", + function(text, pattern) + return WeightsWatcher.newStatTable({[text] = 1}) + end, + {"enchant"}, + }, + + -- profession skills + {"^(fishing) skill by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"enchant", "fishing"}}, + {"^(fishing) by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"elixir", "enchant", "equipEffect", "fishing", "food", "generic", "socketBonus", "useEffect"}}, + {"^(herbalism) skill by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"enchant"}}, + {"^(mining) skill by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"enchant"}}, + {"^(skinning) skill by (%d+)$", WeightsWatcher.statNameFirst, {"enchant"}}, + + {"^reduces? (%a[%a ]+) by (%d+)$", + function(text, pattern, section) + local start, _, name, value = string.find(text, pattern) + if start then + local stats = WeightsWatcher.parseStats("-" .. value .. " " .. name, section) + if stats then + return stats.stats + end + end + end, + {"food", "useEffect"}, + }, + {"^decreases? (%a[%a ]+) by (%d+)$", + function(text, pattern, section) + local start, _, name, value = string.find(text, pattern) + if start then + local stats = WeightsWatcher.parseStats("-" .. value .. " " .. name, section) + if stats then + return stats.stats + end + end + end, + {"elixir", "food", "useEffect"}, + }, + -- Tends to eat other stats if not last + -- TODO: split this into a separate function instead of recursing? + {"^(%a+ ?%a+ ?%a+ ?%a+) by (%d+)$", + function(text, pattern, section) + local start, _, name, value = string.find(text, pattern) + if start then + local stats = parseStats(value .. " " .. name, section) + if stats then + return stats.stats + end + end + end, + {"elixir", "enchant", "equipEffect", "food", "useEffect"}, + }, + + {"^a minor movement speed increase$", + function(text, pattern) + return WeightsWatcher.newStatTable({["minor run speed"] = 1}) + end, + {"enchant"}, + }, + {"^reduce threat slightly$", + function(text, pattern) + return WeightsWatcher.newStatTable({["threat reduction (percent)"] = 2}) + end, + {"generic"}, + }, + + {"^%((%d+%.?%d*) damage per second%)$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "melee dps") + end, + {"generic"}, + }, + {"^([+-]?%d+) mana %a+ 5 seco?n?d?s?%.?$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "mp5") + end, + {"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", "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$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "all resistances") + end, + {"generic"}, + }, + {"^([+-]?%d+) resistance to all schools of magic$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "all resistances") + end, + {"food"}, + }, + {"^(%d+) block$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "block value") + end, + {"generic"}, + }, + {"^([+-]?%d+) (block value)$", WeightsWatcher.statNumFirst, {"enchant", "socketBonus"}}, + {"^([+-]?%d+) health %a+ 5 seco?n?d?s?%.?$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "hp5") + end, + {"elixir", "equipEffect", "food", "generic", "useEffect"}, + }, + {"^([+-]?%d+) (spell penetration)$", WeightsWatcher.statNumFirst, {"enchant", "equipEffect", "generic"}}, + {"^adds (%d[%d%.]*) damage per second$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "melee dps") + end, + {"generic"}, + }, + {"^([+-]?%d+) (ranged attack power)$", WeightsWatcher.statNumFirst, {"equipEffect", "generic"}}, + {"^([+-]?%d+) (all stats)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "generic", "useEffect"}}, + {"^([+-]?%d+) to (all stats)$", WeightsWatcher.statNumFirst, {"generic"}}, + {"^([+-]?%d+) ranged weapon damage$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "average ranged weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum ranged weapon damage") + end, + {"enchant"}, + }, + + {"^chance to resist (%a+) effects by (%d+)%%$", + function(text, pattern) + local start, _, effect, value = string.find(text, pattern) + if start then + return WeightsWatcher.newStatTable({[effect .. " resist chance (percent)"] = tonumber(value)}) + end + end, + {"equipEffect"}, + }, + + -- random suffix enchants + {"^([+-]?%d+) (%a+ spell damage)$", WeightsWatcher.statNumFirst, {"generic"}}, + -- Used only for random enchant id 1470 + {"^([+-]?%d+) resist shadow$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "shadow resistance") + end, + {"generic"}, + }, + -- currently only used by random enchant id -55 (of the Nightmare) + {"^([+-]?%d+) shadow damage$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "shadow spell damage") + end, + {"generic"}, + }, + + -- druid only + {"^increases attack power by (%d+) in cat, bear, dire bear, and moonkin forms only%.$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "feral attack power") + end, + {"generic"}, + }, + + -- meta effects + {"^(%d+)%% increased armor value from items$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "armor from items (percent)") + end, + {"generic"}, + }, + {"^([+-]?%d+)%% shield block value$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "block value (percent)") + end, + {"generic"}, + }, + {"^chance to increase melee/ranged attack speed$", + function(text, pattern) + return WeightsWatcher.newStatTable({["chance to increase physical haste"] = 1}) + end, + {"generic"}, + }, + {"^chance to increase spell cast speed$", + function(text, pattern) + return WeightsWatcher.newStatTable({["chance to increase spell haste"] = 1}) + end, + {"generic"}, + }, + {"^chance to restore health on hit$", + function(text, pattern) + return WeightsWatcher.newStatTable({[text] = 1}) + end, + {"generic"}, + }, + {"^chance to restore mana on spellcast$", + function(text, pattern) + return WeightsWatcher.newStatTable({[text] = 1}) + end, + {"generic"}, + }, + {"^chance to stun target$", + function(text, pattern) + return WeightsWatcher.newStatTable({[text] = 1}) + end, + {"generic"}, + }, + {"^(%d+)%% increased critical damage$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "critical damage (percent)") + end, + {"generic"}, + }, + {"^(%d+)%% increased critical healing effect$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "critical healing (percent)") + end, + {"generic"}, + }, + {"^fear duration reduced by (%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "fear duration reduction (percent)") + end, + {"generic"}, + }, + {"^([+-]?%d+)%% intellect$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "intellect (percent)") + end, + {"generic"}, + }, + {"^([+-]?%d+)%% mana$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "mana (percent)") + end, + {"generic"}, + }, + {"^([+-]?%d+) melee damage$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "average melee weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum melee weapon damage") + end, + {"enchant", "generic"}, + }, + {"^([+-]?%d+) physical damage$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "average melee weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum melee weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "average ranged weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum ranged weapon damage") + end, + {"enchant"}, + }, + {"^minor run speed increase$", + function(text, pattern) + return WeightsWatcher.newStatTable({["minor run speed"] = 1}) + end, + {"generic"}, + }, + {"^silence duration reduced by (%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "silence duration reduction (percent)") + end, + {"generic"}, + }, + {"^reduces snare/root duration by (%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "snare/root duration reduction (percent)") + end, + {"generic"}, + }, + {"^sometimes heal on your crits$", + function(text, pattern) + return WeightsWatcher.newStatTable({[text] = 1}) + end, + {"generic"}, + }, + {"^reduce spell damage taken by (%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "spell damage taken reduction (percent)") + end, + {"generic"}, + }, + {"^(%d+)%% spell reflect$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "spell reflect (percent)") + end, + {"elixir", "generic"}, + }, + {"^stun duration reduced by (%d+)%%$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "stun duration reduction (percent)") + end, + {"generic"}, + }, + {"^(%d+)%% stun resistance$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "stun resist chance (percent)") + end, + {"generic"}, + }, + {"^(%d+)%% reduced threat$", + function(text, pattern) + return WeightsWatcher.singleStatValueOnly(text, pattern, "threat reduction (percent)") + end, + {"generic"}, + }, +} + +ww_ItemInfoLines = { + "^binds ", + "^unique", + "^soulbound$", + "^heroic$", + "^quest item$", +} + +ww_DoubleSlotLines = { + "^head$", + "^shoulder$", + "^chest$", + "^wrist$", + "^hands$", + "^waist$", + "^legs$", + "^feet$", + "^two%-hand$", + "^one%-hand$", + "^main hand$", + "^off hand$", + "^ranged$", + "^relic$", + "^thrown$", + "^projectile$", +} + +ww_SingleSlotLines = { + "^finger$", + "^back$", + "^neck$", + "^trinket$", + "^held in off%-hand$", + "^shirt$", + "^tabard$", +} diff --git a/Locales/enUS/stats.lua b/Locales/enUS/stats.lua index 6b65db7..17c8941 100644 --- a/Locales/enUS/stats.lua +++ b/Locales/enUS/stats.lua @@ -201,6 +201,5 @@ ww_statCategories = { ["CC Resists/Reductions"] = "CC Resists/Reductions", ["Resistances"] = "Resistances", ["Professions"] = "Professions", - ["Triggers"] = "Triggers", ["Miscellaneous"] = "Miscellaneous", } diff --git a/Locales/enUS/triggers.lua b/Locales/enUS/triggers.lua deleted file mode 100644 index d32daf0..0000000 --- a/Locales/enUS/triggers.lua +++ /dev/null @@ -1,22 +0,0 @@ -if GetLocale() == "enUS" then - local L = ww_localization - - ww_triggerDisplayNames = { - ["meleeDamage"] = "Melee damage dealt", - ["rangedDamage"] = "Ranged damage dealt", - ["harmfulSpell"] = "Harmful spell cast", - ["helpfulSpell"] = "Helpful spell cast", - } - - ww_triggerGroups = { - ["meleeDamageDealt"] = {"meleeDamage"}, - ["rangedDamageDealt"] = {"rangedDamage"}, - ["spellDamageDealt"] = {"harmfulSpell"}, - ["damagingSpellCast"] = {"harmfulSpell"}, - ["harmfulSpellHit"] = {"harmfulSpell"}, - ["spellCast"] = {"harmfulSpell", "helpfulSpell"}, - ["healingSpellCast"] = {"helpfulSpell"}, - ["helpfulSpellCast"] = {"helpfulSpell"}, - } - -end diff --git a/Regexps.lua b/Regexps.lua index ed4df08..5995b7a 100644 --- a/Regexps.lua +++ b/Regexps.lua @@ -1,3 +1,5 @@ +WeightsWatcher = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceHook-2.1") + local patternCategories = { "elixir", "enchant", @@ -109,466 +111,7 @@ function WeightsWatcher.handleEffects(text, matchLines, ignoreLines, unweightedL end end -local FoodMatchLines = { - "^use: restores .* over ", - "^use: restores .* per seco?n?d? for ", - "^use: restores .* every seco?n?d? for ", - "^use: set out a %a+ feast ", - " drunk", - " drinker's desire ", - " smooo+th", -} - -local FoodIgnoreLines = { - " must remain seated while %a+ing%.$", - " usable only inside %a[%a ]+%.$", - " %(%d+ min cooldown%)$", - " nearby party members ", - "can only be consumed underwater%.", -} - -local FoodUnweightedLines = { - " you will become well fed and can track ", - " you are likely to grow in size%.", - " discover the fortune hidden in your meal!$", -} - -local FoodPreprocessLines = { - {" of your (%a+) ", " %1 "}, - {" every seco?n?d? for ", " over "}, - {" per seco?n?d? for ", " over "}, - {", but decreases ", " and decreases "}, -} - -local FoodAffixes = { - "^use: +", - "^set out a great feast that will feed your party! +", - "^set out a bountiful feast to feed a very hungry party%. +", - "^restores %d+%%? %a+ over %d+ sec%. *", - "^restores %d+%%? health and %d*%%? ?mana over %d+ sec%. *", - "^restores %d+ %a+ over %d+ sec, but at a cost%. +", - "^must remain seated while %a+ing%. +", - "^if you spend at least %d+ seco?n?d?s? %a+ing you will become \"?well fed\"? and +", - "^if you spend at least %d+ seco?n?d?s? %a+ing you will become enlightened and +", - "^if you eat for %d+ seconds will +", - "^gain +", - "^also +", - "^increases? +", - "^your +", - "^restores +", - " +green means it's good!$", - " +and gets you pretty drunk%.$", - " +and gets you drunk to boot[%.!]$", - " +standard alcohol%.$", - " +strong alcohol%.$", - " +also packs quite a kick%.%.%.$", - " +smooo+th%.$", - " +and increases the drinker's desire to converse%.$", - " +for %d+ min%.?$", - " +for %d+ hours?%.$", -} - -local EquipStatsMatchLines = { - "^equip: increases [^t].* by ", - "^equip: increases your effective stealth level", - "^equip: increases effective stealth level", - "^equip: improves [^t].* by ", - "^equip: restores ", - "^equip: increases the block value of your shield by ", - "^equip: [+-]?%d+ all resistances%.$", - "^equip: [+-]?%d+ armor%.$", -} - -local EquipStatsUnweightedLines = { - " when fighting ", - " spell power of ", - " pet[' ]", - " you kill a target ", - " against ", - " while ", - " periodic damage done by ", - " you use ", -} - -local EquipStatsPreprocessLines = { - {" effective stealth level%.$", " effective stealth level by 1."}, -} - -local EquipStatsAffixes = { - "^equip: +", - "^increases +", - "^improves +", - "^restores +", - "^your +", - " +does not work for players above level %d+%.$", - "%.$", -} - -local EnchantMatchLines = { - "^use: permanently ", - "^use: teaches you how to permanently enchant ", - "^use: attaches ", - "^use: enchants? ", -} - -local EnchantUnweightedLines = { - " sometimes ", - " chance ", - " often ", - " damage to ", - " occasionally ", -} - -local EnchantPreprocessLines = { - {" socket ", " prismatic socket "}, - {" and increase?i?n?g? ", " and "}, - {" and your ", " and "}, - {" melee weapon to do (%d+) additional points? of damage", " %1 melee damage"}, - {" armor value ", " armor "}, - {" a slight movement speed increase", " a minor movement speed increase"}, - {"^use: attaches a permanent scope to a bow or gun that increases its damage by ", "increases ranged weapon damage by "}, - {" resistance to (%a+) by ", " %1 resistance by "}, - {" resistance to all schools of magic by ", " all resistances by "}, - {" to all ", " all "}, -} - -local EnchantAffixes = { - "^use: +", - "^teaches you how to +", - "^permanently +", - "^enchants? +", - "^attache?s? +", - "^an? +", - "^chain to your weapon, +", - "^counterweight to a two%-handed sword, mace, axe or polearm increasing the wielder's +", - "^permanent scope to a bow or gun +", - "weapon to increase its +", - "^spurs to your +", - - "^boots +", - "^bracers? +", - "^cloak +", - "^gloves +", - "^shield +", - "^piece of +", - "^chest armor +", - "^two%-handed +", - "^melee weapon +", - "^weapon +", - "^staff +", - "^ring +", - - "^%a+ l?e?g? ?armor onto pants +", - "^embroiders spellthread into pants, +", - "lightweight titanium plating to a shield, +", - - "^increasing +", - - "^[st]o +", - "^that +", - "^they +", - "^it +", - - "^increases? +", - "^provides? +", - "^adds? +", - "^gives? +", - "^grants? +", - "^regenerates? +", - "^restores? +", - - "^your +", - "^the +", - "^[bw]earer's +", - " of the [bw]earer", - "^both +", - "^its +", - - " +%(1 sec cooldown%)$", - " +only use?able on items level %d+ and above%.$", - " +requires a level %d+ or higher l?e?v?e?l? ?item%.$", - " +must be level %d+ or lower to gain this benefit%.$", - " +wearer must be level %d+ or higher%.$", - "[\r\n]+%a+ing [%a ]+ causes [%a ]+ to become soulbound%.$", - "[\r\n]+can only be attached to [%a ]+ in your inventory%.$", - " +only the enchanter's rings can be enchanted,? and enchanting a ring will cause it to become soulbound%.$", - -- TODO: flag this somehow and handle it in scoring - " +does not stack with other similar effects%.", - - "^eternal belt buckle onto a belt, adding a +", - " +to the belt%.$", - " +t?of? an item worn on the %a[%a ,]+ or %a+", - " +on a pair of gloves", - "additional points? of +", - "^mana regeneration by +", - - "%.$", -} - -local FishingMatchLines = { - " fishing ", -} - -local FishingPreProcessLines = { - {" skill increased ", " "}, - {" for 10 min%. %(10 min cooldown%)$", ""}, -} - -local FishingAffixes = { - "^use: +", - "^equip: +", - "^replaces the fishing line on your fishing pole with a %a[%a ]+%a line, increasing +", - "^when applied to your fishing pole, increases +", - "^makes you slightly tipsy and increases your skill in +", - "^attach a lure to your equipped fishing pole, increasing +", - "%.$", - "utes$", - " +3 min", - " +10 min$", - " +1 hour$", - " +for$", -} - -local UseEffectMatchLines = { - "^use: ", -} - -local UseEffectIgnoreLines = { - "^use: heal", - "^use: a strong alcoholic beverage", - "^use: transform", - "^use: a sample of ", - "^use: a typical alcoholic beverage", - " if they have free room ", - "^use: a weak alcohol", - "^use: throw into ", - "^use: a strangely glowing alcoholic beverage", - "^use: instantly restores ", -} - -local UseEffectUnweightedLines = { - "^[^%d]+ %(%d[%a%d ]+ cooldown%)$", - "^use: absorbs ", - "^use: coats a weapon with poison ", -} - -local UseEffectPreprocessLines = { - {" decreases your ", " decreases "}, - {" all magical resistances ", " all resistances "}, - {" additional ", " "}, - {" maximum health ", " health "}, - {" all attributes ", " all stats "}, -} - -local UseEffectAffixes = { - "^use: +", - "^a powerful ale that +", - "^increases +", - "^the target's +", - "^the player's +", - "^your +", - "^restores +", - "^gives the gift of the wild to all party and raid members, increasing +", - " +%([14] sec cooldown%)$", - " +only one scroll effect can be active at a time%.$", - " +for 5 min%.$", - " +30 mins?%.$", - " +1 hour%.$", - " +for$", - " +lasts$", - " +for all party and raid members$", - "%.$", -} - -local ElixirMatchLines = { - " battle elixir%.", - " guardian elixir%.", -} - -local ElixirUnweightedLines = { - " walk across water ", - " of your spell targets ", -} - -local ElixirPreprocessLines = { - {" and your ", " and "}, - {" and restores ", " and "}, - {" and grants ", " and "}, - {" critical rating ", " critical strike rating "}, - {" maximum health ", " health "}, - {" the chance that the player will reflect hostile spells cast on them by (%d+)%% for %d+ hrs%. +will automatically reflect the first offensive spell cast against the user", " %1%% spell reflect"}, - {" goes up by ", " by "}, -} - -local ElixirAffixes = { - "^use: +", - "^increases +", - "^your size is increased and +", - "^your +", - "^the player's +", - "^mana regeneration by +", - "^regenerate +", - " +%(1 sec cooldown%)$", - " +%([12] min cooldown%)$", - " +this effect persists through death, but only works [io]n [%a ',:]+%.$", - " +this effect only works [io]n [%a ',:]+%.$", - "[\r\n]+only active [io]n [%a ',:]+%.$", - " +effect persists through death%.$", - " +this$", - " +you can only have the effect of one flask at a time%.$", - " +counts as both a battle and guardian elixir%.$", - " +battle elixir%.$", - " +guardian elixir%.$", - " +%d+ ho?u?rs?%.$", - " +%d+ minu?t?e?s?%.$", - " +for$", - " +lasts$", - " +effect$", - " +when consumed%.$", - " +and size$", - " +to match your new size%.$", - "%.$", -} - -local CooldownUseMatchLines = { - "^use: grants? .* cooldown%)$", - "^use: increases? .* cooldown%)$", -} - -local CooldownUsePreprocessLines = { - {" (arcane spell) power ", " %1 damage "}, - {" (fire spell) power ", " %1 damage "}, - {" (frost spell) power ", " %1 damage "}, - {" (holy spell) power ", " %1 damage "}, - {" (nature spell) power ", " %1 damage "}, - {" (shadow spell) power ", " %1 damage "}, - {" your stats ", " all stats "}, - {" dodge by ", " dodge rating by "}, -} - -local CooldownUseAffixes = { - "^use: +", - "^grants? +", - "^increases? +", - "^your +", - "^the target's +", - "^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(ww_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) +function WeightsWatcher.parseStats(text, section) for _, regex in ipairs(ww_regexes[section].MultipleStat) do local pattern, func = unpack(regex) if string.find(text, pattern) then @@ -581,25 +124,6 @@ local function parseStats(text, section) return WeightsWatcher.singleStat(text, section) end -local function parseSocketBonusStat(text, section) - local stats = WeightsWatcher.singleStat(text, section) - return {socketBonusStat = stats.stats} -end - -ww_EffectHandlers = { - {EquipStatsMatchLines, {}, EquipStatsUnweightedLines, EquipStatsPreprocessLines, EquipStatsAffixes, parseStats, "equipEffect"}, - {{" socket$"}, {}, {}, {}, {" socket$"}, function(text) return {socket = text} end, "socket"}, - {{"^[^:]+$"}, {}, {}, {}, {}, parseStats, "generic"}, - {{"^socket bonus: "}, {}, {}, {}, {"^socket bonus: "}, parseSocketBonusStat, "socketBonus"}, - {FoodMatchLines, FoodIgnoreLines, FoodUnweightedLines, FoodPreprocessLines, FoodAffixes, parseStats, "food"}, - {EnchantMatchLines, {}, EnchantUnweightedLines, EnchantPreprocessLines, EnchantAffixes, parseStats, "enchant"}, - {ElixirMatchLines, {}, ElixirUnweightedLines, ElixirPreprocessLines, ElixirAffixes, parseStats, "elixir"}, - {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) local start, _, stat1, stat2 = string.find(text, pattern) if start then @@ -622,41 +146,6 @@ function WeightsWatcher.multipleStatsOneNumber(text, pattern, section) end end -function WeightsWatcher.damageRange(textL, textR) - local stats - local start, _, minimum, maximum = string.find(textL, "^%+?(%d+) %- (%d+) %a* ?damage$") - if start then - stats = WeightsWatcher.newStatTable() - maximum = tonumber(maximum) - stats["average melee weapon damage"] = (minimum + maximum) / 2 - stats["maximum melee weapon damage"] = maximum - else - local start, _, damage = string.find(textL, "^(%d+) damage$") - if start then - stats = WeightsWatcher.newStatTable() - damage = tonumber(damage) - stats["average melee weapon damage"] = damage - stats["maximum melee weapon damage"] = damage - else - -- item 7730 - local start, _, damage = string.find(textL, "^%+(%d+) frost damage$") - if start then - stats = WeightsWatcher.newStatTable() - damage = tonumber(damage) - stats["average melee weapon damage"] = damage - stats["maximum melee weapon damage"] = damage - end - end - end - if stats and textR then - local start, _, speed = string.find(textR, "^speed (%d+%.?%d*)$") - if start then - stats["melee weapon speed"] = tonumber(speed) - end - end - return stats -end - function WeightsWatcher.singleStat(text, section) for _, regex in ipairs(ww_regexes[section].SingleStat) do local pattern, func = unpack(regex) @@ -693,741 +182,3 @@ end function WeightsWatcher.newStatTable(tbl) return setmetatable(tbl or {}, ww_normalStatsMetatable) end - -function WeightsWatcher.convertToSeconds(duration) - local start, _, hours = string.find(duration, "^(%d+) ho?u?rs?$") - if start then - return hours * 3600 - end - local start, _, minutes, seconds = string.find(duration, "^(%d+) minu?t?e?s? (%d+) seco?n?d?s?$") - if start then - return minutes * 60 + seconds - end - local start, _, minutes = string.find(duration, "^(%d+) minu?t?e?s?$") - if start then - return minutes * 60 - end - local start, _, seconds = string.find(duration, "^(%d+) seco?n?d?s?$") - if start then - return tonumber(seconds) - end -end - -function WeightsWatcher.useEffect(text) - local start, _, stat, value, duration, cooldown = string.find(text, "^(%a+ ?%a+ ?%a+ ?%a+) by ([+-]?%d+) for (%d+ %a+ ?%d* ?%a*)%. +%((%d+ %a+ ?%d* ?%a*) cooldown%)$") - if not start then - start, _, value, stat, duration, cooldown = string.find(text, "^([+-]?%d+) (%a+ ?%a+ ?%a+ ?%a+) for (%d+ %a+ ?%d* ?%a*)%. +%((%d+ %a+ ?%d* ?%a*) cooldown%)$") - end - if start then - cooldown = WeightsWatcher.convertToSeconds(cooldown) - duration = WeightsWatcher.convertToSeconds(duration) - return { - stat = stat, - value = value, - duration = duration, - cooldown = cooldown, - } - end -end - -ww_Preprocess = { - {"|c[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]([^|]+)|r", "%1"}, - {" +$", ""}, -} - -ww_ignoredInvalidStats = { - "item level", - "requires level", - "all stats", - "all resistances", -} - -ww_IgnoredLines = { - "^$", - -- Reputation and materials requirements - "^requires ", - "^ [^ ]", - "^%a[%a' -]+ %(%d/%d%)$", - "^classes: ", - "^\n", - "^\".+\"$", - "^races: ", - "^duration: ", - "^conjured item$", - "^use: right click to ", - "^this item begins a quest$", - "^already known$", - -- Zone names - "^alterac valley$", - "^black temple$", - "^blackrock depths$", - "^blade's edge mountains$", - "^isle of conquest$", - "^karazhan$", - "^shadowmoon valley", - "^strand of the ancients$", - "^tempest keep$", - "^the battle for mount hyjal$", - "^the black morass$", - "^the oculus$", - "^wintergrasp$", - "^zul'aman$", -} - -ww_TempIgnoredLines = { - "^item level %d+$", - "^use: restores %d+ to %d+ %a+", - "^use: teaches .* %(rank %d+%)%.$", - "^%d+ slot ", - "^use: heals %d+ damage over %d+ sec%.$", - -- Profession patterns - "^use: teaches you how to make ", - "^use: teaches you how to cut ", - "^use: teaches you how to craft ", - "^use: teaches you how to sew ", - "^use: teaches you how to cook ", - "^use: teaches you how to forge ", - "^use: teaches you how to transmute ", - "^use: teaches you how to create ", - "^use: teaches you how to bake ", - "^use: teaches you how to be ", - "^use: teaches you how to summon ", - "^use: teaches you how to brew ", - "^use: teaches you how to inscribe ", - "^use: teaches you how to ride ", - "^use: teaches you how to burn ", - "^use: teaches you how to deep fry ", - "^use: teaches you how to purify ", - "^use: teaches you how to shatter ", - "^use: teaches you how to smelt ", - "^use: teaches you how to turn ", -} - -ww_UnweightedLines = { - "^%(%d%) set: ", - "^set: ", -- In-game only? - -- Some relics that boost stats for certain abilities only - "^equip: increases the %a[%a ]+ of your %a[%a ]+ by ", - -- Use effects that have a cooldown - "cooldown", - "chance t?on? ", - "^use: .*enchants? ", - "^equip: you", - "^equip: causes your ", -} - -ww_MultipleStatLines = { - {"^([^,]+) and ([^,]+)$", WeightsWatcher.twoStats, {"elixir", "enchant", "food", "generic", "useEffect"}}, - {"^([+-]?%d+ )(%a[%a ]+%a) and (%a[%a ]+%a)$", WeightsWatcher.multipleStatsOneNumber, {"elixir", "food"}}, - {"^([%a%d][%a%d ]+[%a%d]), ([%a%d][%a%d ]+[%a%d]),? and ([%a%d][%a%d ]+[%a%d])$", - function(text, pattern, section) - local start, _, stat1, stat2, stat3 = string.find(text, pattern) - if start then - stat1 = WeightsWatcher.singleStat(stat1, section) - stat2 = WeightsWatcher.singleStat(stat2, section) - stat3 = WeightsWatcher.singleStat(stat3, section) - if stat1 and stat2 and stat3 then - return stat1.stats + stat2.stats + stat3.stats - end - end - end, - {"elixir", "food", "useEffect"}, - }, - -- used by some enchants - {"^(%a[%a ]+ rating )and (%a[%a ]+ rating )by( %d+)$", - function(text, pattern, section) - local start, _, stat1, stat2, value = string.find(text, pattern) - if start then - stat1 = WeightsWatcher.singleStat(stat1 .. "by" .. value, section) - stat2 = WeightsWatcher.singleStat(stat2 .. "by" .. value, section) - if stat1 and stat2 then - return stat1.stats + stat2.stats - else - ww_unparsed_lines[text][pattern].parsedTo = {stat1, stat2} - end - end - end, - {"enchant"}, - }, - {"^(%a[%a ]+ )and (%a[%a ]+ )rating by( %d+)$", - function(text, pattern, section) - local start, _, stat1, stat2, value = string.find(text, pattern) - if start then - stat1 = WeightsWatcher.singleStat(stat1 .. "rating by" .. value, section) - stat2 = WeightsWatcher.singleStat(stat2 .. "rating by" .. value, section) - if stat1 and stat2 then - return stat1.stats + stat2.stats - else - ww_unparsed_lines[text][pattern].parsedTo = {stat1, stat2} - end - end - end, - {"enchant"}, - }, - {"^(%a+), (%a+),? and (%a+) spell power by (%d+)$", - function(text, pattern) - local start, _, stat1, stat2, stat3, value = string.find(text, pattern) - if start then - value = tonumber(value) - local stats = WeightsWatcher.newStatTable() - stats[stat1 .. " spell damage"] = value - stats[stat2 .. " spell damage"] = value - stats[stat3 .. " spell damage"] = value - return stats - end - end, - {"elixir"}, - }, - {"^spell damage caused by (%a+), (%a+),? and (%a+) spells by up to (%d+)$", - function(text, pattern) - local start, _, stat1, stat2, stat3, value = string.find(text, pattern) - if start then - value = tonumber(value) - local stats = WeightsWatcher.newStatTable() - stats[stat1 .. " spell damage"] = value - stats[stat2 .. " spell damage"] = value - stats[stat3 .. " spell damage"] = value - return stats - end - end, - {"elixir"}, - }, - {"^(%a+) and (%a+) spell power by (%d+)$", - function(text, pattern) - local start, _, stat1, stat2, value = string.find(text, pattern) - if start then - value = tonumber(value) - local stats = WeightsWatcher.newStatTable() - stats[stat1 .. " spell damage"] = value - stats[stat2 .. " spell damage"] = value - return stats - end - end, - {"enchant"}, - }, - {"^([+-]?%d+) mana and health every 5 seco?n?d?s?$", - function(text, pattern) - local start, _, value = string.find(text, pattern) - if start then - value = tonumber(value) - local stats = WeightsWatcher.newStatTable() - stats["mp5"] = value - stats["hp5"] = value - return stats - end - end, - {"enchant"}, - }, - {"^([+-]?%d+) health and mana every 5 seco?n?d?s?$", - function(text, pattern) - local start, _, value = string.find(text, pattern) - if start then - value = tonumber(value) - local stats = WeightsWatcher.newStatTable() - stats["mp5"] = value - stats["hp5"] = value - return stats - end - end, - {"enchant"}, - }, - -- Convert this and following to re-use the parser? - -- item 10779 - {"(%a[%a ]+) by (%d+), (%a[%a ]+) by (%d+),? and your normal health regeneration by (%d+)", - function(text, pattern) - local start, _, stat1, val1, stat2, val2, val3 = string.find(text, pattern) - if start then - local stats = WeightsWatcher.newStatTable() - stats[stat1] = tonumber(val1) - stats[stat2] = tonumber(val2) - stats["hp5"] = tonumber(val3) - return stats - end - end, - {"equipEffect"}, - }, - {"^(%a+), (%a+), and (%a+) by (%d+)$", - function(text, pattern) - local start, _, stat1, stat2, stat3, value = string.find(text, pattern) - if start then - value = tonumber(value) - local stats = WeightsWatcher.newStatTable() - stats[stat1] = value - stats[stat2] = value - stats[stat3] = value - return stats - end - end, - {"enchant"}, - }, - -- currently used only by items 31864 and 31872 - {"^([^,]+) & ([^,]+)$", WeightsWatcher.twoStats, {"generic"}}, - -- currently only used by item 28363 - {"^([^,]+), ([^,]+)$", WeightsWatcher.twoStats, {"generic"}}, - {"^chance to resist (%a+) and (%a+) effects by (%d+)%%$", - function(text, pattern) - local start, _, effect1, effect2, value = string.find(text, pattern) - if start then - value = tonumber(value) - local stats = WeightsWatcher.newStatTable() - stats[effect1 .. " resist chance (percent)"] = value - stats[effect2 .. " resist chance (percent)"] = value - return stats - end - end, - {"equipEffect"}, - }, -} - -ww_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", "stackingEquipEffect", "useEffect"}}, - {"^([+-]?%d+) (stamina)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}}, - {"^([+-]?%d+) (strength)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "food", "generic", "socketBonus", "useEffect"}}, - - - {"^the (block value) of your shield by (%d+)$", WeightsWatcher.statNameFirst, {"equipEffect"}}, - {"^shield (block rating) by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"equipEffect"}}, - {"^(all stats) are reduced by (%d+)$", - function(text, pattern) - local start, _, name, value = string.find(text, pattern) - if start then - return WeightsWatcher.newStatTable({[name] = -tonumber(value)}) - end - end, - {"food"}, - }, - {"^reduces (%a[%a ]+) by (%d+)$", - function(text, pattern) - local start, _, name, value = string.find(text, pattern) - if start then - return WeightsWatcher.newStatTable({[name] = -tonumber(value)}) - end - end, - {"food"}, - }, - {"^resistance to all schools of magic by ([+-]?%d+)$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "all resistances") - end, - {"elixir"}, - }, - {"^(%a+ spell )power by ([+-]?%d+)$", - function(text, pattern) - local start, _, name, value = string.find(text, pattern) - if start then - return WeightsWatcher.newStatTable({[name .. "damage"] = tonumber(value)}) - end - end, - {"elixir", "enchant"}, - }, - {"^resilience by ([+-]?%d+)$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "resilience rating") - end, - {"enchant"}, - }, - {"^mounted movement speed by ([+-]?%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "mount speed (percent)") - end, - {"enchant"}, - }, - {"^mount speed by ([+-]?%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "mount speed (percent)") - end, - {"enchant", "equipEffect"}, - }, - {"^([+-]?%d+) additional (armor)$", WeightsWatcher.statNumFirst, {"enchant"}}, - {"^stealth$", - function(text, pattern) - return WeightsWatcher.newStatTable({["increased stealth"] = 1}) - end, - {"enchant"}, - }, - {"^stealth slightly$", - function(text, pattern) - return WeightsWatcher.newStatTable({["increased stealth"] = 1}) - end, - {"enchant"}, - }, - {"^effective stealth level by (%d+)$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "increased stealth") - end, - {"equipEffect"}, - }, - {"^threat from all attacks and spells by (%d+)%%$", - function(text, pattern) - local start, _, value = string.find(text, pattern) - if start then - return WeightsWatcher.newStatTable({["threat (percent)"] = value}) - end - end, - {"enchant"}, - }, - {"^threat caused by (%d+)%%$", - function(text, pattern) - local start, _, value = string.find(text, pattern) - if start then - return WeightsWatcher.newStatTable({["threat (percent)"] = value}) - end - end, - {"enchant"}, - }, - {"^decrease threat from all attacks and spells by (%d+)%%$", - function(text, pattern) - local start, _, value = string.find(text, pattern) - if start then - return WeightsWatcher.newStatTable({["threat reduction (percent)"] = value}) - end - end, - {"enchant"}, - }, - {"^([+-]?%d+) additional (block value)$", WeightsWatcher.statNumFirst, {"enchant"}}, - {"^reducing the duration of disarm effects by ([+-]?%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "disarm duration reduction (percent)") - end, - {"enchant"}, - }, - {"^prismatic socket$", - function(text, pattern) - return WeightsWatcher.newStatTable({[text] = 1}) - end, - {"enchant"}, - }, - - -- profession skills - {"^(fishing) skill by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"enchant", "fishing"}}, - {"^(fishing) by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"elixir", "enchant", "equipEffect", "fishing", "food", "generic", "socketBonus", "useEffect"}}, - {"^(herbalism) skill by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"enchant"}}, - {"^(mining) skill by ([+-]?%d+)$", WeightsWatcher.statNameFirst, {"enchant"}}, - {"^(skinning) skill by (%d+)$", WeightsWatcher.statNameFirst, {"enchant"}}, - - {"^reduces? (%a[%a ]+) by (%d+)$", - function(text, pattern, section) - local start, _, name, value = string.find(text, pattern) - if start then - local stats = parseStats("-" .. value .. " " .. name, section) - if stats then - return stats.stats - end - end - end, - {"food", "useEffect"}, - }, - {"^decreases? (%a[%a ]+) by (%d+)$", - function(text, pattern, section) - local start, _, name, value = string.find(text, pattern) - if start then - local stats = parseStats("-" .. value .. " " .. name, section) - if stats then - return stats.stats - end - end - end, - {"elixir", "food", "useEffect"}, - }, - -- Tends to eat other stats if not last - -- TODO: split this into a separate function instead of recursing? - {"^(%a+ ?%a+ ?%a+ ?%a+) by (%d+)$", - function(text, pattern, section) - local start, _, name, value = string.find(text, pattern) - if start then - local stats = parseStats(value .. " " .. name, section) - if stats then - return stats.stats - end - end - end, - {"elixir", "enchant", "equipEffect", "food", "useEffect"}, - }, - - {"^a minor movement speed increase$", - function(text, pattern) - return WeightsWatcher.newStatTable({["minor run speed"] = 1}) - end, - {"enchant"}, - }, - {"^reduce threat slightly$", - function(text, pattern) - return WeightsWatcher.newStatTable({["threat reduction (percent)"] = 2}) - end, - {"generic"}, - }, - - {"^%((%d+%.?%d*) damage per second%)$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "melee dps") - end, - {"generic"}, - }, - {"^([+-]?%d+) mana %a+ 5 seco?n?d?s?%.?$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "mp5") - end, - {"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", "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$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "all resistances") - end, - {"generic"}, - }, - {"^([+-]?%d+) resistance to all schools of magic$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "all resistances") - end, - {"food"}, - }, - {"^(%d+) block$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "block value") - end, - {"generic"}, - }, - {"^([+-]?%d+) (block value)$", WeightsWatcher.statNumFirst, {"enchant", "socketBonus"}}, - {"^([+-]?%d+) health %a+ 5 seco?n?d?s?%.?$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "hp5") - end, - {"elixir", "equipEffect", "food", "generic", "useEffect"}, - }, - {"^([+-]?%d+) (spell penetration)$", WeightsWatcher.statNumFirst, {"enchant", "equipEffect", "generic"}}, - {"^adds (%d[%d%.]*) damage per second$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "melee dps") - end, - {"generic"}, - }, - {"^([+-]?%d+) (ranged attack power)$", WeightsWatcher.statNumFirst, {"equipEffect", "generic"}}, - {"^([+-]?%d+) (all stats)$", WeightsWatcher.statNumFirst, {"elixir", "enchant", "generic", "useEffect"}}, - {"^([+-]?%d+) to (all stats)$", WeightsWatcher.statNumFirst, {"generic"}}, - {"^([+-]?%d+) ranged weapon damage$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "average ranged weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum ranged weapon damage") - end, - {"enchant"}, - }, - - {"^chance to resist (%a+) effects by (%d+)%%$", - function(text, pattern) - local start, _, effect, value = string.find(text, pattern) - if start then - return WeightsWatcher.newStatTable({[effect .. " resist chance (percent)"] = tonumber(value)}) - end - end, - {"equipEffect"}, - }, - - -- random suffix enchants - {"^([+-]?%d+) (%a+ spell damage)$", WeightsWatcher.statNumFirst, {"generic"}}, - -- Used only for random enchant id 1470 - {"^([+-]?%d+) resist shadow$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "shadow resistance") - end, - {"generic"}, - }, - -- currently only used by random enchant id -55 (of the Nightmare) - {"^([+-]?%d+) shadow damage$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "shadow spell damage") - end, - {"generic"}, - }, - - -- druid only - {"^increases attack power by (%d+) in cat, bear, dire bear, and moonkin forms only%.$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "feral attack power") - end, - {"generic"}, - }, - - -- meta effects - {"^(%d+)%% increased armor value from items$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "armor from items (percent)") - end, - {"generic"}, - }, - {"^([+-]?%d+)%% shield block value$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "block value (percent)") - end, - {"generic"}, - }, - {"^chance to increase melee/ranged attack speed$", - function(text, pattern) - return WeightsWatcher.newStatTable({["chance to increase physical haste"] = 1}) - end, - {"generic"}, - }, - {"^chance to increase spell cast speed$", - function(text, pattern) - return WeightsWatcher.newStatTable({["chance to increase spell haste"] = 1}) - end, - {"generic"}, - }, - {"^chance to restore health on hit$", - function(text, pattern) - return WeightsWatcher.newStatTable({[text] = 1}) - end, - {"generic"}, - }, - {"^chance to restore mana on spellcast$", - function(text, pattern) - return WeightsWatcher.newStatTable({[text] = 1}) - end, - {"generic"}, - }, - {"^chance to stun target$", - function(text, pattern) - return WeightsWatcher.newStatTable({[text] = 1}) - end, - {"generic"}, - }, - {"^(%d+)%% increased critical damage$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "critical damage (percent)") - end, - {"generic"}, - }, - {"^(%d+)%% increased critical healing effect$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "critical healing (percent)") - end, - {"generic"}, - }, - {"^fear duration reduced by (%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "fear duration reduction (percent)") - end, - {"generic"}, - }, - {"^([+-]?%d+)%% intellect$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "intellect (percent)") - end, - {"generic"}, - }, - {"^([+-]?%d+)%% mana$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "mana (percent)") - end, - {"generic"}, - }, - {"^([+-]?%d+) melee damage$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "average melee weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum melee weapon damage") - end, - {"enchant", "generic"}, - }, - {"^([+-]?%d+) physical damage$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "average melee weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum melee weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "average ranged weapon damage") + WeightsWatcher.singleStatValueOnly(text, pattern, "maximum ranged weapon damage") - end, - {"enchant"}, - }, - {"^minor run speed increase$", - function(text, pattern) - return WeightsWatcher.newStatTable({["minor run speed"] = 1}) - end, - {"generic"}, - }, - {"^silence duration reduced by (%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "silence duration reduction (percent)") - end, - {"generic"}, - }, - {"^reduces snare/root duration by (%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "snare/root duration reduction (percent)") - end, - {"generic"}, - }, - {"^sometimes heal on your crits$", - function(text, pattern) - return WeightsWatcher.newStatTable({[text] = 1}) - end, - {"generic"}, - }, - {"^reduce spell damage taken by (%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "spell damage taken reduction (percent)") - end, - {"generic"}, - }, - {"^(%d+)%% spell reflect$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "spell reflect (percent)") - end, - {"elixir", "generic"}, - }, - {"^stun duration reduced by (%d+)%%$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "stun duration reduction (percent)") - end, - {"generic"}, - }, - {"^(%d+)%% stun resistance$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "stun resist chance (percent)") - end, - {"generic"}, - }, - {"^(%d+)%% reduced threat$", - function(text, pattern) - return WeightsWatcher.singleStatValueOnly(text, pattern, "threat reduction (percent)") - end, - {"generic"}, - }, -} - -ww_ItemInfoLines = { - "^binds ", - "^unique", - "^soulbound$", - "^heroic$", - "^quest item$", -} - -ww_DoubleSlotLines = { - "^head$", - "^shoulder$", - "^chest$", - "^wrist$", - "^hands$", - "^waist$", - "^legs$", - "^feet$", - "^two%-hand$", - "^one%-hand$", - "^main hand$", - "^off hand$", - "^ranged$", - "^relic$", - "^thrown$", - "^projectile$", -} - -ww_SingleSlotLines = { - "^finger$", - "^back$", - "^neck$", - "^trinket$", - "^held in off%-hand$", - "^shirt$", - "^tabard$", -} diff --git a/WeightsWatcher.toc b/WeightsWatcher.toc index c264ff8..5e2dca5 100644 --- a/WeightsWatcher.toc +++ b/WeightsWatcher.toc @@ -9,18 +9,19 @@ ## X-Category: Interface Enhancements ## X-License: GPLv2 -Locales\locales.xml - Libs\AceLibrary\AceLibrary.lua Libs\AceOO-2.0\AceOO-2.0.lua Libs\AceAddon-2.0\AceAddon-2.0.lua Libs\AceEvent-2.0\AceEvent-2.0.lua Libs\AceHook-2.1\AceHook-2.1.lua +Regexps.lua + +Locales\locales.xml + GemIds.lua config.xml weights.xml -Regexps.lua Upgrade.lua defaults.lua HiddenTooltip.xml diff --git a/config.xml b/config.xml index 3463b2f..2768b14 100644 --- a/config.xml +++ b/config.xml @@ -491,7 +491,12 @@ </Frames> <Scripts> <OnLoad> - self.label:SetText(ww_localization["IDEAL_USE_UPTIME"]) + if ww_cooldownUseEffects then + self.label:SetText(ww_localization["IDEAL_USE_UPTIME"]) + else + self:SetParent(nil) + self:Hide() + end </OnLoad> </Scripts> </Frame> diff --git a/defaults.lua b/defaults.lua index 6b0d98f..68caffb 100644 --- a/defaults.lua +++ b/defaults.lua @@ -13,7 +13,6 @@ ww_trackedStats = { ww_statCategories["PVP"], ww_statCategories["CC Resists/Reductions"], ww_statCategories["Resistances"], - ww_statCategories["Triggers"], ww_statCategories["Professions"], ww_statCategories["Miscellaneous"], [ww_statCategories["General"]] = { @@ -117,7 +116,6 @@ ww_trackedStats = { "nature resistance", "shadow resistance", }, - [ww_statCategories["Triggers"]] = {}, [ww_statCategories["Professions"]] = { "fishing", "herbalism", @@ -129,12 +127,12 @@ ww_trackedStats = { }, } -ww_triggerTypes = { - "meleeDamage", - "rangedDamage", - "harmfulSpell", - "helpfulSpell", -} +if ww_stackingEquipEffects then + table.insert(ww_trackedStats, 12, L["Triggers"]) + ww_trackedStats[L["Triggers"]] = {} + + ww_triggerTypes = {"meleeDamage", "rangedDamage", "harmfulSpell", "helpfulSpell"} +end ww_keyDetectors = { "Always", diff --git a/weights.lua b/weights.lua index a7779f7..ce835c2 100644 --- a/weights.lua +++ b/weights.lua @@ -125,7 +125,7 @@ function ww_configSelectWeight(weightFrame) for _, categoryFrame in ipairs(ww_weights.rightPanel.scrollFrame.categories) do local empty = true - if categoryFrame.name == L["Triggers"] then + if ww_stackingEquipEffects and categoryFrame.name == L["Triggers"] then for _, triggerFrame in ipairs({categoryFrame:GetChildren()}) do if triggerFrame.active then if triggerFrame.active:GetChecked() then @@ -183,11 +183,13 @@ function ww_configResetWeight() frame.statValue:SetText(value) end end - for _, categoryFrame in pairs(ww_weights.rightPanel.scrollFrame.categories) do - if categoryFrame.name == L["Triggers"] then - for _, triggerFrame in ipairs({categoryFrame:GetChildren()}) do - if triggerFrame.active then - triggerFrame.active:SetChecked(ww_weights.rightPanel.statList.triggers[triggerFrame.active:GetText()]) + if ww_stackingEquipEffects then + for _, categoryFrame in pairs(ww_weights.rightPanel.scrollFrame.categories) do + if categoryFrame.name == L["Triggers"] then + for _, triggerFrame in ipairs({categoryFrame:GetChildren()}) do + if triggerFrame.active then + triggerFrame.active:SetChecked(ww_weights.rightPanel.statList.triggers[triggerFrame.active:GetText()]) + end end end end @@ -462,7 +464,8 @@ local function loadStatButtons() createScrollableTieredList(ww_trackedStats, ww_weights.rightPanel.scrollFrame, ww_weights.rightPanel.scrollContainer, "ww_statFrame", 22, setmetatable({}, metatable)) for _, categoryFrame in ipairs(ww_weights.rightPanel.scrollFrame.categories) do - if categoryFrame.name == L["Triggers"] then + -- TODO: avoid this check entirely if triggers aren't translated? + if ww_stackingEquipEffects and categoryFrame.name == L["Triggers"] then for i, trigger in ipairs(ww_triggerTypes) do local triggerFrame = CreateFrame("Frame", "WW_" .. trigger, categoryFrame, "ww_triggerFrame") triggerFrame.position = i