Editing Module:Infobox itemGive feedback
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 4: | Line 4: | ||
local data = mw.loadJsonData("Data:ItemCards.json") | local data = mw.loadJsonData("Data:ItemCards.json") | ||
local stat_links = mw.loadJsonData("Data:StatLinks.json") | local stat_links = mw.loadJsonData("Data:StatLinks.json") | ||
-- Local references for hot-path globals | -- Local references for hot-path globals | ||
| Line 15: | Line 14: | ||
local tostring = tostring | local tostring = tostring | ||
local type = type | local type = type | ||
-- Pre-computed constants | -- Pre-computed constants | ||
| Line 29: | Line 19: | ||
.. " [[{{#invoke:Lang|get_string|Citadel_StatusEffect}}]]" | .. " [[{{#invoke:Lang|get_string|Citadel_StatusEffect}}]]" | ||
-- | -- Spirit damage constants | ||
local | local SPIRIT_ICON = "[[File:Spirit_damage.png|12px]]" | ||
local SPIRIT_COLOR = "#bc8ee8" | |||
local SPIRIT_LINK = "Spirit Damage" | |||
-- Label key remapping table (replaces if/elseif chain) | -- Label key remapping table (replaces if/elseif chain) | ||
local LABEL_KEY_REMAP = { | local LABEL_KEY_REMAP = { | ||
BuildUpPerShot = "BuildupPerShot", | |||
DotDuration = "DOTDuration", | DotDuration = "DOTDuration", | ||
} | } | ||
| Line 69: | Line 54: | ||
local conditional_label -- lazily initialised | local conditional_label -- lazily initialised | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
| Line 117: | Line 72: | ||
local function get_json_item(name) | local function get_json_item(name) | ||
local direct = data[name] | |||
local direct = data[ | |||
if direct and not direct.IsDisabled then return direct end | if direct and not direct.IsDisabled then return direct end | ||
local fallback | local fallback | ||
for _, v in pairs(data) do | for _, v in pairs(data) do | ||
if v.Name == | if v.Name == name then | ||
if not v.IsDisabled then return v end | if not v.IsDisabled then return v end | ||
fallback = fallback or v | fallback = fallback or v | ||
| Line 177: | Line 129: | ||
local function get_component_of_sorted(item_input) | local function get_component_of_sorted(item_input) | ||
local target_key | local target_key | ||
if data[ | if data[item_input] then | ||
target_key = | target_key = item_input | ||
else | else | ||
for k, v in pairs(data) do | for k, v in pairs(data) do | ||
if v.Name == | if v.Name == item_input and not v.IsDisabled then | ||
target_key = k | target_key = k | ||
break | break | ||
| Line 233: | Line 182: | ||
end | end | ||
local function append_label(val_str, prop_key, label, | local function append_label(val_str, prop_key, label, label_color, link_override) | ||
if label == "" then return val_str end | if label == "" then return val_str end | ||
local display_label | |||
local link_page = link_override or stat_links[prop_key] | |||
local | if link_page then | ||
if link_page == label then | |||
if | |||
display_label = "[[" .. label .. "]]" | display_label = "[[" .. label .. "]]" | ||
else | else | ||
display_label = "[[" .. | display_label = "[[" .. link_page .. "|" .. label .. "]]" | ||
end | end | ||
else | |||
display_label = label | |||
end | end | ||
if label_color then | |||
display_label = '<span style="color:' .. label_color .. '">' | |||
if | .. display_label .. '</span>' | ||
end | end | ||
return val_str .. " " .. display_label | |||
end | end | ||
| Line 271: | Line 210: | ||
if not conditional_label then | if not conditional_label then | ||
conditional_label = format( | conditional_label = format( | ||
'<span style="color:#C0C0C0">%s</span>', | ' <span style="color:#C0C0C0">(%s)</span>', | ||
lang.get_string("Citadel_Shop_ConditionalAttribute") | lang.get_string("Citadel_Shop_ConditionalAttribute") | ||
) | ) | ||
end | end | ||
return val_str .. conditional_label | |||
return val_str | |||
end | end | ||
| Line 286: | Line 224: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Spirit damage detection helper | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local function | local function is_spirit_damage(prop_key, css_type) | ||
return prop_key == "Damage" and css_type == "tech_damage" | |||
end | end | ||
| Line 342: | Line 236: | ||
local function format_value(prop_key, value, css_type, loc_override, | local function format_value(prop_key, value, css_type, loc_override, | ||
skip_label, allow_conditional, usage_flags, scale_info | skip_label, allow_conditional, usage_flags, scale_info) | ||
local numeric_val = extract_numeric(value) | local numeric_val = extract_numeric(value) | ||
if not numeric_val then return nil end | if not numeric_val then return nil end | ||
| Line 374: | Line 267: | ||
end | end | ||
-- | -- Spirit damage: prepend icon before the value | ||
local | local spirit = is_spirit_damage(prop_key, css_type) | ||
if spirit then | |||
val_str = SPIRIT_ICON .. " " .. val_str | |||
if | |||
val_str = | |||
end | end | ||
val_str = append_label(val_str, label_key, label, | val_str = append_label(val_str, label_key, label, | ||
spirit and SPIRIT_COLOR or nil, | |||
nil | spirit and SPIRIT_LINK or nil) | ||
return append_conditional(val_str, allow_conditional, usage_flags) | return append_conditional(val_str, allow_conditional, usage_flags) | ||
end | end | ||
| Line 397: | Line 285: | ||
local function format_value_enhanced(item_name, prop_key, value, css_type, | local function format_value_enhanced(item_name, prop_key, value, css_type, | ||
loc_override, skip_label, | loc_override, skip_label, | ||
allow_conditional, usage_flags | allow_conditional, usage_flags) | ||
local numeric_val = extract_numeric(value) | local numeric_val = extract_numeric(value) | ||
if not numeric_val then return nil end | if not numeric_val then return nil end | ||
| Line 440: | Line 327: | ||
end | end | ||
-- | -- Spirit damage: prepend icon before the value | ||
local | local spirit = is_spirit_damage(prop_key, css_type) | ||
if spirit then | |||
val_str = SPIRIT_ICON .. " " .. val_str | |||
if | |||
val_str = | |||
end | end | ||
val_str = append_label(val_str, label_key, label, | val_str = append_label(val_str, label_key, label, | ||
spirit and SPIRIT_COLOR or nil, | |||
nil | spirit and SPIRIT_LINK or nil) | ||
return append_conditional(val_str, allow_conditional, usage_flags) | return append_conditional(val_str, allow_conditional, usage_flags) | ||
end | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Tooltip builder helpers | -- Tooltip builder helpers | ||
| Line 494: | Line 358: | ||
end | end | ||
local function | local function process_stats(lines, fmt, counter, start_index, prop_list, | ||
item_name, seen, formatter) | |||
local stat_index = start_index | local stat_index = start_index | ||
for _, prop_obj in ipairs(prop_list or {}) do | for _, prop_obj in ipairs(prop_list or {}) do | ||
local key = prop_obj.Key | local key = prop_obj.Key | ||
if not seen | if not seen[key] and ( | ||
key:match("^StatusEffect") | key:match("^StatusEffect") | ||
or is_property_in_lang_data(key, prop_obj.LocTokenOverride) | or is_property_in_lang_data(key, prop_obj.LocTokenOverride) | ||
| Line 505: | Line 369: | ||
local val = formatter(prop_obj) | local val = formatter(prop_obj) | ||
if val then | if val then | ||
insert(lines, format( | insert(lines, format(fmt, counter, stat_index, val)) | ||
stat_index = stat_index + 1 | stat_index = stat_index + 1 | ||
seen[key] = true | seen[key] = true | ||
| Line 513: | Line 377: | ||
return stat_index | return stat_index | ||
end | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Unified tooltip builder (handles both default and enhanced modes) | -- Unified tooltip builder (handles both default and enhanced modes) | ||
| Line 520: | Line 383: | ||
local item_name = frame.args[1] | local item_name = frame.args[1] | ||
if not item_name then return "Item name missing" end | if not item_name then return "Item name missing" end | ||
local item = get_json_item(item_name) | local item = get_json_item(item_name) | ||
| Line 533: | Line 393: | ||
insert(lines, "| enhanced = true") | insert(lines, "| enhanced = true") | ||
end | end | ||
insert(lines, "| item_name = " .. item_name) | |||
insert(lines, "| item_name = " .. | |||
if item.StreetBrawl == true then | if item.StreetBrawl == true then | ||
insert(lines, "| street_brawl = true") | insert(lines, "| street_brawl = true") | ||
end | end | ||
| Line 549: | Line 402: | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
-- Innate stats | -- Innate stats | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
local innate_index = 1 | local innate_index = 1 | ||
| Line 555: | Line 408: | ||
if section.Type == "Innate" then | if section.Type == "Innate" then | ||
for _, obj in ipairs(section.Main or {}) do | for _, obj in ipairs(section.Main or {}) do | ||
if | |||
if is_property_in_lang_data(obj.Key, obj.LocTokenOverride) then | |||
local val | local val | ||
if enhanced then | if enhanced then | ||
val = format_value_enhanced( | val = format_value_enhanced(item_name, obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, nil, false, obj.UsageFlags) | ||
else | else | ||
val = format_value( | val = format_value(obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, false, false, obj.UsageFlags, obj.Scale) | ||
end | end | ||
if val then | if val then | ||
| Line 577: | Line 423: | ||
end | end | ||
for _, obj in ipairs(section.Alt or {}) do | for _, obj in ipairs(section.Alt or {}) do | ||
if | |||
if is_property_in_lang_data(obj.Key, obj.LocTokenOverride) then | |||
local val | local val | ||
if enhanced then | if enhanced then | ||
val = format_value_enhanced( | val = format_value_enhanced( | ||
item_name, obj.Key, obj.Value, obj.Type, | |||
obj.LocTokenOverride, nil, false, obj.UsageFlags | obj.LocTokenOverride, nil, false, obj.UsageFlags | ||
) | ) | ||
else | else | ||
val = format_value( | val = format_value( | ||
obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, | obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, | ||
false, false, obj.UsageFlags, obj.Scale | false, false, obj.UsageFlags, obj.Scale | ||
) | ) | ||
end | end | ||
| Line 602: | Line 447: | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
-- Build formatters once (closures capture | -- Build formatters once (closures capture item_name) | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
local main_formatter, alt_formatter | local main_formatter, alt_formatter | ||
| Line 609: | Line 454: | ||
main_formatter = function(obj) | main_formatter = function(obj) | ||
if obj.Key:match("^StatusEffect") then | if obj.Key:match("^StatusEffect") then | ||
return | return format(STATUS_FMT, obj.Key) | ||
end | end | ||
return format_value_enhanced( | return format_value_enhanced( | ||
item_name, obj.Key, obj.Value, obj.Type, | |||
obj.LocTokenOverride, false, true, obj.UsageFlags | obj.LocTokenOverride, false, true, obj.UsageFlags | ||
) | ) | ||
end | end | ||
alt_formatter = function(obj) | alt_formatter = function(obj) | ||
return format_value_enhanced( | return format_value_enhanced( | ||
item_name, obj.Key, obj.Value, obj.Type, | |||
obj.LocTokenOverride, nil, false, obj.UsageFlags | obj.LocTokenOverride, nil, false, obj.UsageFlags | ||
) | ) | ||
end | end | ||
else | else | ||
main_formatter = function(obj) | |||
if obj.Key:match("^StatusEffect") then | |||
return format(STATUS_FMT, obj.Key) | |||
end | |||
return format_value( | |||
obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, | |||
false, true, obj.UsageFlags, obj.Scale | |||
) | |||
end | |||
alt_formatter = function(obj) | alt_formatter = function(obj) | ||
return format_value( | return format_value( | ||
obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, | obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, | ||
false, false, obj.UsageFlags, obj.Scale | false, false, obj.UsageFlags, obj.Scale | ||
) | ) | ||
end | end | ||
| Line 649: | Line 490: | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
-- Passive & Active | -- Passive & Active stats (unified loop) | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
local passive_counter, active_counter = 1, 1 | local passive_counter, active_counter = 1, 1 | ||
| Line 659: | Line 500: | ||
local prefix = is_active and "active" or "passive" | local prefix = is_active and "active" or "passive" | ||
local counter = is_active and active_counter or passive_counter | local counter = is_active and active_counter or passive_counter | ||
local stat_fmt = "| " .. prefix .. "%d_stat%d = %s" | |||
-- Description | -- Description | ||
| Line 667: | Line 509: | ||
insert(lines, format( | insert(lines, format( | ||
"| %s%d_description = {{#invoke:Lang|get_string|%s|item_name=%s}}", | "| %s%d_description = {{#invoke:Lang|get_string|%s|item_name=%s}}", | ||
prefix, counter, loc, | prefix, counter, loc, item_name | ||
)) | )) | ||
end | end | ||
end | end | ||
-- | -- Stats | ||
local | local seen = {} | ||
local stat_index = process_stats( | |||
local | lines, stat_fmt, counter, 1, | ||
section.Main, item_name, seen, main_formatter | |||
) | |||
process_stats( | |||
lines, stat_fmt, counter, stat_index, | |||
section.Alt, item_name, seen, alt_formatter | |||
) | |||
-- Cooldown / ChargeUp | -- Cooldown / ChargeUp | ||
local cd = format_section_cooldown(section, | local cd = format_section_cooldown(section, item_name, enhanced) | ||
if cd.cooldown then | if cd.cooldown then | ||
insert(lines, format("| %s%d_cooldown = %s", prefix, counter, cd.cooldown)) | insert(lines, format("| %s%d_cooldown = %s", prefix, counter, cd.cooldown)) | ||
| Line 732: | Line 546: | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
for i = 1, 2 do | for i = 1, 2 do | ||
local comp = ItemData.get_component_name { args = { | local comp = ItemData.get_component_name { args = { item_name, i } } | ||
if comp and comp ~= "" then | if comp and comp ~= "" then | ||
insert(lines, format("| component%d_name = %s", i, comp)) | insert(lines, format("| component%d_name = %s", i, comp)) | ||
| Line 763: | Line 577: | ||
return concat(lines, "\n") | return concat(lines, "\n") | ||
end | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Public interface | -- Public interface | ||