Module:AbilityTable: Difference between revisionsGive feedback
Jump to navigation
Jump to search
mNo edit summary |
Add moveslow and dashslow stats with Move Slow % and Dash Slow % columns and upgrade notes (with help from vergir-bot LLM) |
||
| Line 19: | Line 19: | ||
-- can also just list abilities if they don't have a reusable property | -- can also just list abilities if they don't have a reusable property | ||
"Hotel Guest", "Life Drain", "Combo", "Light Eater", "Spirit Lasso", "Card Trick" | "Hotel Guest", "Life Drain", "Combo", "Light Eater", "Spirit Lasso", "Card Trick" | ||
}, | |||
["moveslow"] = { "SlowPercent", "EnemySlowPct", "MoveSlowPercent" }, | |||
["dashslow"] = { | |||
"GroundDashReductionPercent", "MaxGroundDashReductionPercent", | |||
"MoveSpeedAndDashSlowPct", "EnemyDashSlowPercent", | |||
}, | }, | ||
} | } | ||
| Line 55: | Line 60: | ||
["debuffresist"] = { | ["debuffresist"] = { | ||
"Bookwyrm", -- has debuffduration for some reason | "Bookwyrm", -- has debuffduration for some reason | ||
"Itani Lo Sahn", -- has | "Itani Lo Sahn", -- has debuffduration but does not get reduced | ||
"Slam Fire", -- has debuffduration for some reason | "Slam Fire", -- has debuffduration for some reason | ||
"Splatter", -- has SlowPercent but no duration to shave off. | "Splatter", -- has SlowPercent but no duration to shave off. | ||
| Line 93: | Line 98: | ||
end | end | ||
return nil | return nil | ||
end | |||
-- Finds the first non-zero value for any of the given fields, checking base | |||
-- then upgrades in order. Returns field, tier (nil=base, N=upgrade), abs value. | |||
local function find_first_value(ability, fields) | |||
for _, field in ipairs(fields) do | |||
local v = num_val(ability[field]) | |||
if v and v ~= 0 then return field, nil, math.abs(v) end | |||
end | |||
local upgrades = ability["Upgrades"] | |||
if type(upgrades) == "table" then | |||
for i, tier in ipairs(upgrades) do | |||
if type(tier) == "table" then | |||
for _, field in ipairs(fields) do | |||
local v = num_val(tier[field]) | |||
if v and v ~= 0 then return field, i, math.abs(v) end | |||
end | |||
end | |||
end | |||
end | |||
return nil, nil, nil | |||
end | end | ||
| Line 290: | Line 316: | ||
if #notes > 0 then cells["Notes"] = table.concat(notes, " ") end | if #notes > 0 then cells["Notes"] = table.concat(notes, " ") end | ||
return cells | return cells | ||
end | |||
-- Generic renderer for a single percentage stat (move slow, dash slow). | |||
-- col_name: the column header string (e.g. "Move Slow") | |||
-- fields: ordered list of property names to check (first non-zero wins for display) | |||
-- Upgrade deltas are additive; notes track totals. | |||
local function pct_stat_cells(ability, col_name, fields) | |||
local cells = {} | |||
local notes = {} | |||
local first_field, first_tier, first_val = find_first_value(ability, fields) | |||
if not first_field then return cells end | |||
local cell_str = tostring(first_val) .. "%" | |||
if first_tier then cell_str = cell_str .. " (T" .. first_tier .. ")" end | |||
cells[col_name] = cell_str | |||
-- Scan upgrades for changes after the first value. | |||
local upgrades = ability["Upgrades"] | |||
if type(upgrades) == "table" then | |||
local running = first_val | |||
local seen_first = (first_tier == nil) | |||
for i, tier in ipairs(upgrades) do | |||
if type(tier) == "table" then | |||
if first_tier == i then | |||
seen_first = true | |||
else | |||
-- Check if any of our fields has a delta in this tier | |||
local delta = nil | |||
for _, field in ipairs(fields) do | |||
local v = num_val(tier[field]) | |||
if v and v ~= 0 then delta = math.abs(v); break end | |||
end | |||
if seen_first and delta then | |||
local total = running + delta | |||
table.insert(notes, "T" .. i .. " upgrade increases " | |||
.. col_name:lower() .. " by " .. delta | |||
.. "% (total " .. total .. "%).") | |||
running = total | |||
end | |||
end | |||
end | |||
end | |||
end | |||
if #notes > 0 then cells["Notes"] = table.concat(notes, " ") end | |||
return cells | |||
end | |||
local function moveslow_cells(ability) | |||
return pct_stat_cells(ability, "Move Slow", { "SlowPercent", "EnemySlowPct", "MoveSlowPercent" }) | |||
end | |||
local function dashslow_cells(ability) | |||
return pct_stat_cells(ability, "Dash Slow", { | |||
"GroundDashReductionPercent", "MaxGroundDashReductionPercent", | |||
"MoveSpeedAndDashSlowPct", "EnemyDashSlowPercent", | |||
}) | |||
end | end | ||
| Line 304: | Line 389: | ||
headers = { "Heal Reduction", "Duration", "Notes" }, | headers = { "Heal Reduction", "Duration", "Notes" }, | ||
get_cells = healreduce_cells, | get_cells = healreduce_cells, | ||
}, | |||
["moveslow"] = { | |||
headers = { "Move Slow", "Notes" }, | |||
get_cells = moveslow_cells, | |||
}, | |||
["dashslow"] = { | |||
headers = { "Dash Slow", "Notes" }, | |||
get_cells = dashslow_cells, | |||
}, | }, | ||
} | } | ||
| Line 431: | Line 524: | ||
-- Compact mode: <ul> with one <li> per hero. | -- Compact mode: <ul> with one <li> per hero. | ||
-- Each item: "{HeroIcon}: {AbilityIcon} (note), {AbilityIcon}, ..." | -- Each item: "{HeroIcon}: {AbilityIcon} (note), {AbilityIcon}, ..." | ||
local hero_order = {} | local hero_order = {} | ||
local hero_abilities = {} | local hero_abilities = {} | ||
for _, ability in ipairs(filtered) do | for _, ability in ipairs(filtered) do | ||
local info = key_lookup[ability["Key"]] | local info = key_lookup[ability["Key"]] | ||