Module:GameData: Difference between revisions

From The Deadlock Wiki
Jump to navigation Jump to search
Remove Upgrades skip in find_value so abilities gaining charges via upgrades are included (with help from vergir-bot LLM)
get_entities now matches props as values too, enabling Scale.Type-based filtering (with help from vergir-bot LLM)
Line 25: Line 25:
end
end


-- Recursively searches a record for a given key at any nesting level,
-- Recursively searches a record for a match against prop, which may be:
-- including inside the Upgrades array. This means abilities or items that
--   - a key name: matches if the key exists with a non-zero/non-empty value
-- only gain a property via an upgrade tier will still be matched.
--  - a plain value: matches if the string appears as a value anywhere in the record
-- @param  record  table   the data record to search
-- Returns true if a match is found, false otherwise.
-- @param  key    string the internal property name to look for
local function record_matches_prop(record, prop)
-- @return          any    the value if found, nil otherwise
local function find_value(record, key)
     for k, v in pairs(record) do
     for k, v in pairs(record) do
         if k == key then
        -- Key match: property name exists with a meaningful value
             return v
         if k == prop then
         elseif type(v) == "table" then
             if v ~= nil and v ~= 0 and v ~= "" and v ~= "0" and v ~= "0m" then
             local found = find_value(v, key)
                return true
             if found ~= nil then return found end
            end
        end
         if type(v) == "table" then
             if record_matches_prop(v, prop) then return true end
        elseif type(v) == "string" then
            -- Value match: prop string appears as a value (e.g. Scale.Type = "melee")
             if v == prop then return true end
         end
         end
     end
     end
     return nil
     return false
end
end


-- Returns all active entities from a dataset that have a non-nil, non-zero,
-- Returns all active entities from a dataset that match at least one of the
-- non-empty value for at least one of the given internal property keys.
-- given properties. A property may be matched either as a key name (the
-- property exists with a non-zero value) or as a plain string value anywhere
-- in the record (e.g. "melee" matching Scale.Type = "melee").
-- @param  dataset    string  one of the GameData.Dataset constants
-- @param  dataset    string  one of the GameData.Dataset constants
-- @param  properties  table  array of internal property name strings
-- @param  properties  table  array of property strings
-- @return              table  array of matching entity records
-- @return              table  array of matching entity records
function p.get_entities(dataset, properties)
function p.get_entities(dataset, properties)
Line 55: Line 61:
         if is_active(record) then
         if is_active(record) then
             for _, prop in ipairs(properties) do
             for _, prop in ipairs(properties) do
                 local value = find_value(record, prop)
                 if record_matches_prop(record, prop) then
                if value ~= nil and value ~= 0 and value ~= "" and value ~= "0" and value ~= "0m" then
                     table.insert(results, record)
                     table.insert(results, record)
                     break
                     break

Revision as of 01:11, 11 May 2026

Documentation for this module may be created at Module:GameData/doc

-- Module:GameData
-- Provides generic access to game data files, with consistent active-entity filtering.
-- Used by ItemTables, and intended for future AbilityTables, HeroTables, etc.

local p = {}

-- Dataset descriptors. Values are the data file paths passed to mw.loadJsonData.
-- Callers should use these constants rather than raw strings.
p.Dataset = {
    ITEMS     = "Data:ItemData.json",
    ABILITIES = "Data:AbilityData.json",
    HEROES    = "Data:HeroData.json",
}

-- Returns true if a record represents an active, usable entity.
-- Applies consistently across all datasets:
--   - IsDisabled must not be true
--   - Name must not be nil
--   - IsSelectable, if present, must not be false
local function is_active(record)
    if record["IsDisabled"] == true then return false end
    if record["Name"] == nil then return false end
    if record["IsSelectable"] ~= nil and record["IsSelectable"] == false then return false end
    return true
end

-- Recursively searches a record for a match against prop, which may be:
--   - a key name: matches if the key exists with a non-zero/non-empty value
--   - a plain value: matches if the string appears as a value anywhere in the record
-- Returns true if a match is found, false otherwise.
local function record_matches_prop(record, prop)
    for k, v in pairs(record) do
        -- Key match: property name exists with a meaningful value
        if k == prop then
            if v ~= nil and v ~= 0 and v ~= "" and v ~= "0" and v ~= "0m" then
                return true
            end
        end
        if type(v) == "table" then
            if record_matches_prop(v, prop) then return true end
        elseif type(v) == "string" then
            -- Value match: prop string appears as a value (e.g. Scale.Type = "melee")
            if v == prop then return true end
        end
    end
    return false
end

-- Returns all active entities from a dataset that match at least one of the
-- given properties. A property may be matched either as a key name (the
-- property exists with a non-zero value) or as a plain string value anywhere
-- in the record (e.g. "melee" matching Scale.Type = "melee").
-- @param   dataset     string  one of the GameData.Dataset constants
-- @param   properties  table   array of property strings
-- @return              table   array of matching entity records
function p.get_entities(dataset, properties)
    local data = mw.loadJsonData(dataset)
    local results = {}

    for _, record in pairs(data) do
        if is_active(record) then
            for _, prop in ipairs(properties) do
                if record_matches_prop(record, prop) then
                    table.insert(results, record)
                    break
                end
            end
        end
    end

    return results
end

return p