Module:AbilityTable: Difference between revisions

LVL (talk | contribs)
add support for collapsible tables
Extract list membership into public p.is_member() as the shared source of truth (exclusions + special rules); filter_abilities now delegates to it. Behavior-identical for tables (with help from vergir-bot LLM)
Line 69: Line 69:
         extra["Notes"] = extra["Notes"] and (extra["Notes"] .. "; " .. human_note) or human_note
         extra["Notes"] = extra["Notes"] and (extra["Notes"] .. "; " .. human_note) or human_note
     end
     end
end
-- ============================================================
-- Membership
-- Shared source of truth for "is ability X a member of list Y".
-- Also consumed by Module:AbilityInteractions to decide which
-- interaction icons to show on ability cards.
-- ============================================================
-- Memoized name-exclusion set per list (from Lists.exclude_abilities).
local _excluded = {}
local function excluded_set(stat)
    if _excluded[stat] then return _excluded[stat] end
    local set = {}
    for _, name in ipairs(Lists.exclude_abilities[stat] or {}) do
        set[name] = true
    end
    _excluded[stat] = set
    return set
end
-- Per-list rules that can't be expressed as prop lists or exclusions.
-- Returns true to keep the ability, false to drop it.
local function special_ok(stat, record, ability_num)
    if stat == "dispelmagic" and ability_num == 4 then return false end
    return true
end
-- Public: does an ability record belong to list `stat`?
--  record      an entry from Data:AbilityData.json
--  ability_num  the ability's slot (1-4), used by special rules
function p.is_member(stat, record, ability_num)
    local props = Lists.lists[stat]
    if not props then return false end
    local name = record["Name"]
    if name and excluded_set(stat)[name] then return false end
    if not special_ok(stat, record, ability_num) then return false end
    return GameData.entity_matches(record, props)
end
end


Line 76: Line 114:


local function filter_abilities(stat, abilities, key_lookup)
local function filter_abilities(stat, abilities, key_lookup)
    local excluded = {}
    if Lists.exclude_abilities[stat] then
        for _, name in ipairs(Lists.exclude_abilities[stat]) do
            excluded[name] = true
        end
    end
     local result = {}
     local result = {}
     for _, ability in ipairs(abilities) do
     for _, ability in ipairs(abilities) do
         local key  = ability["Key"]
         local info = ability["Key"] and key_lookup[ability["Key"]]
        local info = key and key_lookup[key]
        if info and p.is_member(stat, ability, info.abilityNum) then
        if info and not excluded[ability["Name"]] then
             table.insert(result, ability)
            local skip = false
            if stat == "dispelmagic" and info.abilityNum == 4 then
                skip = true
            end
             if not skip then
                table.insert(result, ability)
            end
         end
         end
     end
     end