|
|
| Line 1: |
Line 1: |
| local p = {} | | local p = {} |
| local lang = require "Module:Lang"
| |
| local util_module = require "Module:Utilities"
| |
| local data = mw.loadJsonData("Data:Monster_Domosed/ItemCards.json")
| |
| local stat_links = mw.loadJsonData("Data:StatLinks.json")
| |
|
| |
|
| local LANG_CODE = lang.get_lang_code() | | -- Single pre-indexed lookup, built by the bot at deploy time. |
| local IS_EN = (LANG_CODE == "en") | | -- mw.loadJsonData re-parses JSON on every page render, but is still |
| | -- dramatically faster than loading 3 separate files and iterating them. |
| | local iconData = mw.loadJsonData("Data:Sandbox") |
| | local lang_codes = mw.loadJsonData("Data:LangCodes.json") |
|
| |
|
| local MOVE_SPEED_RATES = mw.loadJsonData("Data:LocalizedUnits.json") | | local cachedLangCode, cachedLangData |
|
| |
|
| --------------------------------------------------------------------------------
| | local linkOverrides = { |
| -- Utility helpers
| | ["Bullet Lifesteal"] = "Bullet Lifesteal (item)", |
| --------------------------------------------------------------------------------
| | ["Spirit Lifesteal"] = "Spirit Lifesteal (item)" |
| | } |
|
| |
|
| local function has_rate_unit(str) | | local aliases = { |
| if type(str) ~= "string" then return false end | | ["doorman"] = "the doorman", |
| return str:find("/") ~= nil | | ["mo and krill"] = "mo & krill", |
| end
| | ["mo"] = "mo & krill", |
| | | ["krill"] = "mo & krill", |
| local function get_movespeed_rate_suffix()
| | ["curse"] = "cursed relic", |
| return MOVE_SPEED_RATES[LANG_CODE] | | ["debuff remover"] = "dispel magic", |
| end
| | ["defend and fight!"] = "plot armor", |
| | | ["conjure dragon"] = "bookwyrm", |
| local function get_missing_rate_warning()
| | ["backstabber"] = "stalker", |
| return '<sup style="white-space:nowrap; font-size: smaller;"><span title="Missing translated m/s. Please add an entry for this language to Data:Lang_MoveSpeedRates.json" style="color:red; cursor:help;">!?</span></sup>' | | ["flying strike"] = "flying slash", |
| end
| | ["tornado"] = "dust devil", |
| | | ["kudzu bomb"] = "entangling thorns", |
| local function first_non_nil(...)
| | ["kudzu connection"] = "watcher's covenant" |
| for i = 1, select("#", ...) do | | } |
| local v = select(i, ...)
| |
| if v and v ~= "" then return v end
| |
| end | |
| return "" | |
| end
| |
| | |
| local function get_lang_with_fallback(base_key, suffix1, suffix2)
| |
| return first_non_nil( | |
| lang.get_string(base_key .. suffix1),
| |
| lang.get_string(base_key .. suffix2)
| |
| ) | |
| end
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- Data access helpers (adapted for new Info-section format)
| |
| --------------------------------------------------------------------------------
| |
|
| |
|
| -- Get item by name, preferring non-disabled
| | local function getLangData() |
| local function get_json_item(name) | | if cachedLangData then |
| if data[name] and not data[name].IsDisabled then | | return cachedLangCode, cachedLangData |
| return data[name] | |
| end
| |
| for _, v in pairs(data) do
| |
| if v.Name == name and not v.IsDisabled then return v end
| |
| end | | end |
| for _, v in pairs(data) do
| |
| if v.Name == name then return v end
| |
| end
| |
| return nil
| |
| end
| |
|
| |
|
| -- Get ordered Info sections (Info1, Info2, ...) from an item
| | local title = mw.title.getCurrentTitle().fullText |
| local function get_info_sections(item)
| | local subpageLang = title:match("/([^/]+)$") |
| local sections = {} | | local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" |
| local i = 1 | |
| while item["Info" .. i] do
| |
| table.insert(sections, item["Info" .. i])
| |
| i = i + 1
| |
| end
| |
| return sections
| |
| end
| |
|
| |
|
| -- Find a property object by key across all Info sections and Other
| | local langData = {} |
| local function find_property_obj(item, prop_key) | | if langCode ~= "en" then |
| for _, section in ipairs(get_info_sections(item)) do | | local success, data = pcall(function() |
| for _, obj in ipairs(section.Main or {}) do
| | return mw.loadJsonData("Data:Lang " .. langCode .. ".json") |
| if obj.Key == prop_key then return obj end
| | end) |
| end | | if success and type(data) == "table" then |
| for _, obj in ipairs(section.Alt or {}) do | | langData = data |
| if obj.Key == prop_key then return obj end | |
| end | | end |
| end | | end |
| if item.Other and item.Other[prop_key] then
| |
| return item.Other[prop_key]
| |
| end
| |
| return nil
| |
| end
| |
|
| |
|
| -- Get raw value, type (CSS class), and LocTokenOverride for a property
| | cachedLangCode = langCode |
| local function get_raw_value(item_name, prop)
| | cachedLangData = langData |
| local item = data[item_name] or get_json_item(item_name) | | return langCode, langData |
| if not item then return nil, nil, nil end | |
| | |
| local obj = find_property_obj(item, prop)
| |
| if not obj then return nil, nil, nil end | |
| | |
| return obj.Value, obj.Type, obj.LocTokenOverride or prop
| |
| end | | end |
|
| |
|
| -- Check if property has language data (checks both key and optional loc override)
| | function p.render(frame) |
| local function is_property_in_lang_data(prop, loc_override) | | local args = frame:getParent().args |
| local suffixes = { | | local name = args[1] or "" |
| "_label", "_Label", "_prefix", "_Prefix",
| | local lowerName = name:lower() |
| "_postfix", "_Postfix", "_postvalue_label", "_Postvalue_Label"
| |
| }
| |
| local keys = { prop } | |
| if loc_override and loc_override ~= prop then
| |
| table.insert(keys, loc_override)
| |
| end
| |
| for _, key in ipairs(keys) do
| |
| for _, suffix in ipairs(suffixes) do
| |
| if lang.get_string(key .. suffix) then return true end
| |
| end
| |
| end
| |
| return false
| |
| end
| |
|
| |
|
| -- Returns item keys that build from this item, sorted by tier | | -- Resolve aliases |
| local function get_component_of_sorted(item_input)
| | if aliases[lowerName] then |
| local target_key = nil
| | lowerName = aliases[lowerName] |
| if data[item_input] then | |
| target_key = item_input | |
| else
| |
| for k, v in pairs(data) do
| |
| if v.Name == item_input and not v.IsDisabled then
| |
| target_key = k; break
| |
| end
| |
| end
| |
| end | | end |
| if not target_key then return {} end
| |
|
| |
|
| local parents = {} | | -- Direct O(1) lookup, no iteration |
| for key, item in pairs(data) do
| | local iconInfo = iconData[lowerName] |
| if not item.IsDisabled and item.Components and type(item.Components) == "table" then
| |
| for _, comp in ipairs(item.Components) do
| |
| if comp == target_key then
| |
| table.insert(parents, key)
| |
| break
| |
| end
| |
| end
| |
| end
| |
| end | |
|
| |
|
| table.sort(parents, function(a, b) | | if not iconInfo then |
| local tier_a = tonumber(data[a] and data[a].Tier) or 0 | | return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name) |
| local tier_b = tonumber(data[b] and data[b].Tier) or 0
| |
| return tier_a < tier_b
| |
| end)
| |
| | |
| return parents
| |
| end
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- Shared formatting sub-routines
| |
| --------------------------------------------------------------------------------
| |
| | |
| local function resolve_label_key(prop_key, loc_override)
| |
| local label_key = (loc_override or prop_key):gsub("^#", "")
| |
| if prop_key == "BuildUpPerShot" then label_key = "BuildupPerShot"
| |
| elseif prop_key == "DotDuration" then label_key = "DOTDuration" end
| |
| return label_key
| |
| end
| |
| | |
| local function resolve_prefix(prefix, numeric_val)
| |
| if prefix == "{s:sign}" then
| |
| return (numeric_val >= 0) and "+" or ""
| |
| end | | end |
| return prefix
| |
| end
| |
|
| |
|
| local function resolve_suffix(postfix, css_type)
| | -- Argument parsing |
| local suffix = postfix | | local customText = args.l1 or "" |
| if postfix == "HP/s" then suffix = " " .. postfix end | | local size = args.size or "20px" |
| if (css_type == "move_speed" or css_type == "sprint_speed") | | local noLink = args["no-link"] == "true" |
| and postfix ~= "%" and not has_rate_unit(postfix) then
| | local iconOnly = args["icon-only"] == "true" |
| local override = get_movespeed_rate_suffix()
| |
| suffix = override or ("m/s" .. get_missing_rate_warning())
| |
| end
| |
| return suffix
| |
| end
| |
|
| |
|
| local function append_label(val_str, prop_key, label)
| | for k, v in pairs(args) do |
| if label == "" then return val_str end
| | if type(k) == "number" and k > 1 then |
| local link_page = stat_links[prop_key]
| | local val = mw.text.trim(v) |
| if link_page then
| | if val == "icon-only" then iconOnly = true |
| if link_page == label then
| | elseif val == "no-link" then noLink = true |
| return val_str .. " [[" .. label .. "]]" | | elseif val:match("^%d+px$") then size = val end |
| else
| |
| return val_str .. " [[" .. link_page .. "|" .. label .. "]]" | |
| end | | end |
| end | | end |
| return val_str .. " " .. label
| |
| end
| |
|
| |
| local function append_conditional(val_str, allow_conditional, usage_flags)
| |
| if allow_conditional
| |
| and (usage_flags == "ConditionallyApplied"
| |
| or usage_flags == "ConditionallyEnemyApplied") then
| |
| return val_str .. string.format(
| |
| ' <span style="color:#C0C0C0">(%s)</span>',
| |
| lang.get_string("Citadel_Shop_ConditionalAttribute")
| |
| )
| |
| end
| |
| return val_str
| |
| end
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- Core formatting: non-enhanced
| |
| --------------------------------------------------------------------------------
| |
|
| |
| local function format_value(prop_key, value, css_type, loc_override,
| |
| skip_label, allow_conditional, usage_flags, scale_info)
| |
| if value == nil or value == 0 or value == "" then return nil end
| |
|
| |
| local numeric_val = tonumber(tostring(value):match("^-?%d+%.?%d*")) or 0
| |
| if numeric_val == 0 then return nil end
| |
|
| |
| local label_key = resolve_label_key(prop_key, loc_override)
| |
| 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 postfix = get_lang_with_fallback(label_key, "_postfix", "_Postfix")
| |
|
| |
| if prefix == "" and postfix == "" and label == "" then return nil end
| |
|
| |
| prefix = resolve_prefix(prefix, numeric_val)
| |
| local suffix = resolve_suffix(postfix, css_type)
| |
|
| |
| -- Compose value string
| |
| local val_str = tostring(numeric_val)
| |
| if prefix ~= "" then val_str = prefix .. val_str end
| |
| if suffix ~= "" and not val_str:find(suffix, 1, true) then
| |
| val_str = val_str .. suffix
| |
| end
| |
|
| |
| -- Scale handling
| |
| if scale_info and scale_info.Value and scale_info.Value ~= 0 then
| |
| local scale_val = util_module.round_to_sig_fig(scale_info.Value, 2)
| |
| local tmpl = (scale_info.Type == "power_increase") and "Boon" or "Ss"
| |
| val_str = val_str .. " " .. mw.getCurrentFrame():expandTemplate{
| |
| title = tmpl, args = { scale_val }
| |
| }
| |
| end
| |
|
| |
| val_str = append_label(val_str, prop_key, label)
| |
| val_str = append_conditional(val_str, allow_conditional, usage_flags)
| |
|
| |
| return val_str
| |
| end
| |
|
| |
| -- Convenience wrapper: look up a property from item data, then format
| |
| local function format_stat(item_name, prop, skip_label, debug, allow_conditional)
| |
| skip_label = skip_label or false
| |
| if allow_conditional == nil then allow_conditional = true end
| |
|
| |
|
| local item = get_json_item(item_name) | | -- Language handling |
| if not item then return nil end
| | local langCode, langData = getLangData() |
|
| |
|
| local obj = find_property_obj(item, prop) | | local displayName = customText |
| if not obj then return nil end | | if displayName == "" then |
| | | if iconInfo.key and langData[iconInfo.key] then |
| return format_value(
| | displayName = langData[iconInfo.key] |
| prop, obj.Value, obj.Type, obj.LocTokenOverride,
| |
| skip_label, allow_conditional, obj.UsageFlags, obj.Scale
| |
| )
| |
| end
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- Core formatting: enhanced
| |
| --------------------------------------------------------------------------------
| |
| | |
| local function format_value_enhanced(item_name, prop_key, value, css_type,
| |
| loc_override, skip_label,
| |
| allow_conditional, usage_flags)
| |
| if value == nil or value == 0 or value == "" then return nil end
| |
| | |
| local numeric_val = tonumber(tostring(value):match("^-?%d+%.?%d*")) or 0
| |
| if numeric_val == 0 then return nil end
| |
| | |
| local label_key = resolve_label_key(prop_key, loc_override)
| |
| | |
| -- Enhanced requires lang data to exist
| |
| if not (
| |
| 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.."_postfix") or lang.get_string(label_key.."_Postfix") or
| |
| lang.get_string(label_key.."_postvalue_label") or lang.get_string(label_key.."_Postvalue_Label")
| |
| ) then return nil end
| |
| | |
| 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 postfix = get_lang_with_fallback(label_key, "_postfix", "_Postfix")
| |
| | |
| if prefix == "" and postfix == "" and label == "" then return nil end
| |
| | |
| prefix = resolve_prefix(prefix, numeric_val)
| |
| local suffix = resolve_suffix(postfix, css_type)
| |
| | |
| -- Build Enhanced invoke
| |
| local extras = {}
| |
| if prefix ~= "" then table.insert(extras, "prefix=" .. prefix) end
| |
| if suffix ~= "" and suffix ~= "%" then table.insert(extras, "suffix=" .. suffix) end
| |
| table.insert(extras, "noicon=true")
| |
| | |
| local val_str = string.format(
| |
| "{{#invoke:Enhanced|render|%s|%s|%s}}",
| |
| item_name, prop_key, table.concat(extras, "|")
| |
| )
| |
| | |
| -- Unstyled postfix (if not already present)
| |
| if postfix ~= "" and postfix ~= "%" and not val_str:find(postfix, 1, true) then
| |
| val_str = val_str .. (postfix == "HP/s" and (" " .. postfix) or postfix)
| |
| end
| |
| | |
| val_str = append_label(val_str, prop_key, label)
| |
| val_str = append_conditional(val_str, allow_conditional, usage_flags)
| |
| | |
| return val_str
| |
| end
| |
| | |
| -- Convenience wrapper: look up a property from item data, then format (enhanced)
| |
| local function format_stat_enhanced(item_name, prop, skip_label, allow_conditional)
| |
| skip_label = skip_label or false
| |
| if allow_conditional == nil then allow_conditional = true end
| |
| | |
| local item = get_json_item(item_name)
| |
| if not item then return nil end
| |
| | |
| local obj = find_property_obj(item, prop)
| |
| if not obj then return nil end
| |
| | |
| return format_value_enhanced(
| |
| item_name, prop, obj.Value, obj.Type,
| |
| obj.LocTokenOverride, skip_label, allow_conditional, obj.UsageFlags
| |
| )
| |
| end
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- StatusEffect special formatting
| |
| --------------------------------------------------------------------------------
| |
| | |
| local function format_property_for_infobox(item_name, prop, skip_label, debug)
| |
| if prop:match("^StatusEffect") then
| |
| return string.format(
| |
| "[[{{#invoke:Lang|get_string|Citadel_%s}}]] [[{{#invoke:Lang|get_string|Citadel_StatusEffect}}]]",
| |
| prop
| |
| )
| |
| end
| |
| return format_stat(item_name, prop, skip_label, debug, true)
| |
| end
| |
| | |
| local function format_property_for_infobox_enhanced(item_name, prop)
| |
| if prop:match("^StatusEffect") then
| |
| return string.format(
| |
| "[[{{#invoke:Lang|get_string|Citadel_%s}}]] [[{{#invoke:Lang|get_string|Citadel_StatusEffect}}]]",
| |
| prop
| |
| )
| |
| end
| |
| return format_stat_enhanced(item_name, prop)
| |
| end
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- Tooltip builder helpers
| |
| --------------------------------------------------------------------------------
| |
| | |
| -- Format the Cooldown / ChargeUp fields that sit directly on an Info section
| |
| local function format_section_cooldown(section, item_name, enhanced)
| |
| local result = {}
| |
| if section.Cooldown and section.Cooldown ~= 0 then
| |
| if enhanced then
| |
| result.cooldown = format_value_enhanced( | |
| item_name, "AbilityCooldown", section.Cooldown,
| |
| nil, nil, true, false, nil
| |
| )
| |
| else | | else |
| result.cooldown = format_value( | | displayName = iconInfo.name |
| "AbilityCooldown", section.Cooldown,
| |
| nil, nil, true, false, nil, nil
| |
| )
| |
| end | | end |
| end | | end |
| if section.ChargeUp and section.ChargeUp ~= 0 then
| |
| if enhanced then
| |
| result.chargeup = format_value_enhanced(
| |
| item_name, "AbilityChargeUpTime", section.ChargeUp,
| |
| nil, nil, true, false, nil
| |
| )
| |
| else
| |
| result.chargeup = format_value(
| |
| "AbilityChargeUpTime", section.ChargeUp,
| |
| nil, nil, true, false, nil, nil
| |
| )
| |
| end
| |
| end
| |
| return result
| |
| end
| |
|
| |
|
| -- Iterate a property list (Main or Alt), format each, and append to lines | | -- Link logic |
| -- Returns the next stat_index
| | local baseLink = linkOverrides[iconInfo.name] or iconInfo.link or "" |
| local function process_stats(lines, fmt, counter, start_index, prop_list,
| | local link = baseLink |
| item_name, seen, formatter)
| | if langCode ~= "en" and baseLink ~= "" then |
| local stat_index = start_index | | link = baseLink .. "/" .. langCode |
| for _, prop_obj in ipairs(prop_list or {}) do | |
| local key = prop_obj.Key
| |
| if is_property_in_lang_data(key, prop_obj.LocTokenOverride) and not seen[key] then
| |
| local val = formatter(prop_obj)
| |
| if val then
| |
| table.insert(lines, string.format(fmt, counter, stat_index, val))
| |
| stat_index = stat_index + 1
| |
| seen[key] = true
| |
| end
| |
| end
| |
| end | | end |
| return stat_index
| |
| end
| |
|
| |
|
| -------------------------------------------------------------------------------- | | -- Style logic |
| -- Build default (non-enhanced) tooltip
| | local style |
| --------------------------------------------------------------------------------
| | if iconInfo.class and iconInfo.class:find("theme", 1, true) then |
| | | style = 'class="module-icon-ability" style="position:relative; bottom:2px;"' |
| local function build_tooltip(frame)
| | else |
| local item_name = frame.args[1] | | style = 'style="position:relative; bottom:2px;"' |
| if not item_name then return "Item name missing", 0 end | |
| | |
| local debug = tonumber(frame.args.debug) or 0
| |
| local item = get_json_item(item_name)
| |
| if not item then return "Item not found", debug end
| |
| | |
| local ItemData = require("Module:ItemData")
| |
| local lines = { | |
| "{{Infobox item",
| |
| "| item_name = " .. item_name | |
| }
| |
| | |
| if item.StreetBrawl == true then
| |
| table.insert(lines, "| street_brawl = true")
| |
| end | | end |
|
| |
|
| local sections = get_info_sections(item) | | -- Render |
| | local imageLink = noLink and "" or link |
| | local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, iconInfo.image, size, imageLink) |
|
| |
|
| ------------------------------------------------------------------ | | if iconOnly or displayName == "" then |
| -- Innate stats
| | return iconHtml |
| ------------------------------------------------------------------
| |
| local innate_index = 1
| |
| for _, section in ipairs(sections) do
| |
| if section.Type == "Innate" then
| |
| for _, prop_obj in ipairs(section.Alt or {}) do
| |
| if is_property_in_lang_data(prop_obj.Key, prop_obj.LocTokenOverride) then
| |
| local val = format_value(
| |
| prop_obj.Key, prop_obj.Value, prop_obj.Type,
| |
| prop_obj.LocTokenOverride, false, false,
| |
| prop_obj.UsageFlags, prop_obj.Scale
| |
| )
| |
| if val then
| |
| table.insert(lines, string.format("| item_stat%d = %s", innate_index, val))
| |
| innate_index = innate_index + 1
| |
| end
| |
| end
| |
| end
| |
| local cd = format_section_cooldown(section, item_name, false)
| |
| if cd.cooldown then table.insert(lines, "| item_stat_cooldown = " .. cd.cooldown) end
| |
| if cd.chargeup then table.insert(lines, "| item_stat_chargeup = " .. cd.chargeup) end
| |
| end | |
| end | | end |
|
| |
|
| ------------------------------------------------------------------
| | local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName) |
| -- Passive stats (any section that is not Innate or Active)
| | return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>' |
| ------------------------------------------------------------------
| |
| local passive_counter = 1 | |
| for _, section in ipairs(sections) do
| |
| if section.Type ~= "Innate" and section.Type ~= "Active" then
| |
| local loc = section.DescKey and section.DescKey:gsub("#", "") or nil
| |
| if loc and loc ~= "" then
| |
| table.insert(lines, string.format(
| |
| "| passive%d_description = {{#invoke:Lang|get_string|%s|item_name=%s}}",
| |
| passive_counter, loc, item_name
| |
| ))
| |
| end
| |
| | |
| local stat_index = 1
| |
| local seen = {}
| |
| | |
| -- Main (important properties) — allow_conditional = true
| |
| stat_index = process_stats(
| |
| lines, "| passive%d_stat%d = %s", passive_counter, stat_index,
| |
| section.Main, item_name, seen,
| |
| function(obj)
| |
| return format_value(
| |
| obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,
| |
| false, true, obj.UsageFlags, obj.Scale
| |
| )
| |
| end
| |
| )
| |
| | |
| -- Alt (regular properties) — allow_conditional = false
| |
| process_stats(
| |
| lines, "| passive%d_stat%d = %s", passive_counter, stat_index,
| |
| section.Alt, item_name, seen,
| |
| function(obj)
| |
| return format_value(
| |
| obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,
| |
| false, false, obj.UsageFlags, obj.Scale
| |
| )
| |
| end
| |
| )
| |
| | |
| local cd = format_section_cooldown(section, item_name, false)
| |
| if cd.cooldown then
| |
| table.insert(lines, string.format("| passive%d_cooldown = %s", passive_counter, cd.cooldown))
| |
| end
| |
| if cd.chargeup then
| |
| table.insert(lines, string.format("| passive%d_chargeup = %s", passive_counter, cd.chargeup))
| |
| end
| |
| | |
| passive_counter = passive_counter + 1
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Active stats
| |
| ------------------------------------------------------------------
| |
| local active_index = 1
| |
| for _, section in ipairs(sections) do
| |
| if section.Type == "Active" then
| |
| local loc = section.DescKey and section.DescKey:gsub("#", "") or nil
| |
| if loc and loc ~= "" then
| |
| table.insert(lines, string.format(
| |
| "| active%d_description = {{#invoke:Lang|get_string|%s|item_name=%s}}",
| |
| active_index, loc, item_name
| |
| ))
| |
| end
| |
| | |
| local stat_index = 1
| |
| local seen = {}
| |
| | |
| stat_index = process_stats(
| |
| lines, "| active%d_stat%d = %s", active_index, stat_index,
| |
| section.Main, item_name, seen,
| |
| function(obj)
| |
| return format_value(
| |
| obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,
| |
| false, true, obj.UsageFlags, obj.Scale
| |
| )
| |
| end
| |
| )
| |
| | |
| process_stats(
| |
| lines, "| active%d_stat%d = %s", active_index, stat_index,
| |
| section.Alt, item_name, seen,
| |
| function(obj)
| |
| return format_value(
| |
| obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,
| |
| false, false, obj.UsageFlags, obj.Scale
| |
| )
| |
| end
| |
| )
| |
| | |
| local cd = format_section_cooldown(section, item_name, false)
| |
| if cd.cooldown then
| |
| table.insert(lines, string.format("| active%d_cooldown = %s", active_index, cd.cooldown))
| |
| end
| |
| if cd.chargeup then
| |
| table.insert(lines, string.format("| active%d_chargeup = %s", active_index, cd.chargeup))
| |
| end
| |
| | |
| active_index = active_index + 1
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Components
| |
| ------------------------------------------------------------------
| |
| for i = 1, 2 do
| |
| local comp = ItemData.get_component_name { args = { item_name, i } }
| |
| if comp and comp ~= "" then
| |
| table.insert(lines, string.format("| component%d_name = %s", i, comp))
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Is Component Of (sorted by tier)
| |
| ------------------------------------------------------------------
| |
| local parents = get_component_of_sorted(item_name)
| |
| for i, key in ipairs(parents) do
| |
| local parent_name = data[key] and data[key].Name or ""
| |
| if parent_name ~= "" then
| |
| table.insert(lines, string.format("| iscomponentof%d_name = %s", i, parent_name))
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Sounds
| |
| ------------------------------------------------------------------
| |
| for key, value in pairs(frame.args) do
| |
| local index = tostring(key):match("^sound(%d+)$")
| |
| if index and value ~= "" then
| |
| table.insert(lines, string.format("| sound%s = %s", index, value))
| |
| end
| |
| end
| |
| | |
| table.insert(lines, "}}")
| |
| return table.concat(lines, "\n"), debug
| |
| end
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- Build enhanced tooltip
| |
| --------------------------------------------------------------------------------
| |
| | |
| local function build_tooltip_enhanced(frame)
| |
| local item_name = frame.args[1]
| |
| if not item_name then return "Item name missing" end
| |
| | |
| local item = get_json_item(item_name)
| |
| if not item then return "Item not found" end
| |
| | |
| local ItemData = require("Module:ItemData")
| |
| local lines = {
| |
| "{{Infobox item",
| |
| "| enhanced = true",
| |
| "| item_name = " .. item_name
| |
| }
| |
| | |
| if item.StreetBrawl == true then
| |
| table.insert(lines, "| street_brawl = true")
| |
| end
| |
| | |
| local sections = get_info_sections(item)
| |
| | |
| ------------------------------------------------------------------
| |
| -- Innate stats (Enhanced)
| |
| ------------------------------------------------------------------ | |
| local innate_index = 1
| |
| for _, section in ipairs(sections) do
| |
| if section.Type == "Innate" then
| |
| for _, prop_obj in ipairs(section.Alt or {}) do
| |
| if is_property_in_lang_data(prop_obj.Key, prop_obj.LocTokenOverride) then
| |
| local val = format_value_enhanced(
| |
| item_name, prop_obj.Key, prop_obj.Value, prop_obj.Type,
| |
| prop_obj.LocTokenOverride, nil, false, prop_obj.UsageFlags
| |
| )
| |
| if val then
| |
| table.insert(lines, string.format("| item_stat%d = %s", innate_index, val))
| |
| innate_index = innate_index + 1
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Passive stats (Enhanced)
| |
| ------------------------------------------------------------------
| |
| local passive_counter = 1
| |
| for _, section in ipairs(sections) do
| |
| if section.Type ~= "Innate" and section.Type ~= "Active" then
| |
| local loc = section.DescKey and section.DescKey:gsub("#", "") or nil
| |
| if loc and loc ~= "" then
| |
| table.insert(lines, string.format(
| |
| "| passive%d_description = {{#invoke:Lang|get_string|%s|item_name=%s}}",
| |
| passive_counter, loc, item_name
| |
| ))
| |
| end
| |
| | |
| local stat_index = 1
| |
| local seen = {}
| |
| | |
| -- Main — use format_property_for_infobox_enhanced (handles StatusEffect)
| |
| stat_index = process_stats(
| |
| lines, "| passive%d_stat%d = %s", passive_counter, stat_index,
| |
| section.Main, item_name, seen,
| |
| function(obj)
| |
| return format_property_for_infobox_enhanced(item_name, obj.Key)
| |
| end
| |
| )
| |
| | |
| -- Alt — use format_value_enhanced directly
| |
| process_stats(
| |
| lines, "| passive%d_stat%d = %s", passive_counter, stat_index,
| |
| section.Alt, item_name, seen,
| |
| function(obj)
| |
| return format_value_enhanced(
| |
| item_name, obj.Key, obj.Value, obj.Type,
| |
| obj.LocTokenOverride, nil, false, obj.UsageFlags
| |
| )
| |
| end
| |
| )
| |
| | |
| local cd = format_section_cooldown(section, item_name, true)
| |
| if cd.cooldown then
| |
| table.insert(lines, string.format("| passive%d_cooldown = %s", passive_counter, cd.cooldown))
| |
| end
| |
| if cd.chargeup then
| |
| table.insert(lines, string.format("| passive%d_chargeup = %s", passive_counter, cd.chargeup))
| |
| end
| |
| | |
| passive_counter = passive_counter + 1
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Active stats (Enhanced)
| |
| ------------------------------------------------------------------
| |
| local active_index = 1
| |
| for _, section in ipairs(sections) do
| |
| if section.Type == "Active" then
| |
| local loc = section.DescKey and section.DescKey:gsub("#", "") or nil
| |
| if loc and loc ~= "" then
| |
| table.insert(lines, string.format(
| |
| "| active%d_description = {{#invoke:Lang|get_string|%s|item_name=%s}}",
| |
| active_index, loc, item_name
| |
| ))
| |
| end
| |
| | |
| local stat_index = 1
| |
| local seen = {}
| |
| | |
| stat_index = process_stats(
| |
| lines, "| active%d_stat%d = %s", active_index, stat_index,
| |
| section.Main, item_name, seen,
| |
| function(obj)
| |
| return format_property_for_infobox_enhanced(item_name, obj.Key)
| |
| end
| |
| )
| |
| | |
| process_stats(
| |
| lines, "| active%d_stat%d = %s", active_index, stat_index,
| |
| section.Alt, item_name, seen,
| |
| function(obj)
| |
| return format_value_enhanced(
| |
| item_name, obj.Key, obj.Value, obj.Type,
| |
| obj.LocTokenOverride, nil, false, obj.UsageFlags
| |
| )
| |
| end
| |
| )
| |
| | |
| local cd = format_section_cooldown(section, item_name, true)
| |
| if cd.cooldown then
| |
| table.insert(lines, string.format("| active%d_cooldown = %s", active_index, cd.cooldown))
| |
| end
| |
| if cd.chargeup then
| |
| table.insert(lines, string.format("| active%d_chargeup = %s", active_index, cd.chargeup))
| |
| end
| |
| | |
| active_index = active_index + 1
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Components
| |
| ------------------------------------------------------------------
| |
| for i = 1, 2 do
| |
| local comp = ItemData.get_component_name { args = { item_name, i } }
| |
| if comp and comp ~= "" then
| |
| table.insert(lines, string.format("| component%d_name = %s", i, comp))
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Is Component Of (sorted by tier)
| |
| ------------------------------------------------------------------
| |
| local parents = get_component_of_sorted(item_name)
| |
| for i, key in ipairs(parents) do
| |
| local parent_name = data[key] and data[key].Name or ""
| |
| if parent_name ~= "" then
| |
| table.insert(lines, string.format("| iscomponentof%d_name = %s", i, parent_name))
| |
| end
| |
| end
| |
| | |
| ------------------------------------------------------------------
| |
| -- Sounds
| |
| ------------------------------------------------------------------
| |
| for key, value in pairs(frame.args) do
| |
| local index = tostring(key):match("^sound(%d+)$")
| |
| if index and value ~= "" then
| |
| table.insert(lines, string.format("| sound%s = %s", index, value))
| |
| end
| |
| end
| |
| | |
| table.insert(lines, "}}")
| |
| return table.concat(lines, "\n")
| |
| end
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- Public interface
| |
| --------------------------------------------------------------------------------
| |
| | |
| function p.fill_tooltip(frame)
| |
| local output, debug = build_tooltip(frame)
| |
| if debug == 1 or debug == 2 then return output end
| |
| return mw.getCurrentFrame():preprocess(output)
| |
| end
| |
| | |
| function p.fill_tooltip_enhanced(frame)
| |
| return mw.getCurrentFrame():preprocess(build_tooltip_enhanced(frame))
| |
| end
| |
| | |
| function p.render(frame)
| |
| local output_lines = { "<tabber>" }
| |
| table.insert(output_lines, "Default=")
| |
| local tooltip, _ = build_tooltip(frame)
| |
| table.insert(output_lines, tooltip)
| |
| table.insert(output_lines, "|-|")
| |
| table.insert(output_lines, "Enhanced=")
| |
| table.insert(output_lines, build_tooltip_enhanced(frame))
| |
| table.insert(output_lines, "</tabber>")
| |
| return mw.getCurrentFrame():preprocess(table.concat(output_lines, "\n"))
| |
| end | | end |
|
| |
|
| return p | | return p |