Editing Module:GameDataGive feedback
Jump to navigation
Jump to search
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
| Latest revision | Your text | ||
| Line 1: | Line 1: | ||
-- Module:GameData | |||
-- Provides generic access to game data files | -- Provides generic access to game data files, with consistent active-entity filtering. | ||
-- Used by ItemTables, and intended for future AbilityTables, HeroTables, etc. | |||
local p = {} | local p = {} | ||
| Line 10: | Line 11: | ||
ABILITIES = "Data:AbilityData.json", | ABILITIES = "Data:AbilityData.json", | ||
HEROES = "Data:HeroData.json", | HEROES = "Data:HeroData.json", | ||
} | } | ||
-- Returns true if a record represents an active, usable entity. | -- Returns true if a record represents an active, usable entity. | ||
| Line 24: | Line 18: | ||
-- - Name must not be nil | -- - Name must not be nil | ||
-- - IsSelectable, if present, must not be false | -- - IsSelectable, if present, must not be false | ||
local function is_active(record) | local function is_active(record) | ||
if record["IsDisabled"] == true then return false end | if record["IsDisabled"] == true then return false end | ||
| Line 38: | Line 29: | ||
-- - a plain value: matches if the string appears as a value anywhere in the record | -- - a plain value: matches if the string appears as a value anywhere in the record | ||
-- Returns true if a match is found, false otherwise. | -- Returns true if a match is found, false otherwise. | ||
local function record_matches_prop(record, prop) | local function record_matches_prop(record, prop) | ||
for k, v in pairs(record) do | for k, v in pairs(record) do | ||
-- Key match: property name exists with a meaningful value | -- Key match: property name exists with a meaningful value | ||
if k == prop then | if k == prop then | ||
if type(v) == "table" then | if type(v) == "table" then v = v["Value"] end | ||
if v ~= nil and v ~= 0 and v ~= "" and v ~= "0" and v ~= "0m" then | if v ~= nil and v ~= 0 and v ~= "" and v ~= "0" and v ~= "0m" then | ||
return true | return true | ||
end | end | ||
end | end | ||
if type(v) == "table" and k ~= " | if type(v) == "table" and k ~= "AutoRegisterModifierValueFromAbilityPropertyName" then | ||
if record_matches_prop(v, prop) then return true end | if record_matches_prop(v, prop) then return true end | ||
elseif type(v) == "string" then | elseif type(v) == "string" then | ||
-- Value match: prop string appears as a value (e.g. Scale.Type = "melee") | -- Value match: prop string appears as a value (e.g. Scale.Type = "melee") | ||
if v == prop then return true end | if v == prop then return true end | ||
end | end | ||
end | end | ||
| Line 186: | Line 49: | ||
-- Returns all active entities from a dataset that match at least one of the | -- Returns all active entities from a dataset that match at least one of the | ||
-- given properties. A property may be a key name (the property exists with a | -- 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 property strings | -- @param properties table array of property strings | ||
| Line 198: | Line 60: | ||
for _, record in pairs(data) do | for _, record in pairs(data) do | ||
if is_active(record) | 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 | ||
end | end | ||
| Line 211: | Line 78: | ||
-- Returns raw values for use in templates and expressions. | -- Returns raw values for use in templates and expressions. | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Lazy-loaded data caches | |||
local _ability_data, _item_data, _hero_data, _resource_lookup | |||
local function load_ability_data() | |||
if not _ability_data then _ability_data = mw.loadJsonData(p.Dataset.ABILITIES) end | |||
return _ability_data | |||
end | |||
local function load_item_data() | |||
if not _item_data then _item_data = mw.loadJsonData(p.Dataset.ITEMS) end | |||
return _item_data | |||
end | |||
local function load_hero_data() | |||
if not _hero_data then _hero_data = mw.loadJsonData(p.Dataset.HEROES) end | |||
return _hero_data | |||
end | |||
local function load_resource_lookup() | |||
if not _resource_lookup then _resource_lookup = mw.loadJsonData("Data:ResourceLookup.json") end | |||
return _resource_lookup | |||
end | |||
-- Find an entity by display name or internal key. | -- Find an entity by display name or internal key. | ||
-- Uses ResourceLookup type field to go directly to the right dataset. | -- Uses ResourceLookup type field to go directly to the right dataset. | ||
-- Returns (entity_record, type_string | -- Returns (entity_record, type_string) or (nil, nil). | ||
local function find_entity(identifier) | local function find_entity(identifier) | ||
local resource = | local resource = load_resource_lookup()[identifier:lower()] | ||
if resource then | if resource then | ||
local data | local data | ||
if resource.type == "ability" then | if resource.type == "ability" then | ||
data = | data = load_ability_data() | ||
elseif resource.type == "hero" then | elseif resource.type == "hero" then | ||
data = | data = load_hero_data() | ||
elseif resource.type == "item" then | elseif resource.type == "item" then | ||
data = | data = load_item_data() | ||
end | end | ||
if data and data[resource.key] then | if data and data[resource.key] then | ||
return data[resource.key], resource.type | return data[resource.key], resource.type | ||
end | end | ||
end | end | ||
| Line 233: | Line 120: | ||
-- Fallback: try as direct internal key | -- Fallback: try as direct internal key | ||
local datasets = { | local datasets = { | ||
{ | { load_ability_data, "ability" }, | ||
{ | { load_hero_data, "hero" }, | ||
{ | { load_item_data, "item" }, | ||
} | } | ||
for _, ds in ipairs(datasets) do | for _, ds in ipairs(datasets) do | ||
local data = | local data = ds[1]() | ||
if data[identifier] then return data[identifier], ds[2] | if data[identifier] then return data[identifier], ds[2] end | ||
end | end | ||
return | return nil, nil | ||
end | end | ||
-- Traverse a table using dot notation, unwrap tables with a .Value field | -- Traverse a table using dot notation, unwrap tables with a .Value field | ||
local function resolve_prop(tbl, prop) | local function resolve_prop(tbl, prop) | ||
if not prop or prop == "" then return nil end | if not prop or prop == "" then return nil end | ||
| Line 252: | Line 138: | ||
for segment in string.gmatch(prop, "[^%.]+") do | for segment in string.gmatch(prop, "[^%.]+") do | ||
if type(element) ~= "table" then return nil end | if type(element) ~= "table" then return nil end | ||
element = element[segment] | |||
if element == nil then return nil end | if element == nil then return nil end | ||
end | end | ||
| Line 266: | Line 147: | ||
end | end | ||
-- {{#invoke:GameData|get_prop|ENTITY_NAME|PROPERTY}} | |||
-- Finds entity via ResourceLookup, returns the raw value (no formatting). | |||
-- Supports dot notation for nested properties (e.g. "Scale.Value"). | |||
-- Tables with a .Value field are automatically unwrapped. | |||
-- | |||
-- | |||
-- | |||
function p.get_prop(frame) | function p.get_prop(frame) | ||
local | local name = frame.args[1] | ||
local | local prop = frame.args[2] | ||
if not name or not prop then return "" end | |||
if not | |||
local entity, etype | local entity, etype = find_entity(name) | ||
if not entity then | if not entity then | ||
return '<span style="color:red;">Entity not found: ' .. name .. '</span>' | return '<span style="color:red;">Entity not found: ' .. name .. '</span>' | ||
end | end | ||
local result = resolve_prop(entity, prop) | local result = resolve_prop(entity, prop) | ||
if result ~= nil then return result end | if result ~= nil then return result end | ||
if entity.Weapon then | |||
result = resolve_prop(entity.Weapon, prop) | |||
if result ~= nil then return result end | |||
end | |||
return '<span style="color:red;">Prop not found: ' .. name .. '/' .. prop .. '</span>' | return '<span style="color:red;">Prop not found: ' .. name .. '/' .. prop .. '</span>' | ||