DopingControl v0.6.1
This commit is contained in:
+114
@@ -0,0 +1,114 @@
|
||||
-- DopingControl scan/resist.lua
|
||||
-- Pure resistance-reconstruction math: turn item TOOLTIP lines into a
|
||||
-- per-school sum, and look up a race's innate bonus. Mirrors scan/hit.lua's
|
||||
-- pure half (ParseHitLine/SumGear) one level down -- the constants live in
|
||||
-- data/resist.lua, this file only turns them into behavior.
|
||||
--
|
||||
-- NO WoW-glue function lives here on purpose: unlike scan/hit.lua/scan/
|
||||
-- gear.lua/scan/aura.lua, this module never calls SetInventoryItem itself.
|
||||
-- The RESIST tab's numbers are reconstructed from tooltip lines
|
||||
-- scan/hit.lua's item scan ALREADY fetched (see that file's itemHit()) --
|
||||
-- one more table walk over data already in hand, not a second tooltip
|
||||
-- operation per item. That is the entire point of hanging resistance
|
||||
-- reconstruction off the HIT tab's existing per-item cache instead of
|
||||
-- building an independent RESIST scan pass: 26 players x 19 slots would be
|
||||
-- ~500 extra SetInventoryItem calls per scan, and scan/hit.lua already pays
|
||||
-- that cost once per unique item.
|
||||
--
|
||||
-- Pure Lua 5.0, no WoW API, dofile-loadable offline: everything here is
|
||||
-- offline-tested (test_resist.lua).
|
||||
|
||||
DopingControl = DopingControl or {}
|
||||
local DC = DopingControl
|
||||
|
||||
DC_Resist = DC_Resist or {}
|
||||
local R = DC_Resist
|
||||
|
||||
-- ParseResistLine(text) -> kind, value | nil
|
||||
-- kind : a DC.RESIST_SCHOOLS name ("Fire", "Nature", ...) or "all"
|
||||
-- value : the flat resistance amount as a number
|
||||
-- Returns nil (a single value) when no pattern matches -- an unrecognized
|
||||
-- phrasing is ignored, never guessed at (same contract as
|
||||
-- DC_Hit.ParseHitLine).
|
||||
function R.ParseResistLine(text)
|
||||
if type(text) ~= "string" then
|
||||
return nil
|
||||
end
|
||||
local pats = DC.RESIST_PATTERNS
|
||||
if type(pats) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
local n = table.getn(pats)
|
||||
for i = 1, n do
|
||||
local e = pats[i]
|
||||
local _, _, cap = string.find(text, e.pattern)
|
||||
if cap then
|
||||
local v = tonumber(cap)
|
||||
if v then
|
||||
return e.kind, v
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- SumLines(lines) -> sum
|
||||
-- lines : the FULL tooltip line array of ONE item, element 1 = item name
|
||||
-- (same convention as scan/hit.lua's itemHit -- line 1 is never
|
||||
-- a stat line, so the scan starts at 2; a caller that already
|
||||
-- stripped the name may safely pass an array starting at the
|
||||
-- real first stat line too, since no genuine item name matches
|
||||
-- "^%+%d+ <School> Resistance" or "^Equip: %+%d+ All
|
||||
-- Resistances" in the first place).
|
||||
-- sum : { [UnitResistance school index] = total } -- ONLY schools
|
||||
-- that actually appeared; a plain item with no resistance stat
|
||||
-- returns {} (empty, not nil) -- an empty sum is a real "this
|
||||
-- item carries no resistance", exactly like SumGear's zero.
|
||||
-- The "All Resistances" trap this table exists to close: a naive parser
|
||||
-- keyed only on the five single-school patterns would silently skip
|
||||
-- "Equip: +8 All Resistances." and undercount every one of the five
|
||||
-- columns by that amount. Handled here by fanning ONE matched line out
|
||||
-- over every entry of DC.RESIST_SCHOOLS.
|
||||
function R.SumLines(lines)
|
||||
local sum = {}
|
||||
lines = lines or {}
|
||||
local n = table.getn(lines)
|
||||
for i = 2, n do
|
||||
local kind, v = R.ParseResistLine(lines[i])
|
||||
if kind then
|
||||
if kind == "all" then
|
||||
local schools = DC.RESIST_SCHOOLS or {}
|
||||
for s = 1, table.getn(schools) do
|
||||
local school = schools[s].school
|
||||
sum[school] = (sum[school] or 0) + v
|
||||
end
|
||||
else
|
||||
local num = DC.RESIST_SCHOOL_NUM and DC.RESIST_SCHOOL_NUM[kind]
|
||||
if num then
|
||||
sum[num] = (sum[num] or 0) + v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return sum
|
||||
end
|
||||
|
||||
-- RaceBonus(race) -> { [UnitResistance school index] = bonus }
|
||||
-- ALWAYS returns a table (empty for "no bonus", an unrecognized race
|
||||
-- token/display name, or nil input) so callers can fold it onto a gear sum
|
||||
-- without a nil check. The returned table is a FRESH COPY, never the
|
||||
-- shared DC.RACE_RESIST entry itself -- DC.RACE_RESIST aliases two
|
||||
-- spellings of the same race to ONE table object, so handing that
|
||||
-- reference out would let a caller's in-place addition (E.AssembleResists
|
||||
-- folds this straight onto the gear sum) corrupt the shared constant for
|
||||
-- every future lookup of that race.
|
||||
function R.RaceBonus(race)
|
||||
local out = {}
|
||||
local tbl = race and DC.RACE_RESIST and DC.RACE_RESIST[race]
|
||||
if tbl then
|
||||
for school, v in pairs(tbl) do
|
||||
out[school] = v
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
Reference in New Issue
Block a user