Module:Sandbox/LVL: Difference between revisions

LVL (talk | contribs)
No edit summary
LVL (talk | contribs)
No edit summary
Line 4: Line 4:
local data = mw.loadJsonData("Data:Monster_Domosed/ItemData.json")
local data = mw.loadJsonData("Data:Monster_Domosed/ItemData.json")


-- Helper function: get first non-nil string from variants (moved to module level)
-- Get raw value, CSS class, and LocTokenOverride for a property
local function get_raw_value(item_name, prop)
    local item = data[item_name] or nil
    if not item then
        for k,v in pairs(data) do
            if v.Name == item_name then item = v; break end
        end
    end
    if not item then return nil, nil, nil end
 
    local raw_prop = item[prop]
    if type(raw_prop) == "table" then
        local loc_override = raw_prop.LocTokenOverride or prop
        return raw_prop.Value, raw_prop.CSSClass, loc_override
    else
        return raw_prop, nil, prop
    end
end
 
-- Check if property exists in language data
local function is_property_in_lang_data(prop)
    local suffixes = {"_label", "_Label", "_prefix", "_Prefix", "_postfix", "_Postfix", "_postvalue_label", "_Postvalue_Label"}
    for _, suffix in ipairs(suffixes) do
        if lang.get_string(prop .. suffix) then
            return true
        end
    end
    return false
end
 
-- Get item by name, ignoring disabled if possible
local function get_json_item(name)
    for _, v in pairs(data) do
        if v.Name == name and (v.IsDisabled == false or v.IsDisabled == nil) then
            return v
        end
    end
    for _, v in pairs(data) do
        if v.Name == name then return v end
    end
    return nil
end
 
-- Helper function: get first non-nil string from variants
local function first_non_nil(...)
local function first_non_nil(...)
     for i = 1, select("#", ...) do
     for i = 1, select("#", ...) do
Line 13: Line 56:
end
end


-- Helper: get lang string with case fallback (from Domo's version)
-- Helper: get lang string with case fallback
local function get_lang_with_fallback(base_key, suffix1, suffix2)
local function get_lang_with_fallback(base_key, suffix1, suffix2)
     return first_non_nil(
     return first_non_nil(
Line 21: Line 64:
end
end


-- Get component-of items sorted by tier (your fix, kept here until ready to move to Module:ItemData)
-- Returns items that build from this item, sorted by tier
local function get_component_of_sorted(item_input)
local function get_component_of_sorted(item_input)
     local target_key = nil
     local target_key = nil
Line 47: Line 90:
     end
     end


    -- Sort by Tier instead of alphabetically (your fix)
     table.sort(parents, function(a, b)
     table.sort(parents, function(a, b)
         local tier_a = tonumber(data[a] and data[a]["Tier"]) or 0
         local tier_a = tonumber(data[a] and data[a]["Tier"]) or 0
Line 55: Line 97:


     return parents
     return parents
end
-- Get raw value, CSS class, and LocTokenOverride for a property
local function get_raw_value(item_name, prop)
    local item = data[item_name] or nil
    if not item then
        for k,v in pairs(data) do
            if v.Name == item_name then item = v; break end
        end
    end
    if not item then return nil, nil, nil end
    local raw_prop = item[prop]
    if type(raw_prop) == "table" then
        local loc_override = raw_prop.LocTokenOverride or prop
        return raw_prop.Value, raw_prop.CSSClass, loc_override
    else
        return raw_prop, nil, prop
    end
end
-- Check if property exists in language data (refactored to loop, from Domo's version)
local function is_property_in_lang_data(prop)
    local suffixes = {"_label", "_Label", "_prefix", "_Prefix", "_postfix", "_Postfix", "_postvalue_label", "_Postvalue_Label"}
    for _, suffix in ipairs(suffixes) do
        if lang.get_string(prop .. suffix) then
            return true
        end
    end
    return false
end
-- Get item by name, ignoring disabled if possible
local function get_json_item(name)
    for _, v in pairs(data) do
        if v.Name == name and (v.IsDisabled == false or v.IsDisabled == nil) then
            return v
        end
    end
    for _, v in pairs(data) do
        if v.Name == name then return v end
    end
    return nil
end
end


-- Format stat value for Infobox, handling prefix/postfix, CSS, scaling, and conditional
-- Format stat value for Infobox, handling prefix/postfix, CSS, scaling, and conditional
-- allow_conditional should be true for ImportantProperties, false for regular Properties
local function format_stat(item_name, prop, skip_label, debug, allow_conditional)
local function format_stat(item_name, prop, skip_label, debug, allow_conditional)
     if allow_conditional == nil then allow_conditional = true end
     if allow_conditional == nil then allow_conditional = true end
Line 110: Line 110:
     local value, css, loc_key = get_raw_value(item_name, prop)
     local value, css, loc_key = get_raw_value(item_name, prop)
     if value == nil or value == 0 or value == "" then
     if value == nil or value == 0 or value == "" then
        return nil
    return nil
     end
     end


    -- Convert string like "0m" or "0.0" to number for zero check
     local numeric_val = tonumber(tostring(value):match("^-?%d+%.?%d*")) or 0
     local numeric_val = tonumber(tostring(value):match("^-?%d+%.?%d*")) or 0
     if numeric_val == 0 then
     if numeric_val == 0 then
Line 119: Line 118:
     end
     end


    -- Skip if property has no lang data
     local label_key = loc_key:gsub("^#", "")
     local label_key = loc_key:gsub("^#", "")
    if not (
if not (
        lang.get_string(label_key.."_label") or
    lang.get_string(label_key.."_label") or
        lang.get_string(label_key.."_Label") or
    lang.get_string(label_key.."_Label") or
        lang.get_string(label_key.."_prefix") or
    lang.get_string(label_key.."_prefix") or
        lang.get_string(label_key.."_Prefix") or
    lang.get_string(label_key.."_Prefix") or
        lang.get_string(label_key.."_postfix") or
    lang.get_string(label_key.."_postfix") or
        lang.get_string(label_key.."_Postfix") or
    lang.get_string(label_key.."_Postfix") or
        lang.get_string(label_key.."_postvalue_label") or
    lang.get_string(label_key.."_postvalue_label") or
        lang.get_string(label_key.."_Postvalue_Label")
    lang.get_string(label_key.."_Postvalue_Label")
    ) then
) then
        return nil
    return nil
    end
end
 
if debug == 2 then
    local label_val, prefix_val, postfix_val
 
    if lang.get_string(label_key.."_label") then
        label_val = label_key.."_label"
    elseif lang.get_string(label_key.."_Label") then
        label_val = label_key.."_Label"
    else
        label_val = "(none)"
    end
 
    if lang.get_string(label_key.."_prefix") then
        prefix_val = label_key.."_prefix"
    elseif lang.get_string(label_key.."_Prefix") then
        prefix_val = label_key.."_Prefix"
    else
        prefix_val = "(none)"
    end
 
    if lang.get_string(label_key.."_postfix") then
        postfix_val = label_key.."_postfix"
    elseif lang.get_string(label_key.."_Postfix") then
        postfix_val = label_key.."_Postfix"
    else
        postfix_val = "(none)"
    end


    if debug == 2 then
    return string.format(
        local label_val = lang.get_string(label_key.."_label") and label_key.."_label"
        "raw invoke key: %s | raw value: %s | label key used: %s | prefix key used: %s | postfix key used: %s",
                      or lang.get_string(label_key.."_Label") and label_key.."_Label"
        loc_key,
                      or "(none)"
        tostring(value),
        local prefix_val = lang.get_string(label_key.."_prefix") and label_key.."_prefix"
        label_val,
                        or lang.get_string(label_key.."_Prefix") and label_key.."_Prefix"
        prefix_val,
                        or "(none)"
        postfix_val
        local postfix_val = lang.get_string(label_key.."_postfix") and label_key.."_postfix"
    )
                        or lang.get_string(label_key.."_Postfix") and label_key.."_Postfix"
end
                        or "(none)"
        return string.format(
            "raw invoke key: %s | raw value: %s | label key used: %s | prefix key used: %s | postfix key used: %s",
            loc_key, tostring(value), label_val, prefix_val, postfix_val
        )
    end


     if prop == "BuildUpPerShot" then label_key = "BuildupPerShot"
     if prop == "BuildUpPerShot" then label_key = "BuildupPerShot"
Line 154: Line 173:
     end
     end


    -- Get actual label, prefix, postfix with fallbacks (using helper from Domo's version)
     local label = skip_label and "" or get_lang_with_fallback(label_key, "_label", "_Label")
     local label = skip_label and "" or get_lang_with_fallback(label_key, "_label", "_Label")
     local prefix = get_lang_with_fallback(label_key, "_prefix", "_Prefix")
     local prefix = get_lang_with_fallback(label_key, "_prefix", "_Prefix")
Line 160: Line 178:


     if prefix == "" and postfix == "" and label == "" then
     if prefix == "" and postfix == "" and label == "" then
        return nil
    return nil
    end
end


     local val_str = tostring(value)
     local val_str = tostring(value)
Line 180: Line 198:


     ------------------------------------------------------------------
     ------------------------------------------------------------------
     -- CSS-specific formatting (after prefix to avoid double +)
     -- CSS-specific formatting (must run after prefix to avoid double +)
     ------------------------------------------------------------------
     ------------------------------------------------------------------
     if css == "move_speed" or css == "sprint_speed" then
     if css == "move_speed" or css == "sprint_speed" then
Line 195: Line 213:
     -- Append postfix
     -- Append postfix
     ------------------------------------------------------------------
     ------------------------------------------------------------------
    if prop ~= "BuildUpPerShot" and postfix ~= "" and not val_str:find(postfix, 1, true) then
if prop ~= "BuildUpPerShot" and postfix ~= "" and not val_str:find(postfix, 1, true) then
        if postfix == "HP/s" then
    if postfix == "HP/s" then
            val_str = val_str .. " " .. postfix
        val_str = val_str .. " " .. postfix
        else
    else
            val_str = val_str .. postfix
        val_str = val_str .. postfix
        end
    end
    end
end


     ------------------------------------------------------------------
     ------------------------------------------------------------------
Line 222: Line 240:


     ------------------------------------------------------------------
     ------------------------------------------------------------------
     -- Append (Conditional) ONLY if allowed (your fix: only for ImportantProperties)
     -- Append (Conditional) only shown for ImportantProperties
     ------------------------------------------------------------------
     ------------------------------------------------------------------
    if allow_conditional
if allow_conditional
        and type(raw_prop) == "table"
    and type(raw_prop) == "table"
        and (raw_prop.UsageFlags == "ConditionallyApplied" or raw_prop.UsageFlags == "ConditionallyEnemyApplied")
    and (raw_prop.UsageFlags == "ConditionallyApplied" or raw_prop.UsageFlags == "ConditionallyEnemyApplied")
    then
then
        local conditional_text = lang.get_string("Citadel_Shop_ConditionalAttribute")
    local conditional_text = lang.get_string("Citadel_Shop_ConditionalAttribute")
        val_str = val_str .. string.format(' <span style="color:#C0C0C0">(%s)</span>', conditional_text)
    val_str = val_str .. string.format(' <span style="color:#C0C0C0">(%s)</span>', conditional_text)
    end
end


     return val_str
     return val_str
end
end


-- Special formatting for StatusEffect
-- Special formatting for StatusEffect properties
local function format_property_for_infobox(item_name, prop, skip_label, debug)
local function format_property_for_infobox(item_name, prop, skip_label, debug)
     if prop:match("^StatusEffect") then
     if prop:match("^StatusEffect") then
Line 243: Line 261:
         )
         )
     else
     else
        -- allow_conditional = true: ImportantProperties can show Conditional (your fix)
         return format_stat(item_name, prop, skip_label, debug, true)
         return format_stat(item_name, prop, skip_label, debug, true)
     end
     end
Line 258: Line 275:
     local ItemData = require("Module:ItemData")
     local ItemData = require("Module:ItemData")
     local lines = {
     local lines = {
    "{{Infobox item",
        "{{Infobox item",
    "| item_name = " .. item_name
        "| item_name = " .. item_name
}
    }
 
if item.StreetBrawl == true then
    if item.StreetBrawl == true then
    table.insert(lines, "| street_brawl = true")
        table.insert(lines, "| street_brawl = true")
end
    end


     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
Line 293: Line 310:
                 for _, prop in ipairs(entry.Properties or {}) do
                 for _, prop in ipairs(entry.Properties or {}) do
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime" then
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime" then
                        -- allow_conditional = false for innate stats (your fix)
                         local val = format_stat(item_name, prop, false, debug, false)
                         local val = format_stat(item_name, prop, false, debug, false)
                         if val then
                         if val then
Line 323: Line 339:
                 local seen_props = {}
                 local seen_props = {}


                -- ImportantProperties: allow_conditional = true (via format_property_for_infobox)
                 for _, prop in ipairs(entry.ImportantProperties or {}) do
                 for _, prop in ipairs(entry.ImportantProperties or {}) do
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
Line 336: Line 351:
                 end
                 end


                -- Properties: allow_conditional = false (your fix)
                 for _, prop in ipairs(entry.Properties or {}) do
                 for _, prop in ipairs(entry.Properties or {}) do
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
Line 349: Line 363:
                 end
                 end


                -- AbilityCooldown
                 for _, prop_list in ipairs({entry.Properties or {}, entry.ImportantProperties or {}}) do
                 for _, prop_list in ipairs({entry.Properties or {}, entry.ImportantProperties or {}}) do
                     for _, prop in ipairs(prop_list) do
                     for _, prop in ipairs(prop_list) do
                         if prop == "AbilityCooldown" then
                         if prop == "AbilityCooldown" then
                             local cd = format_stat(item_name, prop, true, debug)
                             local cd = format_stat(item_name, prop, true, debug)
                             if cd then
                             if cd then table.insert(lines, string.format("| passive%d_cooldown = %s", passive_counter, cd)) end
                                table.insert(lines, string.format("| passive%d_cooldown = %s", passive_counter, cd))
                            end
                         end
                         end
                    end
                end
                -- AbilityChargeUpTime
                for _, prop_list in ipairs({entry.Properties or {}, entry.ImportantProperties or {}}) do
                    for _, prop in ipairs(prop_list) do
                         if prop == "AbilityChargeUpTime" then
                         if prop == "AbilityChargeUpTime" then
                             local cu = format_stat(item_name, prop, true, debug)
                             local cu = format_stat(item_name, prop, true, debug)
                             if cu then
                             if cu then table.insert(lines, string.format("| passive%d_chargeup = %s", passive_counter, cu)) end
                                table.insert(lines, string.format("| passive%d_chargeup = %s", passive_counter, cu))
                            end
                         end
                         end
                     end
                     end
Line 395: Line 398:
                 local seen_props = {}
                 local seen_props = {}


                -- ImportantProperties: allow_conditional = true (via format_property_for_infobox)
                 for _, prop in ipairs(entry.ImportantProperties or {}) do
                 for _, prop in ipairs(entry.ImportantProperties or {}) do
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
Line 408: Line 410:
                 end
                 end


                -- Properties: allow_conditional = false (your fix)
                 for _, prop in ipairs(entry.Properties or {}) do
                 for _, prop in ipairs(entry.Properties or {}) do
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
                     if prop ~= "AbilityCooldown" and prop ~= "AbilityChargeUpTime"
Line 421: Line 422:
                 end
                 end


                -- AbilityCooldown
                 for _, prop_list in ipairs({entry.Properties or {}, entry.ImportantProperties or {}}) do
                 for _, prop_list in ipairs({entry.Properties or {}, entry.ImportantProperties or {}}) do
                     for _, prop in ipairs(prop_list) do
                     for _, prop in ipairs(prop_list) do
                         if prop == "AbilityCooldown" then
                         if prop == "AbilityCooldown" then
                             local cd = format_stat(item_name, prop, true, debug)
                             local cd = format_stat(item_name, prop, true, debug)
                             if cd then
                             if cd then table.insert(lines, string.format("| active%d_cooldown = %s", active_index, cd)) end
                                table.insert(lines, string.format("| active%d_cooldown = %s", active_index, cd))
                            end
                         end
                         end
                    end
                end
                -- AbilityChargeUpTime
                for _, prop_list in ipairs({entry.Properties or {}, entry.ImportantProperties or {}}) do
                    for _, prop in ipairs(prop_list) do
                         if prop == "AbilityChargeUpTime" then
                         if prop == "AbilityChargeUpTime" then
                             local cu = format_stat(item_name, prop, true, debug)
                             local cu = format_stat(item_name, prop, true, debug)
                             if cu then
                             if cu then table.insert(lines, string.format("| active%d_chargeup = %s", active_index, cu)) end
                                table.insert(lines, string.format("| active%d_chargeup = %s", active_index, cu))
                            end
                         end
                         end
                     end
                     end
Line 451: Line 441:


     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
     -- Global fallback for AbilityCooldown (your fix: attaches to active section)
     -- Global fallback for AbilityCooldown and AbilityChargeUpTime
    -- Attaches to the active section if one exists, otherwise innate
     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
     if not cooldown_found_in_sections and not chargeup_found_in_sections and item.AbilityCooldown then
     if not cooldown_found_in_sections and not chargeup_found_in_sections and item.AbilityCooldown then
Line 470: Line 461:
     if not chargeup_found_in_sections and item.AbilityChargeUpTime then
     if not chargeup_found_in_sections and item.AbilityChargeUpTime then
         local cu = format_stat(item_name, "AbilityChargeUpTime", true, debug)
         local cu = format_stat(item_name, "AbilityChargeUpTime", true, debug)
         if cu then
         if cu then table.insert(lines, "| item_stat_chargeup = " .. cu) end
            table.insert(lines, "| item_stat_chargeup = " .. cu)
        end
     end
     end


Line 479: Line 468:
     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
     for i = 1, 2 do
     for i = 1, 2 do
         local comp = ItemData.get_component_name {
         local comp = ItemData.get_component_name { args = { item_name, i } }
            args = { item_name, i }
        }
         if comp and comp ~= "" then
         if comp and comp ~= "" then
             table.insert(lines, string.format("| component%d_name = %s", i, comp))
             table.insert(lines, string.format("| component%d_name = %s", i, comp))
Line 488: Line 475:


     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
     -- Is Component Of (your tier-sorted fix)
     -- Is Component Of (sorted by tier)
     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
     local parents = get_component_of_sorted(item_name)
     local parents = get_component_of_sorted(item_name)
Line 499: Line 486:


     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
     -- Sounds (always manual, passed as sound1= sound2= etc.)
     -- Sounds
     ----------------------------------------------------------------------
     ----------------------------------------------------------------------
     for key, value in pairs(frame.args) do
     for key, value in pairs(frame.args) do