Module:Infobox item: Difference between revisions

Added list for prop keys that need to be ignored
append_label: prefer per-stat StatLinks target over generic attribute-type link (fixes e.g. Debuff Resist → Ability Duration) (with help from vergir-bot LLM)
 
(8 intermediate revisions by 4 users not shown)
Line 15: Line 15:
local tostring = tostring
local tostring = tostring
local type = type
local type = type
-- Status Effect Icon Map
local STATUS_EFFECT_ICON_MAP = {
    StatusEffectDisarmed = {img='Status_Disarm.png',        link='Disarm',  color='Red'},
    StatusEffectEMP      = {img='Status_Silence.png',      link='Silence',  color='Purple'},
    StatusEffectInvisible= {img='Invisible.png',            link='Invisible',color='Green'},
    StatusEffectStun    = {img='Status_Stun.png',          link='Stun',    color='NoColor'},
    StatusEffectSlow    = {img='Status_Movement_Slow.png', link='Slow',    color='Purple'},
}


-- Pre-computed constants
-- Pre-computed constants
Line 28: Line 37:
local LABEL_KEY_REMAP = {
local LABEL_KEY_REMAP = {
     DotDuration    = "DOTDuration",
     DotDuration    = "DOTDuration",
}
-- Item name override mapping (old name -> new name)
local ITEM_NAME_OVERRIDES = {
    ["debuff remover"] = "Dispel Magic",
    ["backstabber"] = "Stalker",
}
}


Line 54: Line 69:


local conditional_label -- lazily initialised
local conditional_label -- lazily initialised
--------------------------------------------------------------------------------
-- Item name resolution
--------------------------------------------------------------------------------
local function resolve_item_name(name)
    -- Check if there's an override for this name (case-insensitive)
    local lowercase_name = name:lower()
    local override = ITEM_NAME_OVERRIDES[lowercase_name]
    if override then
        return override
    end
   
    -- If no override, try to find the item in data and return its proper Name
    -- First try direct key lookup
    if data[name] and not data[name].IsDisabled then
        return data[name].Name or name
    end
   
    -- Then try case-insensitive search by Name field
    local lowercase_search = name:lower()
    for _, v in pairs(data) do
        if v.Name and v.Name:lower() == lowercase_search and not v.IsDisabled then
            return v.Name
        end
    end
   
    -- Fallback to original name
    return name
end


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Line 72: Line 117:


local function get_json_item(name)
local function get_json_item(name)
     local direct = data[name]
    -- Apply name override before lookup
    local resolved_name = resolve_item_name(name)
   
     local direct = data[resolved_name]
     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 == name then
         if v.Name == resolved_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 129: Line 177:


local function get_component_of_sorted(item_input)
local function get_component_of_sorted(item_input)
    -- Apply name override before processing
    local resolved_input = resolve_item_name(item_input)
   
     local target_key
     local target_key
     if data[item_input] then
     if data[resolved_input] then
         target_key = item_input
         target_key = resolved_input
     else
     else
         for k, v in pairs(data) do
         for k, v in pairs(data) do
             if v.Name == item_input and not v.IsDisabled then
             if v.Name == resolved_input and not v.IsDisabled then
                 target_key = k
                 target_key = k
                 break
                 break
Line 185: Line 236:
     if label == "" then return val_str end
     if label == "" then return val_str end


     -- Resolve link priority: Override > Attribute Map Link > JSON Stat Link
     -- Resolve link priority: Override > JSON Stat Link > Attribute Map Link
     local link_target = link_override
     local link_target = link_override
     if not link_target or link_target == "" then
     if not link_target or link_target == "" then
         link_target = attr_link
         link_target = stat_links[prop_key]
     end
     end
     if not link_target or link_target == "" then
     if not link_target or link_target == "" then
         link_target = stat_links[prop_key]
         link_target = attr_link
     end
     end


Line 255: Line 306:
         icon_str = format("{{Icon/%s|[[File:%s|%spx|link=%s]]}}", color, img, 18, link or "")
         icon_str = format("{{Icon/%s|[[File:%s|%spx|link=%s]]}}", color, img, 18, link or "")
     end
     end
    return {
        icon = icon_str,
        link = link
    }
end
--------------------------------------------------------------------------------
-- Status Effect Icon helper
--------------------------------------------------------------------------------
local function resolve_status_effect_icon(prop_key)
    local effect_config = STATUS_EFFECT_ICON_MAP[prop_key]
    if not effect_config then return nil end
    local color = effect_config.color or "NoColor"
    local img = effect_config.img or "GenericProperty.png"
    local link = effect_config.link
    -- Construct icon using the defined color template
    local icon_str = format(
        "{{Icon/%s|[[File:%s|18px|link=%s]]}}",
        color, img, link or ""
    )


     return {
     return {
Line 380: Line 455:


     return append_conditional(val_str, allow_conditional, usage_flags)
     return append_conditional(val_str, allow_conditional, usage_flags)
end
--------------------------------------------------------------------------------
-- Status Effect formatting helper
--------------------------------------------------------------------------------
local function format_status_effect(prop_key)
    local lang_str = format("[[{{#invoke:Lang|get_string|Citadel_%s}}]]", prop_key)
        .. " [[{{#invoke:Lang|get_string|Citadel_StatusEffect}}]]"
   
    -- Get icon for this status effect
    local icon_style = resolve_status_effect_icon(prop_key)
    if icon_style and icon_style.icon then
        return icon_style.icon .. " " .. lang_str
    end
   
    return lang_str
end
end


Line 428: Line 520:
     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
    -- Resolve the item name (apply override if exists)
    local resolved_name = resolve_item_name(item_name)


     local item = get_json_item(item_name)
     local item = get_json_item(item_name)
Line 438: Line 533:
         insert(lines, "| enhanced = true")
         insert(lines, "| enhanced = true")
     end
     end
     insert(lines, "| item_name = " .. item_name)
    -- Use resolved name for item_name parameter
     insert(lines, "| item_name = " .. resolved_name)


     if item.StreetBrawl == true then
     if item.StreetBrawl == true then
         insert(lines, "| street_brawl = true")
         insert(lines, "| street_brawl = true")
    end
   
    -- Pass through nocat arg to the Infobox item template if provided
    local nocat = frame.args.nocat
    if nocat and nocat ~= "" then
        insert(lines, "| nocat = " .. nocat)
     end
     end


Line 457: Line 559:
                     if enhanced then
                     if enhanced then
                         val = format_value_enhanced(
                         val = format_value_enhanced(
                             item_name, obj.Key, obj.Value, obj.Type,  
                             resolved_name, obj.Key, obj.Value, obj.Type,  
                             obj.LocTokenOverride, nil, false, obj.UsageFlags,  
                             obj.LocTokenOverride, nil, false, obj.UsageFlags,  
                             true -- disable_attr
                             true -- disable_attr
Line 479: Line 581:
                     if enhanced then
                     if enhanced then
                         val = format_value_enhanced(
                         val = format_value_enhanced(
                             item_name, obj.Key, obj.Value, obj.Type,
                             resolved_name, obj.Key, obj.Value, obj.Type,
                             obj.LocTokenOverride, nil, false, obj.UsageFlags,
                             obj.LocTokenOverride, nil, false, obj.UsageFlags,
                             true -- disable_attr
                             true -- disable_attr
Line 500: Line 602:


     ------------------------------------------------------------------
     ------------------------------------------------------------------
     -- Build formatters once (closures capture item_name)
     -- Build formatters once (closures capture resolved_name)
     ------------------------------------------------------------------
     ------------------------------------------------------------------
     local main_formatter, alt_formatter
     local main_formatter, alt_formatter
Line 507: Line 609:
         main_formatter = function(obj)
         main_formatter = function(obj)
             if obj.Key:match("^StatusEffect") then
             if obj.Key:match("^StatusEffect") then
                 return format(STATUS_FMT, obj.Key)
                 return format_status_effect(obj.Key)
             end
             end
             return format_value_enhanced(
             return format_value_enhanced(
                 item_name, obj.Key, obj.Value, obj.Type,
                 resolved_name, obj.Key, obj.Value, obj.Type,
                 obj.LocTokenOverride, false, true, obj.UsageFlags, nil, true
                 obj.LocTokenOverride, false, true, obj.UsageFlags, nil, true
             )
             )
         end
         end
         alt_formatter = function(obj)
         alt_formatter = function(obj)
            if obj.Key:match("^StatusEffect") then
                return format_status_effect(obj.Key)
            end
             return format_value_enhanced(
             return format_value_enhanced(
                 item_name, obj.Key, obj.Value, obj.Type,
                 resolved_name, obj.Key, obj.Value, obj.Type,
                 obj.LocTokenOverride, nil, false, obj.UsageFlags,
                 obj.LocTokenOverride, nil, false, obj.UsageFlags,
                 true -- disable_attr
                 true -- disable_attr
Line 524: Line 629:
         main_formatter = function(obj)
         main_formatter = function(obj)
             if obj.Key:match("^StatusEffect") then
             if obj.Key:match("^StatusEffect") then
                 return format(STATUS_FMT, obj.Key)
                 return format_status_effect(obj.Key)
             end
             end
             return format_value(
             return format_value(
Line 532: Line 637:
         end
         end
         alt_formatter = function(obj)
         alt_formatter = function(obj)
            if obj.Key:match("^StatusEffect") then
                return format_status_effect(obj.Key)
            end
             return format_value(
             return format_value(
                 obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,
                 obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,
Line 559: Line 667:
                     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, item_name
                         prefix, counter, loc, resolved_name
                     ))
                     ))
                 end
                 end
Line 604: Line 712:


             -- Cooldown / ChargeUp
             -- Cooldown / ChargeUp
             local cd = format_section_cooldown(section, item_name, enhanced)
             local cd = format_section_cooldown(section, resolved_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 624: Line 732:
     ------------------------------------------------------------------
     ------------------------------------------------------------------
     for i = 1, 2 do
     for i = 1, 2 do
         local comp = ItemData.get_component_name { args = { item_name, i } }
         local comp = ItemData.get_component_name { args = { resolved_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))