<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://deadlock.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=~2026-EnduringDurationJump1108</id>
	<title>The Deadlock Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://deadlock.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=~2026-EnduringDurationJump1108"/>
	<link rel="alternate" type="text/html" href="https://deadlock.wiki/Special:Contributions/~2026-EnduringDurationJump1108"/>
	<updated>2026-09-10T23:08:49Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://deadlock.wiki/Module:Sandbox/Vergir?diff=127645</id>
		<title>Module:Sandbox/Vergir</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/Module:Sandbox/Vergir?diff=127645"/>
		<updated>2026-09-07T00:11:17Z</updated>

		<summary type="html">&lt;p&gt;~2026-EnduringDurationJump1108: Cleanup after audit (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>~2026-EnduringDurationJump1108</name></author>
	</entry>
	<entry>
		<id>https://deadlock.wiki/User:Vergir/test1?diff=127644</id>
		<title>User:Vergir/test1</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/User:Vergir/test1?diff=127644"/>
		<updated>2026-09-07T00:11:15Z</updated>

		<summary type="html">&lt;p&gt;~2026-EnduringDurationJump1108: Cleanup after audit (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>~2026-EnduringDurationJump1108</name></author>
	</entry>
	<entry>
		<id>https://deadlock.wiki/Module:Infobox_item?diff=127642</id>
		<title>Module:Infobox item</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/Module:Infobox_item?diff=127642"/>
		<updated>2026-09-07T00:05:58Z</updated>

		<summary type="html">&lt;p&gt;~2026-EnduringDurationJump1108: 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)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
local lang = require &amp;quot;Module:Lang&amp;quot;&lt;br /&gt;
local util_module = require &amp;quot;Module:Utilities&amp;quot;&lt;br /&gt;
local data = mw.loadJsonData(&amp;quot;Data:ItemCards.json&amp;quot;)&lt;br /&gt;
local stat_links = mw.loadJsonData(&amp;quot;Data:StatLinks.json&amp;quot;)&lt;br /&gt;
local ATTR_TYPE_ICON_MAP = require(&amp;quot;Module:Icon/attr&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
-- Local references for hot-path globals&lt;br /&gt;
local format = string.format&lt;br /&gt;
local concat = table.concat&lt;br /&gt;
local insert = table.insert&lt;br /&gt;
local ipairs = ipairs&lt;br /&gt;
local pairs = pairs&lt;br /&gt;
local tonumber = tonumber&lt;br /&gt;
local tostring = tostring&lt;br /&gt;
local type = type&lt;br /&gt;
&lt;br /&gt;
-- Status Effect Icon Map&lt;br /&gt;
local STATUS_EFFECT_ICON_MAP = {&lt;br /&gt;
    StatusEffectDisarmed = {img=&#039;Status_Disarm.png&#039;,        link=&#039;Disarm&#039;,   color=&#039;Red&#039;},&lt;br /&gt;
    StatusEffectEMP      = {img=&#039;Status_Silence.png&#039;,       link=&#039;Silence&#039;,  color=&#039;Purple&#039;},&lt;br /&gt;
    StatusEffectInvisible= {img=&#039;Invisible.png&#039;,            link=&#039;Invisible&#039;,color=&#039;Green&#039;},&lt;br /&gt;
    StatusEffectStun     = {img=&#039;Status_Stun.png&#039;,          link=&#039;Stun&#039;,     color=&#039;NoColor&#039;},&lt;br /&gt;
    StatusEffectSlow     = {img=&#039;Status_Movement_Slow.png&#039;, link=&#039;Slow&#039;,     color=&#039;Purple&#039;},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Pre-computed constants&lt;br /&gt;
local STATUS_FMT = &amp;quot;[[{{#invoke:Lang|get_string|Citadel_%s}}]]&amp;quot;&lt;br /&gt;
    .. &amp;quot; [[{{#invoke:Lang|get_string|Citadel_StatusEffect}}]]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
-- Property keys to completely ignore during processing&lt;br /&gt;
local IGNORED_PROP_KEYS = {&lt;br /&gt;
    BuildUpPerShot = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Label key remapping table (replaces if/elseif chain)&lt;br /&gt;
local LABEL_KEY_REMAP = {&lt;br /&gt;
    DotDuration    = &amp;quot;DOTDuration&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Item name override mapping (old name -&amp;gt; new name)&lt;br /&gt;
local ITEM_NAME_OVERRIDES = {&lt;br /&gt;
    [&amp;quot;debuff remover&amp;quot;] = &amp;quot;Dispel Magic&amp;quot;,&lt;br /&gt;
    [&amp;quot;backstabber&amp;quot;] = &amp;quot;Stalker&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Suffix pairs for lang data existence checks&lt;br /&gt;
local LANG_SUFFIX_PAIRS = {&lt;br /&gt;
    { &amp;quot;_label&amp;quot;,          &amp;quot;_Label&amp;quot; },&lt;br /&gt;
    { &amp;quot;_prefix&amp;quot;,         &amp;quot;_Prefix&amp;quot; },&lt;br /&gt;
    { &amp;quot;_postfix&amp;quot;,        &amp;quot;_Postfix&amp;quot; },&lt;br /&gt;
    { &amp;quot;_postvalue_label&amp;quot;, &amp;quot;_Postvalue_Label&amp;quot; },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Caches&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local lang_cache = {}&lt;br /&gt;
local info_sections_cache = setmetatable({}, { __mode = &amp;quot;k&amp;quot; }) -- weak keys&lt;br /&gt;
&lt;br /&gt;
local function cached_get_string(key)&lt;br /&gt;
    local v = lang_cache[key]&lt;br /&gt;
    if v ~= nil then return v or nil end -- false sentinel → nil&lt;br /&gt;
    local result = lang.get_string(key)&lt;br /&gt;
    lang_cache[key] = result or false&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local conditional_label -- lazily initialised&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Item name resolution&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function resolve_item_name(name)&lt;br /&gt;
    -- Check if there&#039;s an override for this name (case-insensitive)&lt;br /&gt;
    local lowercase_name = name:lower()&lt;br /&gt;
    local override = ITEM_NAME_OVERRIDES[lowercase_name]&lt;br /&gt;
    if override then&lt;br /&gt;
        return override&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- If no override, try to find the item in data and return its proper Name&lt;br /&gt;
    -- First try direct key lookup&lt;br /&gt;
    if data[name] and not data[name].IsDisabled then&lt;br /&gt;
        return data[name].Name or name&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Then try case-insensitive search by Name field&lt;br /&gt;
    local lowercase_search = name:lower()&lt;br /&gt;
    for _, v in pairs(data) do&lt;br /&gt;
        if v.Name and v.Name:lower() == lowercase_search and not v.IsDisabled then&lt;br /&gt;
            return v.Name&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Fallback to original name&lt;br /&gt;
    return name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Utility helpers&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function get_lang_pair(base_key, suffix1, suffix2)&lt;br /&gt;
    local v1 = cached_get_string(base_key .. suffix1)&lt;br /&gt;
    if v1 and v1 ~= &amp;quot;&amp;quot; then return v1 end&lt;br /&gt;
    local v2 = cached_get_string(base_key .. suffix2)&lt;br /&gt;
    if v2 and v2 ~= &amp;quot;&amp;quot; then return v2 end&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Data access helpers&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function get_json_item(name)&lt;br /&gt;
    -- Apply name override before lookup&lt;br /&gt;
    local resolved_name = resolve_item_name(name)&lt;br /&gt;
    &lt;br /&gt;
    local direct = data[resolved_name]&lt;br /&gt;
    if direct and not direct.IsDisabled then return direct end&lt;br /&gt;
&lt;br /&gt;
    local fallback&lt;br /&gt;
    for _, v in pairs(data) do&lt;br /&gt;
        if v.Name == resolved_name then&lt;br /&gt;
            if not v.IsDisabled then return v end&lt;br /&gt;
            fallback = fallback or v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return fallback&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_info_sections(item)&lt;br /&gt;
    local cached = info_sections_cache[item]&lt;br /&gt;
    if cached then return cached end&lt;br /&gt;
&lt;br /&gt;
    local sections = {}&lt;br /&gt;
    local i = 1&lt;br /&gt;
    while item[&amp;quot;Info&amp;quot; .. i] do&lt;br /&gt;
        sections[i] = item[&amp;quot;Info&amp;quot; .. i]&lt;br /&gt;
        i = i + 1&lt;br /&gt;
    end&lt;br /&gt;
    info_sections_cache[item] = sections&lt;br /&gt;
    return sections&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function find_property_obj(item, prop_key)&lt;br /&gt;
    for _, section in ipairs(get_info_sections(item)) do&lt;br /&gt;
        for _, obj in ipairs(section.Main or {}) do&lt;br /&gt;
            if obj.Key == prop_key then return obj end&lt;br /&gt;
        end&lt;br /&gt;
        for _, obj in ipairs(section.Alt or {}) do&lt;br /&gt;
            if obj.Key == prop_key then return obj end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    local other = item.Other&lt;br /&gt;
    return other and other[prop_key] or nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function is_property_in_lang_data(prop, loc_override)&lt;br /&gt;
    local has_override = loc_override and loc_override ~= prop&lt;br /&gt;
    for _, pair in ipairs(LANG_SUFFIX_PAIRS) do&lt;br /&gt;
        if cached_get_string(prop .. pair[1]) or cached_get_string(prop .. pair[2]) then&lt;br /&gt;
            return true&lt;br /&gt;
        end&lt;br /&gt;
        if has_override and (&lt;br /&gt;
            cached_get_string(loc_override .. pair[1]) or&lt;br /&gt;
            cached_get_string(loc_override .. pair[2])&lt;br /&gt;
        ) then&lt;br /&gt;
            return true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_component_of_sorted(item_input)&lt;br /&gt;
    -- Apply name override before processing&lt;br /&gt;
    local resolved_input = resolve_item_name(item_input)&lt;br /&gt;
    &lt;br /&gt;
    local target_key&lt;br /&gt;
    if data[resolved_input] then&lt;br /&gt;
        target_key = resolved_input&lt;br /&gt;
    else&lt;br /&gt;
        for k, v in pairs(data) do&lt;br /&gt;
            if v.Name == resolved_input and not v.IsDisabled then&lt;br /&gt;
                target_key = k&lt;br /&gt;
                break&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if not target_key then return {} end&lt;br /&gt;
&lt;br /&gt;
    local parents = {}&lt;br /&gt;
    for key, item in pairs(data) do&lt;br /&gt;
        if not item.IsDisabled and type(item.Components) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            for _, comp in ipairs(item.Components) do&lt;br /&gt;
                if comp == target_key then&lt;br /&gt;
                    insert(parents, key)&lt;br /&gt;
                    break&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    table.sort(parents, function(a, b)&lt;br /&gt;
        return (tonumber(data[a] and data[a].Tier) or 0)&lt;br /&gt;
             &amp;lt; (tonumber(data[b] and data[b].Tier) or 0)&lt;br /&gt;
    end)&lt;br /&gt;
    return parents&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Shared formatting primitives&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function resolve_label_key(prop_key, loc_override)&lt;br /&gt;
    local base = (loc_override or prop_key):gsub(&amp;quot;^#&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    return LABEL_KEY_REMAP[base] or base&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function resolve_prefix(prefix, numeric_val)&lt;br /&gt;
    if prefix == &amp;quot;{s:sign}&amp;quot; then&lt;br /&gt;
        return numeric_val &amp;gt;= 0 and &amp;quot;+&amp;quot; or &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return prefix&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function resolve_suffix(postfix, css_type)&lt;br /&gt;
    if postfix == &amp;quot;HP/s&amp;quot; then return &amp;quot;&amp;amp;#32;&amp;quot; .. postfix end&lt;br /&gt;
    return postfix&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function append_label(val_str, prop_key, label, attr_link, link_override, is_main)&lt;br /&gt;
    if label == &amp;quot;&amp;quot; then return val_str end&lt;br /&gt;
&lt;br /&gt;
    -- Resolve link priority: Override &amp;gt; JSON Stat Link &amp;gt; Attribute Map Link&lt;br /&gt;
    local link_target = link_override&lt;br /&gt;
    if not link_target or link_target == &amp;quot;&amp;quot; then&lt;br /&gt;
        link_target = stat_links[prop_key]&lt;br /&gt;
    end&lt;br /&gt;
    if not link_target or link_target == &amp;quot;&amp;quot; then&lt;br /&gt;
        link_target = attr_link&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Construct label with link if valid&lt;br /&gt;
    local display_label = label&lt;br /&gt;
    if link_target and link_target ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        if link_target == label then&lt;br /&gt;
            display_label = &amp;quot;[[&amp;quot; .. label .. &amp;quot;]]&amp;quot;&lt;br /&gt;
        else&lt;br /&gt;
            display_label = &amp;quot;[[&amp;quot; .. link_target .. &amp;quot;|&amp;quot; .. label .. &amp;quot;]]&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Place label on a new line only for Main stats&lt;br /&gt;
    if is_main then&lt;br /&gt;
        return val_str .. &amp;quot;&amp;lt;br&amp;gt;&amp;quot; .. display_label&lt;br /&gt;
    else&lt;br /&gt;
        return val_str .. &amp;quot; &amp;quot; .. display_label&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function append_conditional(val_str, allow_conditional, usage_flags)&lt;br /&gt;
    if not allow_conditional then return val_str end&lt;br /&gt;
    if usage_flags ~= &amp;quot;ConditionallyApplied&amp;quot;&lt;br /&gt;
       and usage_flags ~= &amp;quot;ConditionallyEnemyApplied&amp;quot; then&lt;br /&gt;
        return val_str&lt;br /&gt;
    end&lt;br /&gt;
    if not conditional_label then&lt;br /&gt;
        conditional_label = format(&lt;br /&gt;
            &#039;&amp;lt;span style=&amp;quot;color:#C0C0C0&amp;quot;&amp;gt;%s&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
            lang.get_string(&amp;quot;Citadel_Shop_ConditionalAttribute&amp;quot;)&lt;br /&gt;
        )&lt;br /&gt;
    end&lt;br /&gt;
    -- Place conditional text on a new line&lt;br /&gt;
    return val_str .. &amp;quot;&amp;lt;br&amp;gt;&amp;quot; .. conditional_label&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function extract_numeric(value)&lt;br /&gt;
    if value == nil or value == 0 or value == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
    local n = tonumber(tostring(value):match(&amp;quot;^-?%d+%.?%d*&amp;quot;))&lt;br /&gt;
    return (n and n ~= 0) and n or nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Attribute Icon/Style detection helper&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function resolve_attr_style(css_type)&lt;br /&gt;
    if not css_type then return nil end&lt;br /&gt;
    local attr = ATTR_TYPE_ICON_MAP[css_type]&lt;br /&gt;
    if not attr then return nil end&lt;br /&gt;
&lt;br /&gt;
    local color = attr.color or &amp;quot;Grey&amp;quot; -- Fallback color&lt;br /&gt;
    local img = attr.img or &amp;quot;GenericProperty.png&amp;quot;&lt;br /&gt;
    local link = attr.link&lt;br /&gt;
    local size = attr.size -- Optional&lt;br /&gt;
&lt;br /&gt;
    -- Construct icon using the defined color template: {{Icon/Color|img|size|link=link}}&lt;br /&gt;
    local icon_str&lt;br /&gt;
    if size and size ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        icon_str = format(&amp;quot;{{Icon/%s|[[File:%s|%spx|link=%s]]}}&amp;quot;, color, img, size, link or &amp;quot;&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
        icon_str = format(&amp;quot;{{Icon/%s|[[File:%s|%spx|link=%s]]}}&amp;quot;, color, img, 18, link or &amp;quot;&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        icon = icon_str,&lt;br /&gt;
        link = link&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Status Effect Icon helper&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function resolve_status_effect_icon(prop_key)&lt;br /&gt;
    local effect_config = STATUS_EFFECT_ICON_MAP[prop_key]&lt;br /&gt;
    if not effect_config then return nil end&lt;br /&gt;
&lt;br /&gt;
    local color = effect_config.color or &amp;quot;NoColor&amp;quot;&lt;br /&gt;
    local img = effect_config.img or &amp;quot;GenericProperty.png&amp;quot;&lt;br /&gt;
    local link = effect_config.link&lt;br /&gt;
&lt;br /&gt;
    -- Construct icon using the defined color template&lt;br /&gt;
    local icon_str = format(&lt;br /&gt;
        &amp;quot;{{Icon/%s|[[File:%s|18px|link=%s]]}}&amp;quot;,&lt;br /&gt;
        color, img, link or &amp;quot;&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        icon = icon_str,&lt;br /&gt;
        link = link&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Core formatting: non-enhanced&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function format_value(prop_key, value, css_type, loc_override,&lt;br /&gt;
                            skip_label, allow_conditional, usage_flags, scale_info,&lt;br /&gt;
                            disable_attr, is_main)&lt;br /&gt;
    local numeric_val = extract_numeric(value)&lt;br /&gt;
    if not numeric_val then return nil end&lt;br /&gt;
&lt;br /&gt;
    local label_key = resolve_label_key(prop_key, loc_override)&lt;br /&gt;
    local label   = skip_label and &amp;quot;&amp;quot; or get_lang_pair(label_key, &amp;quot;_label&amp;quot;, &amp;quot;_Label&amp;quot;)&lt;br /&gt;
    local prefix  = get_lang_pair(label_key, &amp;quot;_prefix&amp;quot;, &amp;quot;_Prefix&amp;quot;)&lt;br /&gt;
    local postfix = get_lang_pair(label_key, &amp;quot;_postfix&amp;quot;, &amp;quot;_Postfix&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if prefix == &amp;quot;&amp;quot; and postfix == &amp;quot;&amp;quot; and label == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
&lt;br /&gt;
    prefix = resolve_prefix(prefix, numeric_val)&lt;br /&gt;
    local suffix = resolve_suffix(postfix, css_type)&lt;br /&gt;
&lt;br /&gt;
    -- Compose numeric + scaling first&lt;br /&gt;
    local val_str = tostring(numeric_val)&lt;br /&gt;
    if scale_info and scale_info.Value and scale_info.Value ~= 0 then&lt;br /&gt;
        local scale_val = util_module.round_to_sig_fig(scale_info.Value, 2)&lt;br /&gt;
        local tmpl = scale_info.Type == &amp;quot;power_increase&amp;quot; and &amp;quot;Boon&amp;quot; or &amp;quot;Ss&amp;quot;&lt;br /&gt;
        val_str = val_str .. &amp;quot; &amp;quot; .. mw.getCurrentFrame():expandTemplate{&lt;br /&gt;
            title = tmpl, args = { scale_val }&lt;br /&gt;
        }&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Then prepend prefix&lt;br /&gt;
    if prefix ~= &amp;quot;&amp;quot; then val_str = prefix .. val_str end&lt;br /&gt;
    -- Then append postfix&lt;br /&gt;
    if suffix ~= &amp;quot;&amp;quot; and not val_str:find(suffix, 1, true) then&lt;br /&gt;
        val_str = val_str .. suffix&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Attribute styling (Icon via template) based on css_type&lt;br /&gt;
    local attr_style&lt;br /&gt;
    if not disable_attr then&lt;br /&gt;
        attr_style = resolve_attr_style(css_type)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    if attr_style and attr_style.icon then&lt;br /&gt;
        val_str = attr_style.icon .. &amp;quot; &amp;quot; .. val_str&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    val_str = append_label(val_str, label_key, label,&lt;br /&gt;
        attr_style and attr_style.link or nil,&lt;br /&gt;
        nil, is_main) -- link_override not used here in base calls&lt;br /&gt;
&lt;br /&gt;
    return append_conditional(val_str, allow_conditional, usage_flags)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Core formatting: enhanced&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function format_value_enhanced(item_name, prop_key, value, css_type,&lt;br /&gt;
                                     loc_override, skip_label,&lt;br /&gt;
                                     allow_conditional, usage_flags,&lt;br /&gt;
                                     disable_attr, is_main)&lt;br /&gt;
    local numeric_val = extract_numeric(value)&lt;br /&gt;
    if not numeric_val then return nil end&lt;br /&gt;
&lt;br /&gt;
    local label_key = resolve_label_key(prop_key, loc_override)&lt;br /&gt;
&lt;br /&gt;
    -- Enhanced requires at least one lang token to exist&lt;br /&gt;
    local has_lang = false&lt;br /&gt;
    for _, pair in ipairs(LANG_SUFFIX_PAIRS) do&lt;br /&gt;
        if cached_get_string(label_key .. pair[1])&lt;br /&gt;
           or cached_get_string(label_key .. pair[2]) then&lt;br /&gt;
            has_lang = true&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if not has_lang then return nil end&lt;br /&gt;
&lt;br /&gt;
    local label   = skip_label and &amp;quot;&amp;quot; or get_lang_pair(label_key, &amp;quot;_label&amp;quot;, &amp;quot;_Label&amp;quot;)&lt;br /&gt;
    local prefix  = get_lang_pair(label_key, &amp;quot;_prefix&amp;quot;, &amp;quot;_Prefix&amp;quot;)&lt;br /&gt;
    local postfix = get_lang_pair(label_key, &amp;quot;_postfix&amp;quot;, &amp;quot;_Postfix&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if prefix == &amp;quot;&amp;quot; and postfix == &amp;quot;&amp;quot; and label == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
&lt;br /&gt;
    prefix = resolve_prefix(prefix, numeric_val)&lt;br /&gt;
    local suffix = resolve_suffix(postfix, css_type)&lt;br /&gt;
&lt;br /&gt;
    -- Build Enhanced invoke&lt;br /&gt;
    local extras = {}&lt;br /&gt;
    if prefix ~= &amp;quot;&amp;quot; then insert(extras, &amp;quot;prefix=&amp;quot; .. prefix) end&lt;br /&gt;
    if suffix ~= &amp;quot;&amp;quot; and suffix ~= &amp;quot;%&amp;quot; then insert(extras, &amp;quot;suffix=&amp;quot; .. suffix) end&lt;br /&gt;
    insert(extras, &amp;quot;noicon=true&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    local val_str = format(&lt;br /&gt;
        &amp;quot;{{#invoke:Enhanced|render|%s|%s|%s}}&amp;quot;,&lt;br /&gt;
        item_name, prop_key, concat(extras, &amp;quot;|&amp;quot;)&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    -- Append postfix if not already present&lt;br /&gt;
    if postfix ~= &amp;quot;&amp;quot; and postfix ~= &amp;quot;%&amp;quot; and not val_str:find(postfix, 1, true) then&lt;br /&gt;
        val_str = val_str .. (postfix == &amp;quot;HP/s&amp;quot; and (&amp;quot; &amp;quot; .. postfix) or postfix)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Attribute styling (Icon via template) based on css_type&lt;br /&gt;
    local attr_style&lt;br /&gt;
    if not disable_attr then&lt;br /&gt;
        attr_style = resolve_attr_style(css_type)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if attr_style and attr_style.icon then&lt;br /&gt;
        val_str = attr_style.icon .. &amp;quot; &amp;quot; .. val_str&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    val_str = append_label(val_str, label_key, label,&lt;br /&gt;
        attr_style and attr_style.link or nil,&lt;br /&gt;
        nil, is_main)&lt;br /&gt;
&lt;br /&gt;
    return append_conditional(val_str, allow_conditional, usage_flags)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Status Effect formatting helper&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function format_status_effect(prop_key)&lt;br /&gt;
    local lang_str = format(&amp;quot;[[{{#invoke:Lang|get_string|Citadel_%s}}]]&amp;quot;, prop_key)&lt;br /&gt;
        .. &amp;quot; [[{{#invoke:Lang|get_string|Citadel_StatusEffect}}]]&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    -- Get icon for this status effect&lt;br /&gt;
    local icon_style = resolve_status_effect_icon(prop_key)&lt;br /&gt;
    if icon_style and icon_style.icon then&lt;br /&gt;
        return icon_style.icon .. &amp;quot; &amp;quot; .. lang_str&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return lang_str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Tooltip builder helpers&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function format_section_cooldown(section, item_name, enhanced)&lt;br /&gt;
    local result = {}&lt;br /&gt;
    local cd, cu = section.Cooldown, section.ChargeUp&lt;br /&gt;
    if cd and cd ~= 0 then&lt;br /&gt;
        result.cooldown = enhanced&lt;br /&gt;
            and format_value_enhanced(item_name, &amp;quot;AbilityCooldown&amp;quot;, cd, nil, nil, true, false, nil)&lt;br /&gt;
            or  format_value(&amp;quot;AbilityCooldown&amp;quot;, cd, nil, nil, true, false, nil, nil)&lt;br /&gt;
    end&lt;br /&gt;
    if cu and cu ~= 0 then&lt;br /&gt;
        result.chargeup = enhanced&lt;br /&gt;
            and format_value_enhanced(item_name, &amp;quot;AbilityChargeUpTime&amp;quot;, cu, nil, nil, true, false, nil)&lt;br /&gt;
            or  format_value(&amp;quot;AbilityChargeUpTime&amp;quot;, cu, nil, nil, true, false, nil, nil)&lt;br /&gt;
    end&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function process_stat_list(lines, param_fmt, counter, start_index,&lt;br /&gt;
                                 prop_list, seen, formatter)&lt;br /&gt;
    local stat_index = start_index&lt;br /&gt;
    for _, prop_obj in ipairs(prop_list or {}) do&lt;br /&gt;
        local key = prop_obj.Key&lt;br /&gt;
        if not seen[key] and not IGNORED_PROP_KEYS[key] and (&lt;br /&gt;
            key:match(&amp;quot;^StatusEffect&amp;quot;)&lt;br /&gt;
            or is_property_in_lang_data(key, prop_obj.LocTokenOverride)&lt;br /&gt;
        ) then&lt;br /&gt;
            local val = formatter(prop_obj)&lt;br /&gt;
            if val then&lt;br /&gt;
                insert(lines, format(param_fmt, counter, stat_index, val))&lt;br /&gt;
                stat_index = stat_index + 1&lt;br /&gt;
                seen[key] = true&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return stat_index&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Unified tooltip builder (handles both default and enhanced modes)&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
local function build_tooltip_impl(frame, enhanced)&lt;br /&gt;
    local item_name = frame.args[1]&lt;br /&gt;
    if not item_name then return &amp;quot;Item name missing&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    -- Resolve the item name (apply override if exists)&lt;br /&gt;
    local resolved_name = resolve_item_name(item_name)&lt;br /&gt;
&lt;br /&gt;
    local item = get_json_item(item_name)&lt;br /&gt;
    if not item then return &amp;quot;Item not found&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local ItemData = require(&amp;quot;Module:ItemData&amp;quot;)&lt;br /&gt;
    local lines = { &amp;quot;{{Infobox item&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
    if enhanced then&lt;br /&gt;
        insert(lines, &amp;quot;| enhanced = true&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- Use resolved name for item_name parameter&lt;br /&gt;
    insert(lines, &amp;quot;| item_name = &amp;quot; .. resolved_name)&lt;br /&gt;
&lt;br /&gt;
    if item.StreetBrawl == true then&lt;br /&gt;
        insert(lines, &amp;quot;| street_brawl = true&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Pass through nocat arg to the Infobox item template if provided&lt;br /&gt;
    local nocat = frame.args.nocat&lt;br /&gt;
    if nocat and nocat ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        insert(lines, &amp;quot;| nocat = &amp;quot; .. nocat)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local sections = get_info_sections(item)&lt;br /&gt;
&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    -- Innate stats (Main and Alt merged into item_stat sequentially)&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    local innate_index = 1&lt;br /&gt;
    for _, section in ipairs(sections) do&lt;br /&gt;
        if section.Type == &amp;quot;Innate&amp;quot; then&lt;br /&gt;
            for _, obj in ipairs(section.Main or {}) do&lt;br /&gt;
                if not IGNORED_PROP_KEYS[obj.Key] and is_property_in_lang_data(obj.Key, obj.LocTokenOverride) then&lt;br /&gt;
                    local val&lt;br /&gt;
                    if enhanced then&lt;br /&gt;
                        val = format_value_enhanced(&lt;br /&gt;
                            resolved_name, obj.Key, obj.Value, obj.Type, &lt;br /&gt;
                            obj.LocTokenOverride, nil, false, obj.UsageFlags, &lt;br /&gt;
                            true -- disable_attr&lt;br /&gt;
                        )&lt;br /&gt;
                    else&lt;br /&gt;
                        val = format_value(&lt;br /&gt;
                            obj.Key, obj.Value, obj.Type, obj.LocTokenOverride, &lt;br /&gt;
                            false, false, obj.UsageFlags, obj.Scale, &lt;br /&gt;
                            true -- disable_attr&lt;br /&gt;
                        )&lt;br /&gt;
                    end&lt;br /&gt;
                    if val then&lt;br /&gt;
                        insert(lines, format(&amp;quot;| item_stat%d = %s&amp;quot;, innate_index, val))&lt;br /&gt;
                        innate_index = innate_index + 1&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            for _, obj in ipairs(section.Alt or {}) do&lt;br /&gt;
                if not IGNORED_PROP_KEYS[obj.Key] and is_property_in_lang_data(obj.Key, obj.LocTokenOverride) then&lt;br /&gt;
                    local val&lt;br /&gt;
                    if enhanced then&lt;br /&gt;
                        val = format_value_enhanced(&lt;br /&gt;
                            resolved_name, obj.Key, obj.Value, obj.Type,&lt;br /&gt;
                            obj.LocTokenOverride, nil, false, obj.UsageFlags,&lt;br /&gt;
                            true -- disable_attr&lt;br /&gt;
                        )&lt;br /&gt;
                    else&lt;br /&gt;
                        val = format_value(&lt;br /&gt;
                            obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,&lt;br /&gt;
                            false, false, obj.UsageFlags, obj.Scale,&lt;br /&gt;
                            true -- disable_attr&lt;br /&gt;
                        )&lt;br /&gt;
                    end&lt;br /&gt;
                    if val then&lt;br /&gt;
                        insert(lines, format(&amp;quot;| item_stat%d = %s&amp;quot;, innate_index, val))&lt;br /&gt;
                        innate_index = innate_index + 1&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    -- Build formatters once (closures capture resolved_name)&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    local main_formatter, alt_formatter&lt;br /&gt;
&lt;br /&gt;
    if enhanced then&lt;br /&gt;
        main_formatter = function(obj)&lt;br /&gt;
            if obj.Key:match(&amp;quot;^StatusEffect&amp;quot;) then&lt;br /&gt;
                return format_status_effect(obj.Key)&lt;br /&gt;
            end&lt;br /&gt;
            return format_value_enhanced(&lt;br /&gt;
                resolved_name, obj.Key, obj.Value, obj.Type,&lt;br /&gt;
                obj.LocTokenOverride, false, true, obj.UsageFlags, nil, true&lt;br /&gt;
            )&lt;br /&gt;
        end&lt;br /&gt;
        alt_formatter = function(obj)&lt;br /&gt;
            if obj.Key:match(&amp;quot;^StatusEffect&amp;quot;) then&lt;br /&gt;
                return format_status_effect(obj.Key)&lt;br /&gt;
            end&lt;br /&gt;
            return format_value_enhanced(&lt;br /&gt;
                resolved_name, obj.Key, obj.Value, obj.Type,&lt;br /&gt;
                obj.LocTokenOverride, nil, false, obj.UsageFlags,&lt;br /&gt;
                true -- disable_attr&lt;br /&gt;
            )&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        main_formatter = function(obj)&lt;br /&gt;
            if obj.Key:match(&amp;quot;^StatusEffect&amp;quot;) then&lt;br /&gt;
                return format_status_effect(obj.Key)&lt;br /&gt;
            end&lt;br /&gt;
            return format_value(&lt;br /&gt;
                obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,&lt;br /&gt;
                false, true, obj.UsageFlags, obj.Scale, nil, true&lt;br /&gt;
            )&lt;br /&gt;
        end&lt;br /&gt;
        alt_formatter = function(obj)&lt;br /&gt;
            if obj.Key:match(&amp;quot;^StatusEffect&amp;quot;) then&lt;br /&gt;
                return format_status_effect(obj.Key)&lt;br /&gt;
            end&lt;br /&gt;
            return format_value(&lt;br /&gt;
                obj.Key, obj.Value, obj.Type, obj.LocTokenOverride,&lt;br /&gt;
                false, false, obj.UsageFlags, obj.Scale,&lt;br /&gt;
                true -- disable_attr&lt;br /&gt;
            )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    -- Passive &amp;amp; Active sections — Main and Alt output separately&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    local passive_counter, active_counter = 1, 1&lt;br /&gt;
&lt;br /&gt;
    for _, section in ipairs(sections) do&lt;br /&gt;
        local stype = section.Type&lt;br /&gt;
        if stype ~= &amp;quot;Innate&amp;quot; then&lt;br /&gt;
            local is_active = (stype == &amp;quot;Active&amp;quot;)&lt;br /&gt;
            local prefix = is_active and &amp;quot;active&amp;quot; or &amp;quot;passive&amp;quot;&lt;br /&gt;
            local counter = is_active and active_counter or passive_counter&lt;br /&gt;
&lt;br /&gt;
            -- Description&lt;br /&gt;
            local loc = section.DescKey&lt;br /&gt;
            if loc then&lt;br /&gt;
                loc = loc:gsub(&amp;quot;#&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
                if loc ~= &amp;quot;&amp;quot; then&lt;br /&gt;
                    insert(lines, format(&lt;br /&gt;
                        &amp;quot;| %s%d_description = {{#invoke:Lang|get_string|%s|item_name=%s}}&amp;quot;,&lt;br /&gt;
                        prefix, counter, loc, resolved_name&lt;br /&gt;
                    ))&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            -- Main stats → prefix{N}_main{M}&lt;br /&gt;
            local main_fmt = &amp;quot;| &amp;quot; .. prefix .. &amp;quot;%d_main%d = %s&amp;quot;&lt;br /&gt;
            local main_seen = {}&lt;br /&gt;
            local main_index = 1&lt;br /&gt;
            for _, prop_obj in ipairs(section.Main or {}) do&lt;br /&gt;
                local key = prop_obj.Key&lt;br /&gt;
                if not main_seen[key] and not IGNORED_PROP_KEYS[key] and (&lt;br /&gt;
                    key:match(&amp;quot;^StatusEffect&amp;quot;)&lt;br /&gt;
                    or is_property_in_lang_data(key, prop_obj.LocTokenOverride)&lt;br /&gt;
                ) then&lt;br /&gt;
                    local val = main_formatter(prop_obj)&lt;br /&gt;
                    if val then&lt;br /&gt;
                        insert(lines, format(main_fmt, counter, main_index, val))&lt;br /&gt;
                        main_index = main_index + 1&lt;br /&gt;
                        main_seen[key] = true&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            -- Alt stats → prefix{N}_alt{M}&lt;br /&gt;
            local alt_fmt = &amp;quot;| &amp;quot; .. prefix .. &amp;quot;%d_alt%d = %s&amp;quot;&lt;br /&gt;
            local alt_seen = {}&lt;br /&gt;
            local alt_index = 1&lt;br /&gt;
            for _, prop_obj in ipairs(section.Alt or {}) do&lt;br /&gt;
                local key = prop_obj.Key&lt;br /&gt;
                -- Skip keys already emitted as main stats&lt;br /&gt;
                if not main_seen[key] and not alt_seen[key] and not IGNORED_PROP_KEYS[key] and (&lt;br /&gt;
                    key:match(&amp;quot;^StatusEffect&amp;quot;)&lt;br /&gt;
                    or is_property_in_lang_data(key, prop_obj.LocTokenOverride)&lt;br /&gt;
                ) then&lt;br /&gt;
                    local val = alt_formatter(prop_obj)&lt;br /&gt;
                    if val then&lt;br /&gt;
                        insert(lines, format(alt_fmt, counter, alt_index, val))&lt;br /&gt;
                        alt_index = alt_index + 1&lt;br /&gt;
                        alt_seen[key] = true&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            -- Cooldown / ChargeUp&lt;br /&gt;
            local cd = format_section_cooldown(section, resolved_name, enhanced)&lt;br /&gt;
            if cd.cooldown then&lt;br /&gt;
                insert(lines, format(&amp;quot;| %s%d_cooldown = %s&amp;quot;, prefix, counter, cd.cooldown))&lt;br /&gt;
            end&lt;br /&gt;
            if cd.chargeup then&lt;br /&gt;
                insert(lines, format(&amp;quot;| %s%d_chargeup = %s&amp;quot;, prefix, counter, cd.chargeup))&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            if is_active then&lt;br /&gt;
                active_counter = active_counter + 1&lt;br /&gt;
            else&lt;br /&gt;
                passive_counter = passive_counter + 1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    -- Components&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    for i = 1, 2 do&lt;br /&gt;
        local comp = ItemData.get_component_name { args = { resolved_name, i } }&lt;br /&gt;
        if comp and comp ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            insert(lines, format(&amp;quot;| component%d_name = %s&amp;quot;, i, comp))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    -- Is Component Of (sorted by tier)&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    local parents = get_component_of_sorted(item_name)&lt;br /&gt;
    for i, key in ipairs(parents) do&lt;br /&gt;
        local d = data[key]&lt;br /&gt;
        local parent_name = d and d.Name or &amp;quot;&amp;quot;&lt;br /&gt;
        if parent_name ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            insert(lines, format(&amp;quot;| iscomponentof%d_name = %s&amp;quot;, i, parent_name))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    -- Sounds (pass-through from frame args)&lt;br /&gt;
    ------------------------------------------------------------------&lt;br /&gt;
    for key, value in pairs(frame.args) do&lt;br /&gt;
        local index = tostring(key):match(&amp;quot;^sound(%d+)$&amp;quot;)&lt;br /&gt;
        if index and value ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            insert(lines, format(&amp;quot;| sound%s = %s&amp;quot;, index, value))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    insert(lines, &amp;quot;}}&amp;quot;)&lt;br /&gt;
    return concat(lines, &amp;quot;\n&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Public interface&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- Render only Default item infobox&lt;br /&gt;
function p.fill_tooltip(frame)&lt;br /&gt;
    local output = build_tooltip_impl(frame, false)&lt;br /&gt;
    local debug = tonumber(frame.args.debug) or 0&lt;br /&gt;
    if debug == 1 or debug == 2 then return output end&lt;br /&gt;
    return mw.getCurrentFrame():preprocess(output)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Render only Enhanced item infobox&lt;br /&gt;
function p.fill_tooltip_enhanced(frame)&lt;br /&gt;
    return mw.getCurrentFrame():preprocess(build_tooltip_impl(frame, true))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Render both Default and Enhanced item infobox using tabber&lt;br /&gt;
function p.render(frame)&lt;br /&gt;
    local output = concat({&lt;br /&gt;
        &amp;quot;&amp;lt;tabber&amp;gt;&amp;quot;,&lt;br /&gt;
        lang.get_string(&amp;quot;citadel_settings_camera_preset_default&amp;quot;) .. &amp;quot;=&amp;quot;,&lt;br /&gt;
        build_tooltip_impl(frame, false),&lt;br /&gt;
        &amp;quot;|-|&amp;quot;,&lt;br /&gt;
        lang.get_string(&amp;quot;Citadel_ItemDraft_Enhanced&amp;quot;) .. &amp;quot;=&amp;quot;,&lt;br /&gt;
        build_tooltip_impl(frame, true),&lt;br /&gt;
        &amp;quot;&amp;lt;/tabber&amp;gt;&amp;quot;&lt;br /&gt;
    }, &amp;quot;\n&amp;quot;)&lt;br /&gt;
    return mw.getCurrentFrame():preprocess(output)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>~2026-EnduringDurationJump1108</name></author>
	</entry>
	<entry>
		<id>https://deadlock.wiki/Data:StatLinks.json?diff=127641</id>
		<title>Data:StatLinks.json</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/Data:StatLinks.json?diff=127641"/>
		<updated>2026-09-07T00:04:22Z</updated>

		<summary type="html">&lt;p&gt;~2026-EnduringDurationJump1108: SlowPercent/MaxSlowPercent → Movement Slow, TotalHealthRegen → Healing (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{&lt;br /&gt;
	&amp;quot;AbilityCastRange&amp;quot;: &amp;quot;Ability Range&amp;quot;,&lt;br /&gt;
	&amp;quot;AbilityDuration&amp;quot;: &amp;quot;Ability Duration&amp;quot;,&lt;br /&gt;
	&amp;quot;AbilityLifestealPercentHero&amp;quot;: &amp;quot;Spirit Lifesteal (stat)&amp;quot;,&lt;br /&gt;
	&amp;quot;AbilityLifestealPercentHeroPassive&amp;quot;: &amp;quot;Spirit Lifesteal&amp;quot;,&lt;br /&gt;
	&amp;quot;ActivatedFireRate&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;ActiveBonusFireRate&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;ActiveBonusLifesteal&amp;quot;: &amp;quot;Bullet Lifesteal&amp;quot;,&lt;br /&gt;
	&amp;quot;ActiveBonusMoveSpeed&amp;quot;: &amp;quot;Move Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;ActiveMoveSpeedPenalty&amp;quot;: &amp;quot;Move Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;ActiveReloadPercent&amp;quot;: &amp;quot;Ammo&amp;quot;,&lt;br /&gt;
	&amp;quot;AmbushBonusFireRate&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;AmbushBonusMeleeDamage&amp;quot;: &amp;quot;Melee Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;AmbushBonusTechPower&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;AmmoReloadPercent&amp;quot;: &amp;quot;Ammo&amp;quot;,&lt;br /&gt;
	&amp;quot;BaseAttackDamagePercent&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;BaseAttackDamagePercentAtMaxDuration&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;BaseAttackDamagePercentBonus&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusAbilityCharges&amp;quot;: &amp;quot;Charges&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusAbilityDurationPercent&amp;quot;: &amp;quot;Ability Duration&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusAttackRangePercent&amp;quot;: &amp;quot;Falloff Range&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusBaseHealth&amp;quot;: &amp;quot;Health&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusBulletSpeedPercent&amp;quot;: &amp;quot;Bullet Velocity&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusClipSize&amp;quot;: &amp;quot;Ammo&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusClipSizePercent&amp;quot;: &amp;quot;Ammo&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusFireRate&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusHealth&amp;quot;: &amp;quot;Health&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusHealthRegen&amp;quot;: &amp;quot;Health Regen&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusMeleeDamagePercent&amp;quot;: &amp;quot;Melee Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusMoveSpeed&amp;quot;: &amp;quot;Move Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusShotsDuration&amp;quot;: &amp;quot;Status Effects&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusSpirit&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusSpiritForChargedAbilities&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;BonusSprintSpeed&amp;quot;: &amp;quot;Sprint Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;BuffBulletResist&amp;quot;: &amp;quot;Bullet Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;BuffDuration&amp;quot;: &amp;quot;Status Effects&amp;quot;,&lt;br /&gt;
	&amp;quot;BuffMoveSpeedBonus&amp;quot;: &amp;quot;Move Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;BuffTechResist&amp;quot;: &amp;quot;Spirit Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletArmorReduction&amp;quot;: &amp;quot;Damage Resistance&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletDamageReflectedPct&amp;quot;: &amp;quot;Bullet Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletLifestealPercent&amp;quot;: &amp;quot;Bullet Lifesteal (stat)&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletResist&amp;quot;: &amp;quot;Bullet Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletResistBelowThreshold&amp;quot;: &amp;quot;Bullet Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletResistDuration&amp;quot;: &amp;quot;Bullet Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletResistPerStack&amp;quot;: &amp;quot;Bullet Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletResistReduction&amp;quot;: &amp;quot;Bullet Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;BulletsBonusMagicDamage&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;CasterBuffDuration&amp;quot;: &amp;quot;Status Effects&amp;quot;,&lt;br /&gt;
	&amp;quot;CloseRangeBonusWeaponPower&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;CombatBarrier&amp;quot;: &amp;quot;Damage Barrier&amp;quot;,&lt;br /&gt;
	&amp;quot;CooldownReduction&amp;quot;: &amp;quot;Ability Cooldown&amp;quot;,&lt;br /&gt;
	&amp;quot;CooldownReductionOnChargedAbilities&amp;quot;: &amp;quot;Ability Cooldown&amp;quot;,&lt;br /&gt;
	&amp;quot;CooldownReductionOnHitMin&amp;quot;: &amp;quot;Ability Cooldown&amp;quot;,&lt;br /&gt;
	&amp;quot;CooldownReductionOnHitPct&amp;quot;: &amp;quot;Ability Cooldown&amp;quot;,&lt;br /&gt;
	&amp;quot;CooldownReductionPerHit&amp;quot;: &amp;quot;Ability Cooldown&amp;quot;,&lt;br /&gt;
	&amp;quot;CritDamagePercent&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;DPS&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;DamagePerChain&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;DamagePulseAmount&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;DamageToStack&amp;quot;: &amp;quot;Stack&amp;quot;,&lt;br /&gt;
	&amp;quot;DazeDuration&amp;quot;: &amp;quot;Status Effects&amp;quot;,&lt;br /&gt;
	&amp;quot;DebuffDuration&amp;quot;: &amp;quot;Status Effects&amp;quot;,&lt;br /&gt;
	&amp;quot;EvasionWhileSliding&amp;quot;: &amp;quot;Bullet Evasion&amp;quot;,&lt;br /&gt;
	&amp;quot;ExplosionDamage&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;FervorFireRate&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;FervorMovespeed&amp;quot;: &amp;quot;Move Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;FervorStatusResistancePercent&amp;quot;: &amp;quot;Debuff Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;FervorTechResist&amp;quot;: &amp;quot;Spirit Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;FireRateBonus&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;FireRatePerKill&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;FireRateSlow&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;FireRateWhileSliding&amp;quot;: &amp;quot;Fire Rate&amp;quot;,&lt;br /&gt;
	&amp;quot;FloatMoveSpeed&amp;quot;: &amp;quot;Move Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;FreezeDuration&amp;quot;: &amp;quot;Status Effects&amp;quot;,&lt;br /&gt;
	&amp;quot;GroundDashReductionPercent&amp;quot;: &amp;quot;Stamina&amp;quot;,&lt;br /&gt;
	&amp;quot;GuardianWardCombatBarrier&amp;quot;: &amp;quot;Damage Barrier&amp;quot;,&lt;br /&gt;
	&amp;quot;HeadShotBonusDamage&amp;quot;: &amp;quot;Headshot&amp;quot;,&lt;br /&gt;
	&amp;quot;HealAmpCastPercent&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealAmpReceivePenaltyPercent&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealFromHero&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealFromNPC&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealLifePercentOutOfCombat&amp;quot;: &amp;quot;Health&amp;quot;,&lt;br /&gt;
	&amp;quot;HealOnKill&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealOnSuccess&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealOnVeil&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealPerStack&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealPercentAmount&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealPercentPerHeadshot&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealingPerCast&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;HealthSteal&amp;quot;: &amp;quot;Health&amp;quot;,&lt;br /&gt;
	&amp;quot;ImbueAbilityLifesteal&amp;quot;: &amp;quot;Lifesteal&amp;quot;,&lt;br /&gt;
	&amp;quot;ImbuedCooldownReduction&amp;quot;: &amp;quot;Ability Cooldown&amp;quot;,&lt;br /&gt;
	&amp;quot;ImbuedTechPower&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;ImpactDamage&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;InvisMoveSpeedMod&amp;quot;: &amp;quot;Sprint Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;LifestrikeHeal&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;LightMeleeAmmo&amp;quot;: &amp;quot;Ammo&amp;quot;,&lt;br /&gt;
	&amp;quot;LongRangeBonusWeaponPower&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;MagicIncreasePerStack&amp;quot;: &amp;quot;Spirit Amp&amp;quot;,&lt;br /&gt;
	&amp;quot;MagicResistReduction&amp;quot;: &amp;quot;Spirit Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;MaxArmorStacks&amp;quot;: &amp;quot;Bullet Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;MaxHealthLossPercent&amp;quot;: &amp;quot;Health&amp;quot;,&lt;br /&gt;
	&amp;quot;MaxSlowPercent&amp;quot;: &amp;quot;Movement Slow&amp;quot;,&lt;br /&gt;
	&amp;quot;MaxStacks&amp;quot;: &amp;quot;Stack&amp;quot;,&lt;br /&gt;
	&amp;quot;MeleeDistanceScale&amp;quot;: &amp;quot;Melee Distance&amp;quot;,&lt;br /&gt;
	&amp;quot;MeleeResistPercent&amp;quot;: &amp;quot;Melee Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;MovementSpeedBonusDuration&amp;quot;: &amp;quot;Move Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;MovementSpeedSlow&amp;quot;: &amp;quot;Movement Slow&amp;quot;,&lt;br /&gt;
	&amp;quot;NonHeroStackLimit&amp;quot;: &amp;quot;Unit&amp;quot;,&lt;br /&gt;
	&amp;quot;OutOfCombatHealthRegen&amp;quot;: &amp;quot;Health Regen&amp;quot;,&lt;br /&gt;
	&amp;quot;ParryCooldownReduction&amp;quot;: &amp;quot;Parry&amp;quot;,&lt;br /&gt;
	&amp;quot;ProcAmmoConsumed&amp;quot;: &amp;quot;Ammo&amp;quot;,&lt;br /&gt;
	&amp;quot;ProcBaseAttackDamagePercent&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;ProcBaseAttackDamagePercentAltFire&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;ProcBonusMagicDamage&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;ProcBulletVelocity&amp;quot;: &amp;quot;Bullet Velocity&amp;quot;,&lt;br /&gt;
	&amp;quot;RegenDuration&amp;quot;: &amp;quot;Health Regen&amp;quot;,&lt;br /&gt;
	&amp;quot;Regeneration&amp;quot;: &amp;quot;Health Regen&amp;quot;,&lt;br /&gt;
	&amp;quot;ReloadSpeedMultipler&amp;quot;: &amp;quot;Reload Time&amp;quot;,&lt;br /&gt;
	&amp;quot;SlideScale&amp;quot;: &amp;quot;Slide Distance&amp;quot;,&lt;br /&gt;
	&amp;quot;SlowDuration&amp;quot;: &amp;quot;Movement Slow&amp;quot;,&lt;br /&gt;
	&amp;quot;SlowPercent&amp;quot;: &amp;quot;Movement Slow&amp;quot;,&lt;br /&gt;
	&amp;quot;SlowResistancePercent&amp;quot;: &amp;quot;Slow Resistance&amp;quot;,&lt;br /&gt;
	&amp;quot;SpiritDamage&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;SpiritDamageReductionProc&amp;quot;: &amp;quot;Damage Resistance&amp;quot;,&lt;br /&gt;
	&amp;quot;SpiritDamageReflectedPct&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;SpiritPower&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;SpiritPowerInnate&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;StackingBonusHealth&amp;quot;: &amp;quot;Health&amp;quot;,&lt;br /&gt;
	&amp;quot;StackingBonusSprintSpeed&amp;quot;: &amp;quot;Sprint Speed&amp;quot;,&lt;br /&gt;
	&amp;quot;StackingGoldPerMinute&amp;quot;: &amp;quot;Souls&amp;quot;,&lt;br /&gt;
	&amp;quot;StackingTechRangeMultiplier&amp;quot;: &amp;quot;Ability Range&amp;quot;,&lt;br /&gt;
	&amp;quot;Stamina&amp;quot;: &amp;quot;Stamina&amp;quot;,&lt;br /&gt;
	&amp;quot;StaminaCooldownReduction&amp;quot;: &amp;quot;Stamina&amp;quot;,&lt;br /&gt;
	&amp;quot;StatusResistancePercent&amp;quot;: &amp;quot;Debuff Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;StunDuration&amp;quot;: &amp;quot;Stun&amp;quot;,&lt;br /&gt;
	&amp;quot;TechArmorDamageReduction&amp;quot;: &amp;quot;Spirit Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;TechDamageReduction&amp;quot;: &amp;quot;Damage Resistance&amp;quot;,&lt;br /&gt;
	&amp;quot;TechPower&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;TechPowerPercent&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;TechPowerReduction&amp;quot;: &amp;quot;Spirit Power&amp;quot;,&lt;br /&gt;
	&amp;quot;TechRadiusMultiplier&amp;quot;: &amp;quot;Ability Range&amp;quot;,&lt;br /&gt;
	&amp;quot;TechRangeMultiplier&amp;quot;: &amp;quot;Ability Range&amp;quot;,&lt;br /&gt;
	&amp;quot;TechRangeMultiplierBuff&amp;quot;: &amp;quot;Ability Range&amp;quot;,&lt;br /&gt;
	&amp;quot;TechResist&amp;quot;: &amp;quot;Spirit Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;TechResistBelowThreshold&amp;quot;: &amp;quot;Spirit Resist&amp;quot;,&lt;br /&gt;
	&amp;quot;TotalHealthRegen&amp;quot;: &amp;quot;Healing&amp;quot;,&lt;br /&gt;
	&amp;quot;VexBarrierCombatBarrier&amp;quot;: &amp;quot;Damage Barrier&amp;quot;,&lt;br /&gt;
	&amp;quot;WeaponDamageBonusDuration&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;WeaponDamagePerStack&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;WeaponPowerPerStack&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;WeaponPowerPerStackNonHero&amp;quot;: &amp;quot;Unit&amp;quot;,&lt;br /&gt;
	&amp;quot;StatDesc_TechDamageAttribute&amp;quot;: &amp;quot;Spirit Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;StatDesc_WeaponPower&amp;quot;: &amp;quot;Weapon Damage&amp;quot;,&lt;br /&gt;
	&amp;quot;StatDesc_MeleeDamage&amp;quot;: &amp;quot;Melee Damage&amp;quot;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>~2026-EnduringDurationJump1108</name></author>
	</entry>
	<entry>
		<id>https://deadlock.wiki/User:Vergir/test1?diff=127640</id>
		<title>User:Vergir/test1</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/User:Vergir/test1?diff=127640"/>
		<updated>2026-09-06T23:47:43Z</updated>

		<summary type="html">&lt;p&gt;~2026-EnduringDurationJump1108: Audit table v3 with formatted labels and change classification (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Sandbox/Vergir|audit}}&lt;/div&gt;</summary>
		<author><name>~2026-EnduringDurationJump1108</name></author>
	</entry>
	<entry>
		<id>https://deadlock.wiki/Module:Sandbox/Vergir?diff=127639</id>
		<title>Module:Sandbox/Vergir</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/Module:Sandbox/Vergir?diff=127639"/>
		<updated>2026-09-06T23:47:34Z</updated>

		<summary type="html">&lt;p&gt;~2026-EnduringDurationJump1108: Audit script v3: formatted label values + classification column (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Audit: for every item stat that goes through Infobox item&#039;s append_label&lt;br /&gt;
-- with attribute styling enabled (Passive/Active Main stats), compute the&lt;br /&gt;
-- label link target under the CURRENT priority (attr link &amp;gt; StatLinks)&lt;br /&gt;
-- and the PROPOSED priority (StatLinks &amp;gt; attr link), and classify the change.&lt;br /&gt;
local p = {}&lt;br /&gt;
local lang = require &amp;quot;Module:Lang&amp;quot;&lt;br /&gt;
local data = mw.loadJsonData(&amp;quot;Data:ItemCards.json&amp;quot;)&lt;br /&gt;
local stat_links = mw.loadJsonData(&amp;quot;Data:StatLinks.json&amp;quot;)&lt;br /&gt;
local ATTR = require(&amp;quot;Module:Icon/attr&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
local LABEL_KEY_REMAP = { DotDuration = &amp;quot;DOTDuration&amp;quot; }&lt;br /&gt;
local IGNORED = { BuildUpPerShot = true }&lt;br /&gt;
&lt;br /&gt;
-- Keys whose StatLinks entry is worse than the current type link.&lt;br /&gt;
-- Proposed StatLinks fix noted alongside.&lt;br /&gt;
local STATLINKS_FIX = {&lt;br /&gt;
    SlowPercent = &amp;quot;Movement Slow&amp;quot;,&lt;br /&gt;
    MaxSlowPercent = &amp;quot;Movement Slow&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
local DEBATABLE = {&lt;br /&gt;
    GroundDashReductionPercent = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function get_pair(base, s1, s2)&lt;br /&gt;
    local v = lang.get_string(base .. s1)&lt;br /&gt;
    if v and v ~= &amp;quot;&amp;quot; then return v end&lt;br /&gt;
    v = lang.get_string(base .. s2)&lt;br /&gt;
    if v and v ~= &amp;quot;&amp;quot; then return v end&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function resolve_label_key(prop_key, loc_override)&lt;br /&gt;
    local base = (loc_override or prop_key):gsub(&amp;quot;^#&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    return LABEL_KEY_REMAP[base] or base&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function norm(s)&lt;br /&gt;
    if s == nil or s == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
    return (tostring(s):gsub(&amp;quot;_&amp;quot;, &amp;quot; &amp;quot;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Resolve a title through one redirect hop; returns final page name&lt;br /&gt;
local resolve_cache = {}&lt;br /&gt;
local function resolve(t)&lt;br /&gt;
    if t == nil then return nil end&lt;br /&gt;
    if resolve_cache[t] == nil then&lt;br /&gt;
        local title = mw.title.new(t)&lt;br /&gt;
        local r = t&lt;br /&gt;
        if title and title.exists and title.isRedirect then&lt;br /&gt;
            local tgt = title.redirectTarget&lt;br /&gt;
            if tgt then r = tgt.prefixedText end&lt;br /&gt;
        elseif not title or not title.exists then&lt;br /&gt;
            r = t .. &amp;quot; (MISSING)&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
        resolve_cache[t] = r&lt;br /&gt;
    end&lt;br /&gt;
    return resolve_cache[t]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function fmt_value(label_key, value, label)&lt;br /&gt;
    local n = tonumber(tostring(value):match(&amp;quot;^-?%d+%.?%d*&amp;quot;))&lt;br /&gt;
    if not n then return label end&lt;br /&gt;
    local prefix = get_pair(label_key, &amp;quot;_prefix&amp;quot;, &amp;quot;_Prefix&amp;quot;)&lt;br /&gt;
    local postfix = get_pair(label_key, &amp;quot;_postfix&amp;quot;, &amp;quot;_Postfix&amp;quot;)&lt;br /&gt;
    if prefix == &amp;quot;{s:sign}&amp;quot; then prefix = n &amp;gt;= 0 and &amp;quot;+&amp;quot; or &amp;quot;&amp;quot; end&lt;br /&gt;
    local s = tostring(n)&lt;br /&gt;
    if prefix ~= &amp;quot;&amp;quot; then s = prefix .. s end&lt;br /&gt;
    if postfix ~= &amp;quot;&amp;quot; then s = s .. (postfix == &amp;quot;HP/s&amp;quot; and &amp;quot; &amp;quot; or &amp;quot;&amp;quot;) .. postfix end&lt;br /&gt;
    return s .. &amp;quot; &amp;quot; .. label&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.audit(frame)&lt;br /&gt;
    local names = {}&lt;br /&gt;
    for key, item in pairs(data) do&lt;br /&gt;
        if not item.IsDisabled then table.insert(names, key) end&lt;br /&gt;
    end&lt;br /&gt;
    table.sort(names, function(a, b)&lt;br /&gt;
        return (data[a].Name or a) &amp;lt; (data[b].Name or b)&lt;br /&gt;
    end)&lt;br /&gt;
&lt;br /&gt;
    local rows = {}&lt;br /&gt;
    local counts = {}&lt;br /&gt;
    local n_items, n_stats, n_same = 0, 0, 0&lt;br /&gt;
    for _, key in ipairs(names) do&lt;br /&gt;
        local item = data[key]&lt;br /&gt;
        n_items = n_items + 1&lt;br /&gt;
        local i = 1&lt;br /&gt;
        while item[&amp;quot;Info&amp;quot; .. i] do&lt;br /&gt;
            local sec = item[&amp;quot;Info&amp;quot; .. i]&lt;br /&gt;
            if sec.Type ~= &amp;quot;Innate&amp;quot; then&lt;br /&gt;
                local seen = {}&lt;br /&gt;
                for _, obj in ipairs(sec.Main or {}) do&lt;br /&gt;
                    local pk = obj.Key&lt;br /&gt;
                    if not seen[pk] and not IGNORED[pk] and not pk:match(&amp;quot;^StatusEffect&amp;quot;) then&lt;br /&gt;
                        seen[pk] = true&lt;br /&gt;
                        local label_key = resolve_label_key(pk, obj.LocTokenOverride)&lt;br /&gt;
                        local label = get_pair(label_key, &amp;quot;_label&amp;quot;, &amp;quot;_Label&amp;quot;)&lt;br /&gt;
                        if label ~= &amp;quot;&amp;quot; then&lt;br /&gt;
                            n_stats = n_stats + 1&lt;br /&gt;
                            local attr = obj.Type and ATTR[obj.Type] or nil&lt;br /&gt;
                            local attr_link = norm(attr and attr.link)&lt;br /&gt;
                            local sl = norm(stat_links[label_key])&lt;br /&gt;
                            local cur = attr_link or sl&lt;br /&gt;
                            local new = sl or attr_link&lt;br /&gt;
                            if (cur or &amp;quot;&amp;quot;) == (new or &amp;quot;&amp;quot;) then&lt;br /&gt;
                                n_same = n_same + 1&lt;br /&gt;
                            else&lt;br /&gt;
                                local kind&lt;br /&gt;
                                if STATLINKS_FIX[label_key] then&lt;br /&gt;
                                    kind = &amp;quot;Regression → fixed via StatLinks (&amp;quot; .. label_key .. &amp;quot; = &amp;quot; .. STATLINKS_FIX[label_key] .. &amp;quot;)&amp;quot;&lt;br /&gt;
                                elseif DEBATABLE[label_key] then&lt;br /&gt;
                                    kind = &amp;quot;Debatable&amp;quot;&lt;br /&gt;
                                elseif resolve(cur) == resolve(new) then&lt;br /&gt;
                                    kind = &amp;quot;NOP (redirect to same page)&amp;quot;&lt;br /&gt;
                                else&lt;br /&gt;
                                    kind = &amp;quot;Fix&amp;quot;&lt;br /&gt;
                                end&lt;br /&gt;
                                counts[kind] = (counts[kind] or 0) + 1&lt;br /&gt;
                                table.insert(rows, string.format(&lt;br /&gt;
                                    &amp;quot;|-\n| [[%s]] || %s || [[%s]] || [[%s]] || %s&amp;quot;,&lt;br /&gt;
                                    item.Name or key, fmt_value(label_key, obj.Value, label),&lt;br /&gt;
                                    cur or &amp;quot;&amp;quot;, new or &amp;quot;&amp;quot;, kind))&lt;br /&gt;
                            end&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            i = i + 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
    table.insert(out, string.format(&lt;br /&gt;
        &amp;quot;Items scanned: %d. Passive/Active main stats with a label: %d. Unchanged: %d. Changed: %d.\n&amp;quot;,&lt;br /&gt;
        n_items, n_stats, n_same, #rows))&lt;br /&gt;
    local ks = {}&lt;br /&gt;
    for k in pairs(counts) do table.insert(ks, k) end&lt;br /&gt;
    table.sort(ks)&lt;br /&gt;
    for _, k in ipairs(ks) do table.insert(out, string.format(&amp;quot;* %s: %d&amp;quot;, k, counts[k])) end&lt;br /&gt;
    table.insert(out, &#039;{| class=&amp;quot;wikitable sortable&amp;quot;\n! Item !! Label !! Current target !! Proposed target !! Type&#039;)&lt;br /&gt;
    for _, r in ipairs(rows) do table.insert(out, r) end&lt;br /&gt;
    table.insert(out, &amp;quot;|}&amp;quot;)&lt;br /&gt;
    return table.concat(out, &amp;quot;\n&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>~2026-EnduringDurationJump1108</name></author>
	</entry>
</feed>