Module:AbilityTable/ComplexRenderers: Difference between revisionsGive feedback
Add RenderBossDamageScale for the "bossdmgscale" list (with help from vergir-bot LLM) |
RenderSpiritScaling: list every scaling prop with card labels and {{Ss}}, per-prop upgrade notes (with help from vergir-bot LLM) |
||
| Line 410: | Line 410: | ||
end | end | ||
-- | -- ============================================================ | ||
-- | -- Spirit scaling helpers | ||
-- ============================================================ | |||
-- Spirit scaling entry of a prop, or nil. Scale is a single { Value, Type } | |||
-- or an array of them (e.g. a duration scaling with both Spirit and duration). | |||
local function spirit_scale(v) | |||
if type(v) ~= "table" then return nil end | |||
local scale = v["Scale"] | |||
if type(scale) ~= "table" then return nil end | |||
if scale[1] == nil then | |||
if scale["Type"] == "spirit" then return scale end | |||
return nil | |||
end | |||
for _, entry in ipairs(scale) do | |||
if type(entry) == "table" and entry["Type"] == "spirit" then return entry end | |||
end | |||
return nil | |||
end | |||
-- Non-zero Spirit scalings of one layer (base record or upgrade tier) as | |||
-- { key, value, multiply }, in card order; props not on the card last, by key. | |||
local function spirit_scalings(layer, labels) | |||
local out = {} | |||
for k, v in pairs(layer) do | |||
if k ~= "Upgrades" and tostring(k):sub(1, 1) ~= "_" then | |||
local s = spirit_scale(v) | |||
if s and type(s["Value"]) == "number" and s["Value"] ~= 0 then | |||
table.insert(out, { | |||
key = k, | |||
value = s["Value"], | |||
multiply = s["Multiply"] == true, | |||
}) | |||
end | end | ||
end | end | ||
end | end | ||
table.sort(out, function(a, b) | |||
local oa = labels[a.key] and labels[a.key].order or math.huge | |||
local ob = labels[b.key] and labels[b.key].order or math.huge | |||
if oa ~= ob then return oa < ob end | |||
return a.key < b.key | |||
end) | |||
return out | |||
end | |||
-- Formats a scaling value to 3 significant figures, as the ability cards do. | |||
local function format_spirit(v) | |||
return string.format("%.3g", v) | |||
end | |||
if | -- Compact {{Ss}} badge for the cell, expanded via the current frame like | ||
-- format_barrier; plain "×N" when there is no frame (module console). | |||
local function format_spirit_badge(v) | |||
local text = format_spirit(v) | |||
local frame = mw.getCurrentFrame() | |||
if frame then | |||
return frame:expandTemplate{ | |||
title = "Ss", | |||
args = { text, compact = "1", show_value = "1" }, | |||
} | |||
end | end | ||
return "×" .. text | |||
end | |||
-- "A", "A and B", "A, B and C". | |||
local function join_names(names) | |||
if #names <= 1 then return names[1] or "" end | |||
return table.concat(names, ", ", 1, #names - 1) .. " and " .. names[#names] | |||
end | |||
-- Renders Spirit Power scaling: one {{Ss}} badge per scaling prop, labelled from | |||
-- the card ("x0.55 (Base Damage)"; "Damage: Cost of Stay" when names collide; | |||
-- raw key when the card lacks it). Notes list upgrades per prop with running | |||
-- totals; Multiply upgrades multiply the current scaling, as the gadget does. | |||
function p.RenderSpiritScaling(ability, cardprops) | |||
local labels = cardprops or {} | |||
local base = spirit_scalings(ability, labels) | |||
local tiers = {} -- { tier = i, list = ... } in tier order | |||
local upgrades = ability["Upgrades"] | local upgrades = ability["Upgrades"] | ||
if type(upgrades) | if type(upgrades) == "table" then | ||
-- ipairs rather than #: mw.loadJsonData tables have no length. | |||
for i, tier in ipairs(upgrades) do | |||
if type(tier) == "table" then | |||
table.insert(tiers, { tier = i, list = spirit_scalings(tier, labels) }) | |||
end | |||
end | |||
end | |||
local | -- Props sharing a Name get their Title appended so they can be told apart. | ||
local keys_by_name = {} | |||
local function note_keys(list) | |||
for _, prop in ipairs(list) do | |||
local info = labels[prop.key] | |||
if info then | |||
keys_by_name[info.name] = keys_by_name[info.name] or {} | |||
keys_by_name[info.name][prop.key] = true | |||
end | |||
end | |||
end | |||
note_keys(base) | |||
for _, t in ipairs(tiers) do note_keys(t.list) end | |||
for | local function label_of(key) | ||
if | local info = labels[key] | ||
if not info then return key end | |||
local n = 0 | |||
for _ in pairs(keys_by_name[info.name] or {}) do n = n + 1 end | |||
if n > 1 and info.title then return info.name .. ": " .. info.title end | |||
return info.name | |||
end | |||
local cells = {} | |||
local running = {} -- prop key -> current total scaling | |||
if #base > 0 then | |||
local lines = {} | |||
for _, prop in ipairs(base) do | |||
table.insert(lines, format_spirit_badge(prop.value) .. " (" .. label_of(prop.key) .. ")") | |||
running[prop.key] = prop.value | |||
end | end | ||
cells["Spirit Scaling"] = table.concat(lines, "<br>") | |||
end | end | ||
if | local notes = {} | ||
for _, t in ipairs(tiers) do | |||
local i, list = t.tier, t.list | |||
local groups, group_order = {}, {} -- Multiply upgrades, grouped by multiplier | |||
for _, up in ipairs(list) do | |||
local label = label_of(up.key) | |||
local current = running[up.key] | |||
if up.multiply then | |||
local group = groups[up.value] | |||
if not group then | |||
group = { labels = {}, totals = {} } | |||
groups[up.value] = group | |||
table.insert(group_order, up.value) | |||
end | |||
table.insert(group.labels, label) | |||
if current then | |||
running[up.key] = current * up.value | |||
table.insert(group.totals, "×" .. format_spirit(running[up.key])) | |||
else | |||
table.insert(group.totals, "?") | |||
end | |||
elseif current then | |||
running[up.key] = current + up.value | |||
table.insert(notes, "T" .. i .. " upgrade adds +×" .. format_spirit(up.value) | |||
.. " " .. label .. " scaling (total ×" .. format_spirit(running[up.key]) .. ")") | |||
else | |||
running[up.key] = up.value | |||
table.insert(notes, "T" .. i .. " upgrade grants ×" .. format_spirit(up.value) | |||
.. " " .. label .. " scaling") | |||
end | |||
end | |||
for _, m in ipairs(group_order) do | |||
local group = groups[m] | |||
table.insert(notes, "T" .. i .. " upgrade multiplies " .. join_names(group.labels) | |||
.. " scaling by " .. format_spirit(m) | |||
.. " (total " .. table.concat(group.totals, ", ") .. ")") | |||
end | |||
end | end | ||
if #notes > 0 then cells["Notes"] = table.concat(notes, ". ") end | |||
return cells | return cells | ||
end | end | ||