Module:AbilityTable/ComplexRenderers: Difference between revisions

Vergir (talk | contribs)
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


-- Renders Spirit Power scaling.
-- ============================================================
-- Shows the Scale.Value for abilities whose Scale.Type is "spirit".
-- Spirit scaling helpers
function p.RenderSpiritScaling(ability)
-- ============================================================
    local base_scale = nil
    local base_prop = nil


    -- Find base Spirit scaling
-- Spirit scaling entry of a prop, or nil. Scale is a single { Value, Type }
    for k, v in pairs(ability) do
-- or an array of them (e.g. a duration scaling with both Spirit and duration).
        if k ~= "Upgrades" and type(v) == "table" then
local function spirit_scale(v)
            local scale = v["Scale"]
    if type(v) ~= "table" then return nil end
            if type(scale) == "table"
    local scale = v["Scale"]
              and scale["Type"] == "spirit"
    if type(scale) ~= "table" then return nil end
              and type(scale["Value"]) == "number"
    if scale[1] == nil then
              and scale["Value"] ~= 0 then
        if scale["Type"] == "spirit" then return scale end
                 base_scale = scale["Value"]
        return nil
                base_prop = k
    end
                 break
    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


     local cells = {}
-- 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 base_scale then
-- Compact {{Ss}} badge for the cell, expanded via the current frame like
         cells["Spirit Scaling"] = "×" .. base_scale
-- 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) ~= "table" then return cells end
     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 notes = {}
    -- 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 i, tier in ipairs(upgrades) do
     local function label_of(key)
         if type(tier) == "table" then
        local info = labels[key]
            local upgrade_scale = nil
        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


            for k, v in pairs(tier) do
    local cells  = {}
                if type(v) == "table" then
    local running = {}  -- prop key -> current total scaling
                    local scale = v["Scale"]
                    if type(scale) == "table"
                      and scale["Type"] == "spirit"
                      and type(scale["Value"]) == "number"
                      and scale["Value"] ~= 0 then
                        upgrade_scale = scale["Value"]
                        break
                    end
                end
            end


            if upgrade_scale then
    if #base > 0 then
                table.insert(notes,
        local lines = {}
                    "on T" .. i .. " gets +×" .. upgrade_scale .. " Spirit scaling")
        for _, prop in ipairs(base) do
             end
            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 #notes > 0 then
     local notes = {}
        cells["Notes"] = table.concat(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