Module:AbilityTable: Difference between revisions

Vergir (talk | contribs)
Add hero field to manual_entries; add DebuffAccuracy/TimeSlowDuration/LateCheckoutStun props; resolve manual entry heroes via name lookup (with help from vergir-bot LLM)
Vergir (talk | contribs)
Remove hero field from manual_entries; hero resolved automatically via name_lookup from AbilityCards (with help from vergir-bot LLM)
Line 27: Line 27:
-- Manually specified entries for abilities whose effects cannot be inferred from
-- Manually specified entries for abilities whose effects cannot be inferred from
-- data alone (e.g. engine-side CC with no matching data fields).
-- data alone (e.g. engine-side CC with no matching data fields).
-- The hero is resolved automatically from AbilityCards.json via the ability name.
-- Each entry requires:
-- Each entry requires:
--  hero    = "Hero Name"  (as it appears on the wiki, used for HeroIcon)
--  effects  = { "EffectName", ... }  (supports "Effect (TN)" for upgrade-only)
--  effects  = { "EffectName", ... }  (supports "Effect (TN)" for upgrade-only)
--  duration = <number or nil>        (nil renders as "—")
--  duration = <number or nil>        (nil renders as "—")
Line 34: Line 34:
     ["debuff"] = {
     ["debuff"] = {
         ["Combo"] = {
         ["Combo"] = {
            hero    = "Mo & Krill",
             effects  = { "Stun" },
             effects  = { "Stun" },
             duration = 2.4,
             duration = 2.4,
         },
         },
         ["Sand Blast"] = {
         ["Sand Blast"] = {
            hero    = "Mo & Krill",
             effects  = { "Disarm" },
             effects  = { "Disarm" },
             duration = 2.5,
             duration = 2.5,
         },
         },
         ["Spirit Lasso"] = {
         ["Spirit Lasso"] = {
            hero    = "Holliday",
             effects  = { "Stun" },
             effects  = { "Stun" },
             duration = 2.25,
             duration = 2.25,
Line 300: Line 297:
     TimeSlowDuration    = "Time Slow",
     TimeSlowDuration    = "Time Slow",
     LateCheckoutStun    = "Stun",
     LateCheckoutStun    = "Stun",
}
-- Duration fields for each CC prop (the field whose numeric value is the duration).
-- Props that are themselves duration fields map to themselves.
-- Props that are flags or percentages map to a separate duration field.
local debuff_prop_to_dur_field = {
    StunDuration        = "StunDuration",
    SleepDuration      = "SleepDuration",
    SilenceDuration    = "SilenceDuration",
    SilenceDebuff      = "SilenceDuration",
    PetrifyDuration    = "PetrifyDuration",
    HexDuration        = "HexDuration",
    ImmobilizeDuration  = "ImmobilizeDuration",
    LiftDuration        = "LiftDuration",
    SlowPercent        = "SlowDuration",
    HoldInPlaceDuration = "HoldInPlaceDuration",
    DebuffAccuracy      = "AbilityDuration",
    TimeSlowDuration    = "TimeSlowDuration",
    LateCheckoutStun    = "LateCheckoutStun",
}
}


Line 418: Line 396:


     -- AbilityDuration is only meaningful as a duration source when DebuffAccuracy is the
     -- AbilityDuration is only meaningful as a duration source when DebuffAccuracy is the
     -- sole CC prop (Call Bell) — otherwise it's too generic. Remove it unless that's the case.
     -- sole CC prop (Call Bell) — otherwise it's too generic.
     local sole_cc_is_accuracy = (effects_set["Inaccuracy"] and not effects_set["Slow"]
     local sole_cc_is_accuracy = (effects_set["Inaccuracy"] and not effects_set["Slow"]
         and not effects_set["Stun"] and not effects_set["Sleep"]
         and not effects_set["Stun"] and not effects_set["Sleep"]
Line 461: Line 439:


-- ============================================================
-- ============================================================
-- Hero lookup (ability key -> { heroName, abilityNum })
-- Hero lookup
-- Also builds a name-keyed lookup for manual entries.
--  _hero_lookup : ability key -> { heroName, abilityNum }
--   _name_lookup : ability name -> { heroName, abilityNum }
-- Both are built together from HeroData + AbilityCards.
-- _name_lookup is used to resolve heroes for manual_entries.
-- ============================================================
-- ============================================================


local _hero_lookup     = nil -- key  -> { heroName, abilityNum }
local _hero_lookup = nil
local _name_lookup     = nil -- name  -> { heroName, abilityNum }
local _name_lookup = nil


local function build_hero_lookup()
local function build_hero_lookup()
Line 494: Line 475:
                     if slot_num and type(ability) == "table" then
                     if slot_num and type(ability) == "table" then
                         local info = { heroName = hero_name, abilityNum = slot_num }
                         local info = { heroName = hero_name, abilityNum = slot_num }
                         if ability["Key"] then
                         if ability["Key"] then _hero_lookup[ability["Key"]] = info end
                            _hero_lookup[ability["Key"]] = info
                         if ability["Name"] then _name_lookup[ability["Name"]] = info end
                        end
                         if ability["Name"] then
                            _name_lookup[ability["Name"]] = info
                        end
                     end
                     end
                 end
                 end
Line 557: Line 534:
     end
     end


     -- Inject manual entries not already covered by prop-matching
     -- Inject manual entries not already covered by prop-matching.
    -- Hero is resolved via _name_lookup; if not found the row shows "—" in the Hero column.
     if stat_manual then
     if stat_manual then
         for name, entry in pairs(stat_manual) do
         for name, _ in pairs(stat_manual) do
             if not filtered_names[name] then
             if not filtered_names[name] then
                -- Look up hero and slot via the name-keyed lookup first,
                -- then fall back to the hero field on the entry.
                local info = name_lookup[name]
                 table.insert(filtered, {
                 table.insert(filtered, {
                     Name        = name,
                     Name        = name,
                     Key        = "__manual__",
                     Key        = "__manual__",
                     _manualInfo = info or { heroName = entry.hero, abilityNum = 9999 },
                     _manualInfo = name_lookup[name] or { abilityNum = 9999 },
                 })
                 })
             end
             end
Line 626: Line 601:
         local info = lookup[ability["Key"]] or ability._manualInfo
         local info = lookup[ability["Key"]] or ability._manualInfo


         local hero_cell, ability_cell
         local hero_cell
         if info and info.heroName then
         if info and info.heroName then
             hero_cell = frame:expandTemplate{ title = "HeroIcon", args = { info.heroName } }
             hero_cell = frame:expandTemplate{ title = "HeroIcon", args = { info.heroName } }
Line 632: Line 607:
             hero_cell = "—"
             hero_cell = "—"
         end
         end
         ability_cell = frame:expandTemplate{ title = "AbilityIcon", args = { ability["Name"] } }
         local ability_cell = frame:expandTemplate{ title = "AbilityIcon", args = { ability["Name"] } }


         local extra = get_cells(ability)
         local extra = get_cells(ability)
Line 650: Line 625:
                 local suffix = column_suffix[header] or ""
                 local suffix = column_suffix[header] or ""
                 content = (type(value) == "string" and value:sub(1,1) == "(")
                 content = (type(value) == "string" and value:sub(1,1) == "(")
                     and value
                     and value or (value .. suffix)
                    or (value .. suffix)
             else
             else
                 content = "—"
                 content = "—"