Module:AbilityTable: Difference between revisions

Vergir (talk | contribs)
Register "bossdmgscale" column (Damage to Objectives) (with help from vergir-bot LLM)
Per-prop Spirit scaling: pass card prop labels to renderers (with help from vergir-bot LLM)
Line 8: Line 8:
local p = {}
local p = {}


-- get_cells(ability, cardprops) -> { [column header] = cell text, Notes = ... }; most renderers ignore cardprops
local extra_columns = {
local extra_columns = {
     ["barrier"] = {
     ["barrier"] = {
Line 88: Line 89:


-- "Ability View" is a main-record + any relevant sub-ability records.
-- "Ability View" is a main-record + any relevant sub-ability records.
-- Views also carry "cardprops" (see card_prop_labels), kept outside the record so membership matching never sees them.
-- ============================================================
-- ============================================================


local _views = nil  -- card key -> { view = record, heroName = ..., abilityNum = ... }
-- Card prop labels: key -> { name, title, order }, read from the card in AbilityCards.json.
-- Built per card, since a key like "Damage" is labelled differently on different cards.
local function card_prop_labels(card)
    local labels, n = {}, 0
 
    local function walk(node)
        if type(node) ~= "table" then return end
        local key, name = node["Key"], node["Name"]
        if type(key) == "string" and type(name) == "string" and not labels[key] then
            n = n + 1
            local title = node["Title"]
            if type(title) == "string" then
                title = title:gsub(":%s*$", "")
            else
                title = nil
            end
            labels[key] = { name = name, title = title, order = n }
        end
        if node[1] ~= nil then
            for _, child in ipairs(node) do walk(child) end
        else
            -- Keyed sections (Range, Move, ...): { PropKey = { Name = ..., Value = ... } }
            local keyed = {}
            for k, v in pairs(node) do
                if type(k) == "string" and type(v) == "table" and v["Key"] == nil
                    and type(v["Name"]) == "string" and not labels[k]
                then
                    table.insert(keyed, k)
                end
            end
            table.sort(keyed)
            for _, k in ipairs(keyed) do
                n = n + 1
                labels[k] = { name = node[k]["Name"], order = n }
            end
            -- Main props before Alt props, then anything else in key order.
            if node["Main"] ~= nil then walk(node["Main"]) end
            if node["Alt"]  ~= nil then walk(node["Alt"])  end
            local rest = {}
            for k, v in pairs(node) do
                if k ~= "Main" and k ~= "Alt" and k ~= "Upgrades" and type(v) == "table" then
                    table.insert(rest, k)
                end
            end
            table.sort(rest, function(a, b) return tostring(a) < tostring(b) end)
            for _, k in ipairs(rest) do walk(node[k]) end
        end
    end
 
    for _, section in ipairs({ "Info1", "Info2", "Info3" }) do
        walk(card[section])
    end
    local rest = {}
    for k, v in pairs(card) do
        if type(v) == "table" and k ~= "Upgrades"
            and k ~= "Info1" and k ~= "Info2" and k ~= "Info3"
        then
            table.insert(rest, k)
        end
    end
    table.sort(rest, function(a, b) return tostring(a) < tostring(b) end)
    for _, k in ipairs(rest) do walk(card[k]) end
 
    -- Header attributes are stored on the card without a Name.
    local header_attrs = {
        { "AbilityCastRange",            "Cast Range" },
        { "Radius",                      "Radius" },
        { "AbilityDuration",            "Duration" },
        { "AbilityChannelTime",          "Channel Time" },
        { "AbilityCooldown",            "Cooldown" },
        { "AbilityCharges",              "Charges" },
        { "AbilityCooldownBetweenCharge", "Charge Cooldown" },
    }
    for _, attr in ipairs(header_attrs) do
        if not labels[attr[1]] then
            n = n + 1
            labels[attr[1]] = { name = attr[2], order = n }
        end
    end
 
    return labels
end
 
local _views = nil  -- card key -> { view = record, heroName = ..., abilityNum = ..., cardprops = ... }
local _order = nil  -- array of card keys, sorted by hero then slot
local _order = nil  -- array of card keys, sorted by hero then slot


Line 121: Line 206:
                     local key = type(ability) == "table" and ability["Key"] or nil
                     local key = type(ability) == "table" and ability["Key"] or nil
                     if slot_num and key and ability_data[key] then
                     if slot_num and key and ability_data[key] then
                         card_of[key] = { heroName = hero_name, abilityNum = slot_num }
                         card_of[key] = { heroName = hero_name, abilityNum = slot_num, card = ability }
                     end
                     end
                 end
                 end
Line 151: Line 236:
         for k, v in pairs(ability_data[key]) do view[k] = v end
         for k, v in pairs(ability_data[key]) do view[k] = v end
         view["_subabilities"] = subs[key]
         view["_subabilities"] = subs[key]
         _views[key] = { view = view, heroName = info.heroName, abilityNum = info.abilityNum }
         _views[key] = {
            view       = view,
            heroName   = info.heroName,
            abilityNum = info.abilityNum,
            cardprops  = card_prop_labels(info.card),
        }
         table.insert(_order, key)
         table.insert(_order, key)
     end
     end
Line 272: Line 362:
                 hero_abilities[hero] = {}
                 hero_abilities[hero] = {}
             end
             end
             table.insert(hero_abilities[hero], views[key].view)
             table.insert(hero_abilities[hero], views[key])
         end
         end


Line 279: Line 369:
             local hero_cell = frame:expandTemplate{ title = "HeroIcon", args = { hero } }
             local hero_cell = frame:expandTemplate{ title = "HeroIcon", args = { hero } }
             local ability_parts = {}
             local ability_parts = {}
             for _, ability in ipairs(hero_abilities[hero]) do
             for _, entry in ipairs(hero_abilities[hero]) do
                local ability = entry.view
                 local name = ability["Name"]
                 local name = ability["Name"]
                 local ability_cell = frame:expandTemplate{ title = "AbilityIcon", args = { name } }
                 local ability_cell = frame:expandTemplate{ title = "AbilityIcon", args = { name } }


                 local extra = get_cells(ability)
                 local extra = get_cells(ability, entry.cardprops)
                 enrich_notes_compact(extra, stat_notes and stat_notes[name])
                 enrich_notes_compact(extra, stat_notes and stat_notes[name])


Line 349: Line 440:
         }
         }


         local extra = get_cells(ability)
         local extra = get_cells(ability, entry.cardprops)
         enrich_notes_full(extra, stat_notes and stat_notes[ability["Name"]])
         enrich_notes_full(extra, stat_notes and stat_notes[ability["Name"]])