<?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-LaneLeechSecure746</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-LaneLeechSecure746"/>
	<link rel="alternate" type="text/html" href="https://deadlock.wiki/Special:Contributions/~2026-LaneLeechSecure746"/>
	<updated>2026-09-14T17:53:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://deadlock.wiki/Template:ItemBox/styles.css?diff=99268</id>
		<title>Template:ItemBox/styles.css</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/Template:ItemBox/styles.css?diff=99268"/>
		<updated>2026-07-23T21:54:03Z</updated>

		<summary type="html">&lt;p&gt;~2026-LaneLeechSecure746: Reduce scroll jank when many cards are on screen: skip offscreen cards with content-visibility, isolate the blend group to the card, drop hidden tags from layout, remove the bevel blend mode (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
/* The whole card scales off one knob: font-size on .itembox (1em = 10px base) */&lt;br /&gt;
.itembox,&lt;br /&gt;
.itembox * {&lt;br /&gt;
    margin: 0;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
    border: 0;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
.itembox {&lt;br /&gt;
    --itembox-ink: #10130D;&lt;br /&gt;
    --itembox-weapon: #EC981a;&lt;br /&gt;
    --itembox-vitality: #7CBB1E;&lt;br /&gt;
    --itembox-spirit: #CE91FF;&lt;br /&gt;
    --itembox-imbue-fg: #E8C9FF;&lt;br /&gt;
    --itembox-imbue-bg: #623585;&lt;br /&gt;
    --itembox-font: &#039;Retail Demo&#039;, sans-serif;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    font-size: 10px;&lt;br /&gt;
    width: 8em;&lt;br /&gt;
    height: 12.5em;&lt;br /&gt;
    border-radius: 0.6em;&lt;br /&gt;
    box-shadow: 0.2em 0.2em 1.2em #00000097;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    transition-duration: 0.1s;&lt;br /&gt;
    transition-property: opacity, transform, filter;&lt;br /&gt;
    /* Offscreen cards skip layout, paint and compositing entirely. The box is a&lt;br /&gt;
       fixed 8em x 12.5em, so contain-intrinsic-size keeps the placeholder the&lt;br /&gt;
       exact size of the real card and nothing reflows on scroll. */&lt;br /&gt;
    content-visibility: auto;&lt;br /&gt;
    contain-intrinsic-size: 8em 12.5em;&lt;br /&gt;
}&lt;br /&gt;
.itembox-background {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
}&lt;br /&gt;
.itembox-card {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background-size: cover;&lt;br /&gt;
    /* Confines mix-blend-mode below to the card. Without it the blend group&lt;br /&gt;
       reaches the page backdrop and the card cannot be cached as one layer. */&lt;br /&gt;
    isolation: isolate;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-tier-1.itembox-weapon .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/3/3e/Weapon_Card_T1.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-2.itembox-weapon .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/9/96/Weapon_Card_T2.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-3.itembox-weapon .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/5/5d/Weapon_Card_T3.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-4.itembox-weapon .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/a/a6/Weapon_Card_T4.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-5.itembox-weapon .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/a/a6/Weapon_Card_T4.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-1.itembox-vitality .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/7/75/Armor_Card_T1.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-2.itembox-vitality .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/0/05/Armor_Card_T2.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-3.itembox-vitality .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/7/7c/Armor_Card_T3.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-4.itembox-vitality .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/1/18/Armor_Card_T4.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-5.itembox-vitality .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/1/18/Armor_Card_T4.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-1.itembox-spirit .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/a/af/Tech_Card_T1.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-2.itembox-spirit .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/a/ac/Tech_Card_T2.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-3.itembox-spirit .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/6/67/Tech_Card_T3.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-4.itembox-spirit .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/f/f5/Tech_Card_T4.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-5.itembox-spirit .itembox-card {&lt;br /&gt;
    background-image: url(&#039;/images/f/f5/Tech_Card_T4.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-icon-area {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    aspect-ratio: 1 / 1;&lt;br /&gt;
}&lt;br /&gt;
.itembox-icon {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    background-size: cover;&lt;br /&gt;
    background-repeat: no-repeat;&lt;br /&gt;
    mask-size: cover;&lt;br /&gt;
    mask-repeat: no-repeat;&lt;br /&gt;
    mask-mode: luminance;&lt;br /&gt;
}&lt;br /&gt;
.itembox-icon &amp;gt; span,&lt;br /&gt;
.itembox-icon &amp;gt; span &amp;gt; span,&lt;br /&gt;
.itembox-icon picture {&lt;br /&gt;
    display: block;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
}&lt;br /&gt;
.itembox-icon img {&lt;br /&gt;
    display: block;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    max-height: 100%;&lt;br /&gt;
    object-fit: cover;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-icon-v1 .itembox-icon {&lt;br /&gt;
    mask-image: url(&#039;/images/1/10/Icon_mask01.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-icon-v2 .itembox-icon {&lt;br /&gt;
    mask-image: url(&#039;/images/6/6f/Icon_mask02.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-icon-v3 .itembox-icon {&lt;br /&gt;
    mask-image: url(&#039;/images/9/96/Icon_mask03.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-tier-badge {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    right: 0;&lt;br /&gt;
    width: 2.8em;&lt;br /&gt;
    height: 2.8em;&lt;br /&gt;
    transform: scale(1.4);&lt;br /&gt;
    transform-origin: top right;&lt;br /&gt;
    /* display:none rather than visibility:hidden so the badge and its&lt;br /&gt;
       drop-shadow() cost nothing on the cards that never show it. */&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
.itembox-show-tier .itembox-tier-badge {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-badge-fill {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    mask-size: 2.2em;&lt;br /&gt;
    mask-repeat: no-repeat;&lt;br /&gt;
    mask-position: right 0;&lt;br /&gt;
    mask-image: url(&#039;/images/6/61/Tier_corner_cap.svg&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-badge-shadow {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background-size: 2.2em;&lt;br /&gt;
    background-repeat: no-repeat;&lt;br /&gt;
    background-position: right 0;&lt;br /&gt;
    background-image: url(&#039;/images/6/61/Tier_corner_cap.svg&#039;);&lt;br /&gt;
    filter: drop-shadow(-0.4em 0 0.6em #000000ff);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-weapon .itembox-tier-badge-fill {&lt;br /&gt;
    background-color: var(--itembox-weapon);&lt;br /&gt;
}&lt;br /&gt;
.itembox-vitality .itembox-tier-badge-fill {&lt;br /&gt;
    background-color: var(--itembox-vitality);&lt;br /&gt;
}&lt;br /&gt;
.itembox-spirit .itembox-tier-badge-fill {&lt;br /&gt;
    background-color: var(--itembox-spirit);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-tier-badge-number {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    right: 0;&lt;br /&gt;
    top: 0.3em;&lt;br /&gt;
    height: 0.8em;&lt;br /&gt;
    mask-size: 100% 100%;&lt;br /&gt;
    background-color: var(--itembox-ink);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-1 .itembox-tier-badge-number {&lt;br /&gt;
    width: 0.5em;&lt;br /&gt;
    right: 0.4em;&lt;br /&gt;
    mask-image: url(&#039;/images/2/24/Tier_numbers_small_01.svg&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-2 .itembox-tier-badge-number {&lt;br /&gt;
    width: 0.7em;&lt;br /&gt;
    right: 0.3em;&lt;br /&gt;
    mask-image: url(&#039;/images/7/74/Tier_numbers_small_02.svg&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-3 .itembox-tier-badge-number {&lt;br /&gt;
    width: 0.9em;&lt;br /&gt;
    right: 0.2em;&lt;br /&gt;
    mask-image: url(&#039;/images/5/54/Tier_numbers_small_03.svg&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-4 .itembox-tier-badge-number {&lt;br /&gt;
    width: 1.1em;&lt;br /&gt;
    mask-image: url(&#039;/images/c/c6/Tier_numbers_small_04.svg&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-5 .itembox-tier-badge-number {&lt;br /&gt;
    width: 1.1em;&lt;br /&gt;
    right: 0.1em;&lt;br /&gt;
    mask-image: url(&#039;/images/8/81/Tier_numbers_small_05.svg&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-imbue-tag {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 0;&lt;br /&gt;
    display: none;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: fit-content;&lt;br /&gt;
    font-size: 1.2em;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    font-family: var(--itembox-font);&lt;br /&gt;
    line-height: normal;&lt;br /&gt;
    letter-spacing: 0.1em;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    text-transform: uppercase;&lt;br /&gt;
    border-radius: 0.2em;&lt;br /&gt;
    padding: 0 0.3em;&lt;br /&gt;
    color: var(--itembox-imbue-fg);&lt;br /&gt;
    background-color: var(--itembox-imbue-bg);&lt;br /&gt;
}&lt;br /&gt;
.itembox-imbue .itembox-imbue-tag {&lt;br /&gt;
    display: flex;&lt;br /&gt;
}&lt;br /&gt;
.itembox-active.itembox-imbue .itembox-imbue-tag {&lt;br /&gt;
    justify-content: start;&lt;br /&gt;
    height: 2.2em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-name-area {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 4.5em;&lt;br /&gt;
    padding: 0.5em 0.4em;&lt;br /&gt;
}&lt;br /&gt;
.itembox-name {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    line-height: 1.2;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    font-size: 1.5em;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    font-family: var(--itembox-font);&lt;br /&gt;
    color: var(--itembox-ink);&lt;br /&gt;
    overflow-wrap: normal;&lt;br /&gt;
    word-break: normal;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-tier-4.itembox-weapon .itembox-name,&lt;br /&gt;
.itembox-tier-5.itembox-weapon .itembox-name {&lt;br /&gt;
    color: #e4c5a1;&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-4.itembox-vitality .itembox-name,&lt;br /&gt;
.itembox-tier-5.itembox-vitality .itembox-name {&lt;br /&gt;
    color: #c2e7cd;&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-4.itembox-spirit .itembox-name,&lt;br /&gt;
.itembox-tier-5.itembox-spirit .itembox-name {&lt;br /&gt;
    color: #e3d4f2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-wear {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    opacity: 0.7;&lt;br /&gt;
    mask-size: 100% 100%;&lt;br /&gt;
    background-color: white;&lt;br /&gt;
}&lt;br /&gt;
.itembox-wear-v1 .itembox-wear {&lt;br /&gt;
    mask-image: url(&#039;/images/8/8f/Card_PaperWear_1.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-wear-v2 .itembox-wear {&lt;br /&gt;
    mask-image: url(&#039;/images/1/11/Card_PaperWear_2.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-wear-v3 .itembox-wear {&lt;br /&gt;
    mask-image: url(&#039;/images/8/89/Card_PaperWear_3.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-wear-v4 .itembox-wear {&lt;br /&gt;
    mask-image: url(&#039;/images/5/52/Card_PaperWear_4.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-tier-1.itembox-vitality .itembox-wear {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
    background-color: #f4e2cd;&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-1.itembox-spirit .itembox-wear {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
    background-color: rgb(247, 232, 213);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-2 .itembox-wear {&lt;br /&gt;
    background-color: rgb(230, 209, 191);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-3 .itembox-wear {&lt;br /&gt;
    background-color: rgb(206, 173, 155);&lt;br /&gt;
}&lt;br /&gt;
.itembox-tier-4 .itembox-wear,&lt;br /&gt;
.itembox-tier-5 .itembox-wear {&lt;br /&gt;
    background-color: rgb(105, 97, 92);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-texture {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background-size: 100% 100%;&lt;br /&gt;
    mix-blend-mode: multiply;&lt;br /&gt;
}&lt;br /&gt;
.itembox-texture-v1 .itembox-texture {&lt;br /&gt;
    background-image: url(&#039;/images/9/97/Shopitem_papertexture01.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-texture-v2 .itembox-texture {&lt;br /&gt;
    background-image: url(&#039;/images/b/bf/Shopitem_papertexture02.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
.itembox-texture-v3 .itembox-texture {&lt;br /&gt;
    background-image: url(&#039;/images/9/95/Shopitem_papertexture03.png&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Two hairlines at ~13% alpha: screen and normal blending land within ~2% of&lt;br /&gt;
   each other here, so the blend mode is dropped and the layer stays cheap. */&lt;br /&gt;
.itembox-bevel {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    border-left: 0.1em solid #ffcc6622;&lt;br /&gt;
    border-top: 0.1em solid #ffcc6622;&lt;br /&gt;
    background-size: 100% 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox-active-tag {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 3.5em;&lt;br /&gt;
    display: none;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    align-self: center;&lt;br /&gt;
    width: fit-content;&lt;br /&gt;
    height: fit-content;&lt;br /&gt;
    font-size: 1.1em;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    font-family: var(--itembox-font);&lt;br /&gt;
    line-height: normal;&lt;br /&gt;
    letter-spacing: 0;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    text-transform: uppercase;&lt;br /&gt;
    border-radius: 0.2em;&lt;br /&gt;
    padding: 0.1em 0.6em;&lt;br /&gt;
    box-shadow: 0 0 1.5em #000000ff;&lt;br /&gt;
    color: #ffefd7b3;&lt;br /&gt;
    background-color: #171717;&lt;br /&gt;
}&lt;br /&gt;
.itembox-active .itembox-active-tag {&lt;br /&gt;
    display: flex;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.itembox .item-link-wrapper,&lt;br /&gt;
.itembox .item-link-wrapper &amp;gt; a {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    display: block;&lt;br /&gt;
    inset: 0;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>~2026-LaneLeechSecure746</name></author>
	</entry>
	<entry>
		<id>https://deadlock.wiki/Module:ItemData/nav?diff=99234</id>
		<title>Module:ItemData/nav</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/Module:ItemData/nav?diff=99234"/>
		<updated>2026-07-23T20:40:21Z</updated>

		<summary type="html">&lt;p&gt;~2026-LaneLeechSecure746: Active Items table: use var(--color-subtle) for diminished notes (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
local p = {}&lt;br /&gt;
local items_data = mw.loadJsonData(&amp;quot;Data:ItemData.json&amp;quot;)&lt;br /&gt;
local lang_module = require(&#039;Module:Lang&#039;)&lt;br /&gt;
local generic_module = require(&#039;Module:GenericData&#039;)&lt;br /&gt;
local util_module = require(&#039;Module:Utilities&#039;)&lt;br /&gt;
&lt;br /&gt;
-- Exceptions if the link is different from the item name&lt;br /&gt;
local linkOverrides = {&lt;br /&gt;
    [&amp;quot;Bullet Lifesteal&amp;quot;] = &amp;quot;Bullet Lifesteal (item)&amp;quot;,&lt;br /&gt;
    [&amp;quot;Spirit Lifesteal&amp;quot;] = &amp;quot;Spirit Lifesteal (item)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Cached items grouped by slot to prevent redundant full-table evaluations&lt;br /&gt;
local cached_slots = nil&lt;br /&gt;
local function get_items_by_slot(slot)&lt;br /&gt;
    if not cached_slots then&lt;br /&gt;
        cached_slots = { table = {}, Weapon = {}, Armor = {}, Tech = {} }&lt;br /&gt;
        for item_key, item_data in pairs(items_data) do&lt;br /&gt;
            local this_slot = item_data[&amp;quot;Slot&amp;quot;]&lt;br /&gt;
            if this_slot and cached_slots[this_slot] then&lt;br /&gt;
                table.insert(cached_slots[this_slot], { key = item_key, data = item_data })&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return cached_slots[slot] or {}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- With debug_mode on, it outputs unprocessed wikitext&lt;br /&gt;
local function process_debug_mode(wikitext, debug_mode)&lt;br /&gt;
    if debug_mode == &#039;true&#039; then&lt;br /&gt;
        return wikitext&lt;br /&gt;
    elseif debug_mode == &#039;false&#039; or debug_mode == nil then&lt;br /&gt;
        return mw.getCurrentFrame():preprocess(wikitext)&lt;br /&gt;
    else&lt;br /&gt;
        return &amp;quot;debug_mode must be &#039;true&#039; or &#039;false&#039;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Writes list of items of a certain slot within the min and max soul bounds&lt;br /&gt;
local function write_wrapped_item_list(slot, min_souls, max_souls, template, sep, filter_mode)&lt;br /&gt;
    if slot ~= &#039;Weapon&#039; and slot ~= &#039;Armor&#039; and slot ~= &#039;Tech&#039; then&lt;br /&gt;
        return &#039;slot must be Weapon, Armor (Vitality), or Tech (Spirit)&#039;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local min_souls = tonumber(min_souls)&lt;br /&gt;
    local max_souls = tonumber(max_souls)&lt;br /&gt;
    if min_souls == nil or max_souls == nil then return &#039;Min/Max souls must be numerical&#039; end&lt;br /&gt;
    &lt;br /&gt;
    filter_mode = filter_mode or &amp;quot;all&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    -- Lifted out of the loop: Language code doesn&#039;t change per item&lt;br /&gt;
    local lang_code = lang_module.get_lang_code() &lt;br /&gt;
    &lt;br /&gt;
    local items = {}&lt;br /&gt;
    local slot_items = get_items_by_slot(slot) -- Drastically reduces search pool size&lt;br /&gt;
    &lt;br /&gt;
    for _, item_entry in ipairs(slot_items) do&lt;br /&gt;
        local item_key = item_entry.key&lt;br /&gt;
        local item_data = item_entry.data&lt;br /&gt;
        &lt;br /&gt;
        local this_cost = tonumber(item_data[&amp;quot;Cost&amp;quot;])&lt;br /&gt;
        local is_street_brawl = item_data[&amp;quot;StreetBrawl&amp;quot;] == true&lt;br /&gt;
        local should_include = true&lt;br /&gt;
        &lt;br /&gt;
        -- Filter logic for Street Brawl items&lt;br /&gt;
        if filter_mode == &amp;quot;street_brawl_only&amp;quot; and not is_street_brawl then&lt;br /&gt;
            should_include = false&lt;br /&gt;
        elseif filter_mode == &amp;quot;exclude_street_brawl&amp;quot; and is_street_brawl then&lt;br /&gt;
            should_include = false&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        if should_include and item_data[&amp;quot;Name&amp;quot;] ~= nil and item_data[&amp;quot;IsDisabled&amp;quot;] == false and this_cost ~= nil then&lt;br /&gt;
            if this_cost &amp;gt;= min_souls and this_cost &amp;lt; max_souls then&lt;br /&gt;
                local item_name_english = lang_module.get_string(item_key, &amp;quot;en&amp;quot;)&lt;br /&gt;
                local item_link = linkOverrides[item_name_english] or item_name_english&lt;br /&gt;
                local item_name_local = lang_module.get_string(item_key, lang_code)&lt;br /&gt;
                &lt;br /&gt;
                local item_template&lt;br /&gt;
                if template == &amp;quot;ItemIcon&amp;quot; then&lt;br /&gt;
                    if lang_code == &amp;quot;en&amp;quot; then&lt;br /&gt;
                        item_template = &amp;quot;{{ItemIcon|&amp;quot; .. item_name_english .. &amp;quot;|size=26px}}&amp;quot;&lt;br /&gt;
                    else&lt;br /&gt;
                        item_template = &amp;quot;{{ItemIcon|&amp;quot; .. item_name_english .. &amp;quot;|lang=&amp;quot; .. lang_code .. &amp;quot;|l1=&amp;quot; .. item_name_local .. &amp;quot;|size=26px}}&amp;quot;&lt;br /&gt;
                    end&lt;br /&gt;
                    &lt;br /&gt;
                    local search_data = item_name_english&lt;br /&gt;
                    if lang_code ~= &amp;quot;en&amp;quot; and item_name_local then&lt;br /&gt;
                        search_data = search_data .. &amp;quot; &amp;quot; .. item_name_local&lt;br /&gt;
                    end&lt;br /&gt;
                    &lt;br /&gt;
                    item_template = &#039;&amp;lt;span class=&amp;quot;item-nav-search-wrapper&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;item-nav-search-item&amp;quot; data-item-name=&amp;quot;&#039; .. search_data .. &#039;&amp;quot;&amp;gt;&#039; .. item_template .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
                elseif template == &amp;quot;ItemBox&amp;quot; then&lt;br /&gt;
                    if lang_code == &amp;quot;en&amp;quot; then&lt;br /&gt;
                        if is_street_brawl then&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. item_link .. &amp;quot;|overrideTier=5}}&amp;quot;&lt;br /&gt;
                        else&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. item_link .. &amp;quot;}}&amp;quot;&lt;br /&gt;
                        end&lt;br /&gt;
                    else&lt;br /&gt;
                        local link_local = item_link .. &amp;quot;/&amp;quot; .. lang_code&lt;br /&gt;
                        if is_street_brawl then&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. link_local .. &amp;quot;|item_price={{#invoke:Lang|get_string|Citadel_ItemDraft_Legendary}}}}&amp;quot;&lt;br /&gt;
                        else&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. link_local .. &amp;quot;}}&amp;quot;&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                else&lt;br /&gt;
                    return &amp;quot;Invalid template type&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
                table.insert(items, item_template)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Order list alphabetically&lt;br /&gt;
    table.sort(items)&lt;br /&gt;
    &lt;br /&gt;
    -- Append closing tags and bullets&lt;br /&gt;
    if template == &amp;quot;ItemIcon&amp;quot; then&lt;br /&gt;
        local total_items = #items&lt;br /&gt;
        for i = 1, total_items do&lt;br /&gt;
            if i == total_items then&lt;br /&gt;
                items[i] = items[i] .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            else&lt;br /&gt;
                items[i] = items[i] .. &#039;&amp;lt;span class=&amp;quot;item-nav-search-sep&amp;quot;&amp;gt; &amp;amp;bull; &amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return table.concat(items, sep)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Item Navbox]]&lt;br /&gt;
function p.get_item_nav_bulletpoints(slot, min_souls, max_souls, debug_mode, filter_mode)&lt;br /&gt;
    if type(slot) == &amp;quot;table&amp;quot; and slot.args then&lt;br /&gt;
        local frame = slot&lt;br /&gt;
        slot = frame.args[1]&lt;br /&gt;
        min_souls = frame.args[2]&lt;br /&gt;
        max_souls = frame.args[3]&lt;br /&gt;
        debug_mode = frame.args[&amp;quot;debug_mode&amp;quot;]&lt;br /&gt;
        filter_mode = frame.args[&amp;quot;filter&amp;quot;]&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local item_list = write_wrapped_item_list(slot, min_souls, max_souls, &amp;quot;ItemIcon&amp;quot;, &#039;&#039;, filter_mode)&lt;br /&gt;
    return process_debug_mode(item_list, debug_mode)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Infobox ShopItems]]&lt;br /&gt;
function p.get_item_nav_cards(slot, min_souls, max_souls, debug_mode, filter_mode)&lt;br /&gt;
    if type(slot) == &amp;quot;table&amp;quot; and slot.args then&lt;br /&gt;
        local frame = slot&lt;br /&gt;
        slot = frame.args[1]&lt;br /&gt;
        min_souls = frame.args[2]&lt;br /&gt;
        max_souls = frame.args[3]&lt;br /&gt;
        debug_mode = frame.args[&amp;quot;debug_mode&amp;quot;]&lt;br /&gt;
        filter_mode = frame.args[&amp;quot;filter&amp;quot;]&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local item_list = write_wrapped_item_list(slot, min_souls, max_souls, &amp;quot;ItemBox&amp;quot;, &#039; &#039;, filter_mode)&lt;br /&gt;
    return process_debug_mode(item_list, debug_mode)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Item Navbox]] subgroup rows&lt;br /&gt;
function p.write_item_slot_subgroup(frame)&lt;br /&gt;
    local slot = frame.args[1]&lt;br /&gt;
    local type_func = frame.args[2]&lt;br /&gt;
    local debug_mode = frame.args[&#039;debug_mode&#039;]&lt;br /&gt;
    local street_brawl_label = frame.args[&#039;street_brawl_label&#039;] or &#039;{{Legendary|{{#invoke:Lang|get_string|Citadel_ItemDraft_Legendary}}}}&#039;&lt;br /&gt;
    &lt;br /&gt;
    if slot == nil then return &amp;quot;&#039;slot&#039; parameter is required&amp;quot; end&lt;br /&gt;
    &lt;br /&gt;
    local template_args = {&lt;br /&gt;
        [&amp;quot;groupstyle&amp;quot;] = &amp;quot;background-color:&amp;quot; .. util_module.get_slot_color(slot) .. &amp;quot;;width:10%;min-width:70px;border-radius: 8px 0 0 8px&amp;quot;,&lt;br /&gt;
        [&amp;quot;grouppadding&amp;quot;] = &amp;quot;5px&amp;quot;,&lt;br /&gt;
        [&amp;quot;listpadding&amp;quot;] = &amp;quot;0 0.25rem&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local soul_style = &amp;quot;font-size: 12px; text-shadow: 1px 1px rgba(0, 0, 0, 0.3);&amp;quot;&lt;br /&gt;
    local prices = generic_module.get_item_price_per_tier()&lt;br /&gt;
    local group_index = 1&lt;br /&gt;
    &lt;br /&gt;
    for i, souls in ipairs(prices) do&lt;br /&gt;
        local min_souls = souls&lt;br /&gt;
        &lt;br /&gt;
        if min_souls ~= 0 then &lt;br /&gt;
            local max_souls = prices[i+1] or (min_souls * 10)&lt;br /&gt;
            &lt;br /&gt;
            local list&lt;br /&gt;
            if type_func == &#039;get_item_nav_cards&#039; then&lt;br /&gt;
                list = p.get_item_nav_cards(slot, min_souls, max_souls, debug_mode, &amp;quot;exclude_street_brawl&amp;quot;)&lt;br /&gt;
            elseif type_func == &#039;get_item_nav_bulletpoints&#039; then&lt;br /&gt;
                list = p.get_item_nav_bulletpoints(slot, min_souls, max_souls, debug_mode, &amp;quot;exclude_street_brawl&amp;quot;)&lt;br /&gt;
            else&lt;br /&gt;
                return &amp;quot;&#039;type&#039; should be get_item_nav_cards or get_item_nav_bulletpoints&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            if list and list ~= &amp;quot;&amp;quot; then&lt;br /&gt;
                template_args[&amp;quot;group&amp;quot; .. group_index] = frame:expandTemplate{title=&amp;quot;Souls&amp;quot;, args={[1] = min_souls, [&amp;quot;Shadow&amp;quot;] = soul_style}}&lt;br /&gt;
                template_args[&amp;quot;list&amp;quot; .. group_index] = list&lt;br /&gt;
                group_index = group_index + 1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local sb_list&lt;br /&gt;
    if type_func == &#039;get_item_nav_cards&#039; then&lt;br /&gt;
        sb_list = p.get_item_nav_cards(slot, 0, 999999, debug_mode, &amp;quot;street_brawl_only&amp;quot;)&lt;br /&gt;
    elseif type_func == &#039;get_item_nav_bulletpoints&#039; then&lt;br /&gt;
        sb_list = p.get_item_nav_bulletpoints(slot, 0, 999999, debug_mode, &amp;quot;street_brawl_only&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    if sb_list and sb_list ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        local sb_style = &amp;quot;color:#98ffde; font-family:&#039;Retail Demo&#039;, sans-serif; text-wrap: nowrap; text-shadow: 0px 0px 2px #2c312e, 1.3px 1.3px rgba(0, 0, 0, 0.2);padding:5px;&amp;quot;&lt;br /&gt;
        local sb_link_text = &amp;quot;[[Street Brawl{{if_lang}}|&amp;lt;span style=\&amp;quot;&amp;quot; .. sb_style .. &amp;quot;\&amp;quot;&amp;gt;&amp;lt;b&amp;gt;&amp;quot; .. street_brawl_label .. &amp;quot;&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;]]&amp;quot;&lt;br /&gt;
        template_args[&amp;quot;group&amp;quot; .. group_index] = frame:preprocess(sb_link_text)&lt;br /&gt;
        template_args[&amp;quot;list&amp;quot; .. group_index] = sb_list&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return frame:expandTemplate{title=&amp;quot;Navbox subgroup&amp;quot;, args=template_args}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Active Items]]&lt;br /&gt;
&lt;br /&gt;
-- Displayed when a stat does not apply to an item&lt;br /&gt;
local NO_VALUE = &amp;quot;—&amp;quot;&lt;br /&gt;
&lt;br /&gt;
-- One expanded inline attribute as produced by [[Module:Lang]]:&lt;br /&gt;
-- wrapper span &amp;gt; icon span &amp;gt; spacer span &amp;gt; wikilink&lt;br /&gt;
local INLINE_ATTRIBUTE_PATTERN =&lt;br /&gt;
    &#039;&amp;lt;span class=&amp;quot;no%-blue%-link&amp;quot; style=&amp;quot;text%-wrap:nowrap; font%-weight:bold; color:[^;&amp;quot;]*;&amp;quot;&amp;gt;&#039; ..&lt;br /&gt;
    &#039;&amp;lt;span style=&amp;quot;[^&amp;quot;]*&amp;quot;&amp;gt;%[%[File:[^%]]*%]%]&amp;lt;/span&amp;gt;&#039; ..&lt;br /&gt;
    &#039;&amp;lt;span style=&amp;quot;color: inherit;&amp;quot;&amp;gt; &amp;lt;/span&amp;gt; &#039; ..&lt;br /&gt;
    &#039;%[%[([^|%]]+)|([^%]]*)%]%]&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
-- Range is taken from the first of these the item has a usable value for&lt;br /&gt;
local RANGE_PROPERTIES = { &amp;quot;AbilityCastRange&amp;quot;, &amp;quot;Radius&amp;quot;, &amp;quot;EndRadius&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
-- Rewrites the description markup [[Module:Lang]] produces&lt;br /&gt;
local function restyle_description(text)&lt;br /&gt;
    text = text:gsub(INLINE_ATTRIBUTE_PATTERN, &#039;[[%1|%2]]&#039;)&lt;br /&gt;
    -- Attributes with an icon but no link keep their span; follow the site text color&lt;br /&gt;
    text = text:gsub(&#039;color:#ffefd7;&#039;, &#039;color:var(--color-base);&#039;)&lt;br /&gt;
    -- Diminished notes (&amp;quot;Cannot be used while Stunned...&amp;quot;)&lt;br /&gt;
    return (text:gsub(&#039;color:#C0C0C0&#039;, &#039;color:var(--color-subtle)&#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Numeric value of a stat, used for sorting&lt;br /&gt;
local function stat_sort_value(value)&lt;br /&gt;
    if type(value) == &amp;quot;table&amp;quot; then value = value[&amp;quot;Value&amp;quot;] end&lt;br /&gt;
    if value == nil then return -1 end&lt;br /&gt;
    return tonumber(tostring(value):match(&amp;quot;[-%d%.]+&amp;quot;)) or -1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- First range property the item has a usable value for&lt;br /&gt;
local function get_range_property(item_data)&lt;br /&gt;
    for _, property in ipairs(RANGE_PROPERTIES) do&lt;br /&gt;
        local value = item_data[property]&lt;br /&gt;
        if value ~= nil and stat_sort_value(value) &amp;gt; 0 then&lt;br /&gt;
            return property, value&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return nil, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Builds a stat cell, falling back to an em dash when the stat does not apply&lt;br /&gt;
local function stat_cell(raw_value, item_name, property, postfix)&lt;br /&gt;
    if raw_value == nil or property == nil then&lt;br /&gt;
        return &#039;| data-sort-value=&amp;quot;-1&amp;quot; style=&amp;quot;text-align:center;font-size:16px&amp;quot; | &#039; .. NO_VALUE&lt;br /&gt;
    end&lt;br /&gt;
    return string.format(&lt;br /&gt;
        &#039;| data-sort-value=&amp;quot;%s&amp;quot; style=&amp;quot;text-align:center;font-size:16px&amp;quot; | {{#invoke:ItemData|get_prop|%s|%s}}%s&#039;,&lt;br /&gt;
        stat_sort_value(raw_value), item_name, property, postfix or &amp;quot;&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.generate_active_items_table(frame)&lt;br /&gt;
    local active_items = {}&lt;br /&gt;
    &lt;br /&gt;
    for item_key, item_data in pairs(items_data) do&lt;br /&gt;
        local cost = tonumber(item_data[&amp;quot;Cost&amp;quot;])&lt;br /&gt;
        if item_data[&amp;quot;Name&amp;quot;] and &lt;br /&gt;
           item_data[&amp;quot;IsDisabled&amp;quot;] == false and &lt;br /&gt;
           cost ~= nil and cost &amp;gt; 0 and &lt;br /&gt;
           item_data[&amp;quot;Activation&amp;quot;] and &lt;br /&gt;
           item_data[&amp;quot;Activation&amp;quot;] ~= &amp;quot;Passive&amp;quot; then&lt;br /&gt;
            &lt;br /&gt;
            local range_property, range_value = get_range_property(item_data)&lt;br /&gt;
            &lt;br /&gt;
            table.insert(active_items, {&lt;br /&gt;
                name = item_data[&amp;quot;Name&amp;quot;],&lt;br /&gt;
                key = item_key,&lt;br /&gt;
                cost = cost,&lt;br /&gt;
                slot = item_data[&amp;quot;Slot&amp;quot;] or &amp;quot;Weapon&amp;quot;,&lt;br /&gt;
                has_active_desc = item_data[&amp;quot;ActiveDescription&amp;quot;] ~= nil,&lt;br /&gt;
                cooldown = item_data[&amp;quot;AbilityCooldown&amp;quot;],&lt;br /&gt;
                duration = item_data[&amp;quot;AbilityDuration&amp;quot;],&lt;br /&gt;
                range_property = range_property,&lt;br /&gt;
                range_value = range_value&lt;br /&gt;
            })&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    table.sort(active_items, function(a, b) return a.name &amp;lt; b.name end)&lt;br /&gt;
    &lt;br /&gt;
    -- Optimized string compilation using a structural buffer table&lt;br /&gt;
    local rows = {}&lt;br /&gt;
    table.insert(rows, [=[{| class=&amp;quot;wikitable mw-collapsible sortable&amp;quot; style=&amp;quot;width:100%&amp;quot; &lt;br /&gt;
|+{{#invoke:Dictionary|translate|Active Items}}&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; | {{#invoke:Lang|get_string|Citadel_HeroBuilds_CategoryNameLabel}}&lt;br /&gt;
! {{#invoke:Lang|get_string|Citadel_UserFeedback_TypeLabel}}&lt;br /&gt;
! {{Souls|{{#invoke:Dictionary|translate|Cost}}}}&lt;br /&gt;
! {{#invoke:Lang|get_string|Citadel_Mod_Tooltip_Active}}&lt;br /&gt;
! {{#invoke:Lang|get_string|AbilityCooldown_label}}&lt;br /&gt;
! {{#invoke:Lang|get_string|AbilityDuration_label}}&lt;br /&gt;
! {{#invoke:Lang|get_string|AbilityCastRange_label}}]=])&lt;br /&gt;
    &lt;br /&gt;
    for _, item in ipairs(active_items) do&lt;br /&gt;
        local bg_color = util_module.get_slot_color(item.slot)&lt;br /&gt;
&lt;br /&gt;
		local item_type&lt;br /&gt;
		if item.slot == &amp;quot;Armor&amp;quot; then&lt;br /&gt;
		    item_type = &amp;quot;Armor&amp;quot;&lt;br /&gt;
		elseif item.slot == &amp;quot;Tech&amp;quot; then&lt;br /&gt;
		    item_type = &amp;quot;Tech&amp;quot;&lt;br /&gt;
		else&lt;br /&gt;
		    item_type = &amp;quot;Weapon&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
        &lt;br /&gt;
        local row = string.format([=[&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;background-color:%s&amp;quot; | [[File:%s.png|64x64px]]&lt;br /&gt;
! [[%s{{If_lang}}|{{#invoke:Lang|get_string|%s}}]]&lt;br /&gt;
| style=&amp;quot;text-align:center;font-weight:bold&amp;quot; | {{ItemType|%s|{{#invoke:Lang|get_string|CitadelCategory%s}}}}&lt;br /&gt;
| data-sort-value=&amp;quot;%d&amp;quot; style=&amp;quot;text-align:center;font-size:15px&amp;quot; | {{Souls|%d}}&lt;br /&gt;
| {{#invoke:Utilities|process_variables|%s_active_desc|%s}}{{#invoke:Utilities|process_variables|%s_desc|%s}}{{#invoke:Utilities|process_variables|%s_active|%s}}&lt;br /&gt;
%s&lt;br /&gt;
%s&lt;br /&gt;
%s]=],&lt;br /&gt;
            bg_color, &lt;br /&gt;
            item.name, &lt;br /&gt;
            item.name, item.key,&lt;br /&gt;
            item_type, item_type,&lt;br /&gt;
            item.cost, item.cost,&lt;br /&gt;
            item.key, item.name, item.key, item.name, item.key, item.name,&lt;br /&gt;
            stat_cell(item.cooldown, item.name, &amp;quot;AbilityCooldown&amp;quot;, &amp;quot;s&amp;quot;),&lt;br /&gt;
            stat_cell(item.duration, item.name, &amp;quot;AbilityDuration&amp;quot;, &amp;quot;s&amp;quot;),&lt;br /&gt;
            stat_cell(item.range_value, item.name, item.range_property))&lt;br /&gt;
            &lt;br /&gt;
        table.insert(rows, row)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    table.insert(rows, &amp;quot;\n|}&amp;quot;)&lt;br /&gt;
    return restyle_description(frame:preprocess(table.concat(rows, &amp;quot;\n&amp;quot;)))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>~2026-LaneLeechSecure746</name></author>
	</entry>
	<entry>
		<id>https://deadlock.wiki/Module:ItemData/nav?diff=99226</id>
		<title>Module:ItemData/nav</title>
		<link rel="alternate" type="text/html" href="https://deadlock.wiki/Module:ItemData/nav?diff=99226"/>
		<updated>2026-07-23T20:32:21Z</updated>

		<summary type="html">&lt;p&gt;~2026-LaneLeechSecure746: Active Items table: plain wikilinks for inline attributes, var(--color-base) for off-white styling, em dash for missing stats, add Duration and Cast Range columns (with help from vergir-bot LLM)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
local p = {}&lt;br /&gt;
local items_data = mw.loadJsonData(&amp;quot;Data:ItemData.json&amp;quot;)&lt;br /&gt;
local lang_module = require(&#039;Module:Lang&#039;)&lt;br /&gt;
local generic_module = require(&#039;Module:GenericData&#039;)&lt;br /&gt;
local util_module = require(&#039;Module:Utilities&#039;)&lt;br /&gt;
&lt;br /&gt;
-- Exceptions if the link is different from the item name&lt;br /&gt;
local linkOverrides = {&lt;br /&gt;
    [&amp;quot;Bullet Lifesteal&amp;quot;] = &amp;quot;Bullet Lifesteal (item)&amp;quot;,&lt;br /&gt;
    [&amp;quot;Spirit Lifesteal&amp;quot;] = &amp;quot;Spirit Lifesteal (item)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Cached items grouped by slot to prevent redundant full-table evaluations&lt;br /&gt;
local cached_slots = nil&lt;br /&gt;
local function get_items_by_slot(slot)&lt;br /&gt;
    if not cached_slots then&lt;br /&gt;
        cached_slots = { table = {}, Weapon = {}, Armor = {}, Tech = {} }&lt;br /&gt;
        for item_key, item_data in pairs(items_data) do&lt;br /&gt;
            local this_slot = item_data[&amp;quot;Slot&amp;quot;]&lt;br /&gt;
            if this_slot and cached_slots[this_slot] then&lt;br /&gt;
                table.insert(cached_slots[this_slot], { key = item_key, data = item_data })&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return cached_slots[slot] or {}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- With debug_mode on, it outputs unprocessed wikitext&lt;br /&gt;
local function process_debug_mode(wikitext, debug_mode)&lt;br /&gt;
    if debug_mode == &#039;true&#039; then&lt;br /&gt;
        return wikitext&lt;br /&gt;
    elseif debug_mode == &#039;false&#039; or debug_mode == nil then&lt;br /&gt;
        return mw.getCurrentFrame():preprocess(wikitext)&lt;br /&gt;
    else&lt;br /&gt;
        return &amp;quot;debug_mode must be &#039;true&#039; or &#039;false&#039;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Writes list of items of a certain slot within the min and max soul bounds&lt;br /&gt;
local function write_wrapped_item_list(slot, min_souls, max_souls, template, sep, filter_mode)&lt;br /&gt;
    if slot ~= &#039;Weapon&#039; and slot ~= &#039;Armor&#039; and slot ~= &#039;Tech&#039; then&lt;br /&gt;
        return &#039;slot must be Weapon, Armor (Vitality), or Tech (Spirit)&#039;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local min_souls = tonumber(min_souls)&lt;br /&gt;
    local max_souls = tonumber(max_souls)&lt;br /&gt;
    if min_souls == nil or max_souls == nil then return &#039;Min/Max souls must be numerical&#039; end&lt;br /&gt;
    &lt;br /&gt;
    filter_mode = filter_mode or &amp;quot;all&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    -- Lifted out of the loop: Language code doesn&#039;t change per item&lt;br /&gt;
    local lang_code = lang_module.get_lang_code() &lt;br /&gt;
    &lt;br /&gt;
    local items = {}&lt;br /&gt;
    local slot_items = get_items_by_slot(slot) -- Drastically reduces search pool size&lt;br /&gt;
    &lt;br /&gt;
    for _, item_entry in ipairs(slot_items) do&lt;br /&gt;
        local item_key = item_entry.key&lt;br /&gt;
        local item_data = item_entry.data&lt;br /&gt;
        &lt;br /&gt;
        local this_cost = tonumber(item_data[&amp;quot;Cost&amp;quot;])&lt;br /&gt;
        local is_street_brawl = item_data[&amp;quot;StreetBrawl&amp;quot;] == true&lt;br /&gt;
        local should_include = true&lt;br /&gt;
        &lt;br /&gt;
        -- Filter logic for Street Brawl items&lt;br /&gt;
        if filter_mode == &amp;quot;street_brawl_only&amp;quot; and not is_street_brawl then&lt;br /&gt;
            should_include = false&lt;br /&gt;
        elseif filter_mode == &amp;quot;exclude_street_brawl&amp;quot; and is_street_brawl then&lt;br /&gt;
            should_include = false&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        if should_include and item_data[&amp;quot;Name&amp;quot;] ~= nil and item_data[&amp;quot;IsDisabled&amp;quot;] == false and this_cost ~= nil then&lt;br /&gt;
            if this_cost &amp;gt;= min_souls and this_cost &amp;lt; max_souls then&lt;br /&gt;
                local item_name_english = lang_module.get_string(item_key, &amp;quot;en&amp;quot;)&lt;br /&gt;
                local item_link = linkOverrides[item_name_english] or item_name_english&lt;br /&gt;
                local item_name_local = lang_module.get_string(item_key, lang_code)&lt;br /&gt;
                &lt;br /&gt;
                local item_template&lt;br /&gt;
                if template == &amp;quot;ItemIcon&amp;quot; then&lt;br /&gt;
                    if lang_code == &amp;quot;en&amp;quot; then&lt;br /&gt;
                        item_template = &amp;quot;{{ItemIcon|&amp;quot; .. item_name_english .. &amp;quot;|size=26px}}&amp;quot;&lt;br /&gt;
                    else&lt;br /&gt;
                        item_template = &amp;quot;{{ItemIcon|&amp;quot; .. item_name_english .. &amp;quot;|lang=&amp;quot; .. lang_code .. &amp;quot;|l1=&amp;quot; .. item_name_local .. &amp;quot;|size=26px}}&amp;quot;&lt;br /&gt;
                    end&lt;br /&gt;
                    &lt;br /&gt;
                    local search_data = item_name_english&lt;br /&gt;
                    if lang_code ~= &amp;quot;en&amp;quot; and item_name_local then&lt;br /&gt;
                        search_data = search_data .. &amp;quot; &amp;quot; .. item_name_local&lt;br /&gt;
                    end&lt;br /&gt;
                    &lt;br /&gt;
                    item_template = &#039;&amp;lt;span class=&amp;quot;item-nav-search-wrapper&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;item-nav-search-item&amp;quot; data-item-name=&amp;quot;&#039; .. search_data .. &#039;&amp;quot;&amp;gt;&#039; .. item_template .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
                elseif template == &amp;quot;ItemBox&amp;quot; then&lt;br /&gt;
                    if lang_code == &amp;quot;en&amp;quot; then&lt;br /&gt;
                        if is_street_brawl then&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. item_link .. &amp;quot;|overrideTier=5}}&amp;quot;&lt;br /&gt;
                        else&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. item_link .. &amp;quot;}}&amp;quot;&lt;br /&gt;
                        end&lt;br /&gt;
                    else&lt;br /&gt;
                        local link_local = item_link .. &amp;quot;/&amp;quot; .. lang_code&lt;br /&gt;
                        if is_street_brawl then&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. link_local .. &amp;quot;|item_price={{#invoke:Lang|get_string|Citadel_ItemDraft_Legendary}}}}&amp;quot;&lt;br /&gt;
                        else&lt;br /&gt;
                            item_template = &amp;quot;{{ItemBox|itemName=&amp;quot; .. item_name_english .. &amp;quot;|overrideLinkClick=&amp;quot; .. link_local .. &amp;quot;}}&amp;quot;&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                else&lt;br /&gt;
                    return &amp;quot;Invalid template type&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
                table.insert(items, item_template)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Order list alphabetically&lt;br /&gt;
    table.sort(items)&lt;br /&gt;
    &lt;br /&gt;
    -- Append closing tags and bullets&lt;br /&gt;
    if template == &amp;quot;ItemIcon&amp;quot; then&lt;br /&gt;
        local total_items = #items&lt;br /&gt;
        for i = 1, total_items do&lt;br /&gt;
            if i == total_items then&lt;br /&gt;
                items[i] = items[i] .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            else&lt;br /&gt;
                items[i] = items[i] .. &#039;&amp;lt;span class=&amp;quot;item-nav-search-sep&amp;quot;&amp;gt; &amp;amp;bull; &amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return table.concat(items, sep)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Item Navbox]]&lt;br /&gt;
function p.get_item_nav_bulletpoints(slot, min_souls, max_souls, debug_mode, filter_mode)&lt;br /&gt;
    if type(slot) == &amp;quot;table&amp;quot; and slot.args then&lt;br /&gt;
        local frame = slot&lt;br /&gt;
        slot = frame.args[1]&lt;br /&gt;
        min_souls = frame.args[2]&lt;br /&gt;
        max_souls = frame.args[3]&lt;br /&gt;
        debug_mode = frame.args[&amp;quot;debug_mode&amp;quot;]&lt;br /&gt;
        filter_mode = frame.args[&amp;quot;filter&amp;quot;]&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local item_list = write_wrapped_item_list(slot, min_souls, max_souls, &amp;quot;ItemIcon&amp;quot;, &#039;&#039;, filter_mode)&lt;br /&gt;
    return process_debug_mode(item_list, debug_mode)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Infobox ShopItems]]&lt;br /&gt;
function p.get_item_nav_cards(slot, min_souls, max_souls, debug_mode, filter_mode)&lt;br /&gt;
    if type(slot) == &amp;quot;table&amp;quot; and slot.args then&lt;br /&gt;
        local frame = slot&lt;br /&gt;
        slot = frame.args[1]&lt;br /&gt;
        min_souls = frame.args[2]&lt;br /&gt;
        max_souls = frame.args[3]&lt;br /&gt;
        debug_mode = frame.args[&amp;quot;debug_mode&amp;quot;]&lt;br /&gt;
        filter_mode = frame.args[&amp;quot;filter&amp;quot;]&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local item_list = write_wrapped_item_list(slot, min_souls, max_souls, &amp;quot;ItemBox&amp;quot;, &#039; &#039;, filter_mode)&lt;br /&gt;
    return process_debug_mode(item_list, debug_mode)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Item Navbox]] subgroup rows&lt;br /&gt;
function p.write_item_slot_subgroup(frame)&lt;br /&gt;
    local slot = frame.args[1]&lt;br /&gt;
    local type_func = frame.args[2]&lt;br /&gt;
    local debug_mode = frame.args[&#039;debug_mode&#039;]&lt;br /&gt;
    local street_brawl_label = frame.args[&#039;street_brawl_label&#039;] or &#039;{{Legendary|{{#invoke:Lang|get_string|Citadel_ItemDraft_Legendary}}}}&#039;&lt;br /&gt;
    &lt;br /&gt;
    if slot == nil then return &amp;quot;&#039;slot&#039; parameter is required&amp;quot; end&lt;br /&gt;
    &lt;br /&gt;
    local template_args = {&lt;br /&gt;
        [&amp;quot;groupstyle&amp;quot;] = &amp;quot;background-color:&amp;quot; .. util_module.get_slot_color(slot) .. &amp;quot;;width:10%;min-width:70px;border-radius: 8px 0 0 8px&amp;quot;,&lt;br /&gt;
        [&amp;quot;grouppadding&amp;quot;] = &amp;quot;5px&amp;quot;,&lt;br /&gt;
        [&amp;quot;listpadding&amp;quot;] = &amp;quot;0 0.25rem&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local soul_style = &amp;quot;font-size: 12px; text-shadow: 1px 1px rgba(0, 0, 0, 0.3);&amp;quot;&lt;br /&gt;
    local prices = generic_module.get_item_price_per_tier()&lt;br /&gt;
    local group_index = 1&lt;br /&gt;
    &lt;br /&gt;
    for i, souls in ipairs(prices) do&lt;br /&gt;
        local min_souls = souls&lt;br /&gt;
        &lt;br /&gt;
        if min_souls ~= 0 then &lt;br /&gt;
            local max_souls = prices[i+1] or (min_souls * 10)&lt;br /&gt;
            &lt;br /&gt;
            local list&lt;br /&gt;
            if type_func == &#039;get_item_nav_cards&#039; then&lt;br /&gt;
                list = p.get_item_nav_cards(slot, min_souls, max_souls, debug_mode, &amp;quot;exclude_street_brawl&amp;quot;)&lt;br /&gt;
            elseif type_func == &#039;get_item_nav_bulletpoints&#039; then&lt;br /&gt;
                list = p.get_item_nav_bulletpoints(slot, min_souls, max_souls, debug_mode, &amp;quot;exclude_street_brawl&amp;quot;)&lt;br /&gt;
            else&lt;br /&gt;
                return &amp;quot;&#039;type&#039; should be get_item_nav_cards or get_item_nav_bulletpoints&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            if list and list ~= &amp;quot;&amp;quot; then&lt;br /&gt;
                template_args[&amp;quot;group&amp;quot; .. group_index] = frame:expandTemplate{title=&amp;quot;Souls&amp;quot;, args={[1] = min_souls, [&amp;quot;Shadow&amp;quot;] = soul_style}}&lt;br /&gt;
                template_args[&amp;quot;list&amp;quot; .. group_index] = list&lt;br /&gt;
                group_index = group_index + 1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local sb_list&lt;br /&gt;
    if type_func == &#039;get_item_nav_cards&#039; then&lt;br /&gt;
        sb_list = p.get_item_nav_cards(slot, 0, 999999, debug_mode, &amp;quot;street_brawl_only&amp;quot;)&lt;br /&gt;
    elseif type_func == &#039;get_item_nav_bulletpoints&#039; then&lt;br /&gt;
        sb_list = p.get_item_nav_bulletpoints(slot, 0, 999999, debug_mode, &amp;quot;street_brawl_only&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    if sb_list and sb_list ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        local sb_style = &amp;quot;color:#98ffde; font-family:&#039;Retail Demo&#039;, sans-serif; text-wrap: nowrap; text-shadow: 0px 0px 2px #2c312e, 1.3px 1.3px rgba(0, 0, 0, 0.2);padding:5px;&amp;quot;&lt;br /&gt;
        local sb_link_text = &amp;quot;[[Street Brawl{{if_lang}}|&amp;lt;span style=\&amp;quot;&amp;quot; .. sb_style .. &amp;quot;\&amp;quot;&amp;gt;&amp;lt;b&amp;gt;&amp;quot; .. street_brawl_label .. &amp;quot;&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;]]&amp;quot;&lt;br /&gt;
        template_args[&amp;quot;group&amp;quot; .. group_index] = frame:preprocess(sb_link_text)&lt;br /&gt;
        template_args[&amp;quot;list&amp;quot; .. group_index] = sb_list&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return frame:expandTemplate{title=&amp;quot;Navbox subgroup&amp;quot;, args=template_args}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- for [[Template:Active Items]]&lt;br /&gt;
&lt;br /&gt;
-- Displayed when a stat does not apply to an item&lt;br /&gt;
local NO_VALUE = &amp;quot;—&amp;quot;&lt;br /&gt;
&lt;br /&gt;
-- One expanded inline attribute as produced by [[Module:Lang]]:&lt;br /&gt;
-- wrapper span &amp;gt; icon span &amp;gt; spacer span &amp;gt; wikilink&lt;br /&gt;
local INLINE_ATTRIBUTE_PATTERN =&lt;br /&gt;
    &#039;&amp;lt;span class=&amp;quot;no%-blue%-link&amp;quot; style=&amp;quot;text%-wrap:nowrap; font%-weight:bold; color:[^;&amp;quot;]*;&amp;quot;&amp;gt;&#039; ..&lt;br /&gt;
    &#039;&amp;lt;span style=&amp;quot;[^&amp;quot;]*&amp;quot;&amp;gt;%[%[File:[^%]]*%]%]&amp;lt;/span&amp;gt;&#039; ..&lt;br /&gt;
    &#039;&amp;lt;span style=&amp;quot;color: inherit;&amp;quot;&amp;gt; &amp;lt;/span&amp;gt; &#039; ..&lt;br /&gt;
    &#039;%[%[([^|%]]+)|([^%]]*)%]%]&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
-- Range is taken from the first of these the item has a usable value for&lt;br /&gt;
local RANGE_PROPERTIES = { &amp;quot;AbilityCastRange&amp;quot;, &amp;quot;Radius&amp;quot;, &amp;quot;EndRadius&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
-- Strips the icon markup from inline attributes, leaving plain wikilinks&lt;br /&gt;
local function restyle_inline_attributes(text)&lt;br /&gt;
    text = text:gsub(INLINE_ATTRIBUTE_PATTERN, &#039;[[%1|%2]]&#039;)&lt;br /&gt;
    -- Attributes with an icon but no link keep their span; follow the site text color&lt;br /&gt;
    return (text:gsub(&#039;color:#ffefd7;&#039;, &#039;color:var(--color-base);&#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Numeric value of a stat, used for sorting&lt;br /&gt;
local function stat_sort_value(value)&lt;br /&gt;
    if type(value) == &amp;quot;table&amp;quot; then value = value[&amp;quot;Value&amp;quot;] end&lt;br /&gt;
    if value == nil then return -1 end&lt;br /&gt;
    return tonumber(tostring(value):match(&amp;quot;[-%d%.]+&amp;quot;)) or -1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- First range property the item has a usable value for&lt;br /&gt;
local function get_range_property(item_data)&lt;br /&gt;
    for _, property in ipairs(RANGE_PROPERTIES) do&lt;br /&gt;
        local value = item_data[property]&lt;br /&gt;
        if value ~= nil and stat_sort_value(value) &amp;gt; 0 then&lt;br /&gt;
            return property, value&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return nil, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Builds a stat cell, falling back to an em dash when the stat does not apply&lt;br /&gt;
local function stat_cell(raw_value, item_name, property, postfix)&lt;br /&gt;
    if raw_value == nil or property == nil then&lt;br /&gt;
        return &#039;| data-sort-value=&amp;quot;-1&amp;quot; style=&amp;quot;text-align:center;font-size:16px&amp;quot; | &#039; .. NO_VALUE&lt;br /&gt;
    end&lt;br /&gt;
    return string.format(&lt;br /&gt;
        &#039;| data-sort-value=&amp;quot;%s&amp;quot; style=&amp;quot;text-align:center;font-size:16px&amp;quot; | {{#invoke:ItemData|get_prop|%s|%s}}%s&#039;,&lt;br /&gt;
        stat_sort_value(raw_value), item_name, property, postfix or &amp;quot;&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.generate_active_items_table(frame)&lt;br /&gt;
    local active_items = {}&lt;br /&gt;
    &lt;br /&gt;
    for item_key, item_data in pairs(items_data) do&lt;br /&gt;
        local cost = tonumber(item_data[&amp;quot;Cost&amp;quot;])&lt;br /&gt;
        if item_data[&amp;quot;Name&amp;quot;] and &lt;br /&gt;
           item_data[&amp;quot;IsDisabled&amp;quot;] == false and &lt;br /&gt;
           cost ~= nil and cost &amp;gt; 0 and &lt;br /&gt;
           item_data[&amp;quot;Activation&amp;quot;] and &lt;br /&gt;
           item_data[&amp;quot;Activation&amp;quot;] ~= &amp;quot;Passive&amp;quot; then&lt;br /&gt;
            &lt;br /&gt;
            local range_property, range_value = get_range_property(item_data)&lt;br /&gt;
            &lt;br /&gt;
            table.insert(active_items, {&lt;br /&gt;
                name = item_data[&amp;quot;Name&amp;quot;],&lt;br /&gt;
                key = item_key,&lt;br /&gt;
                cost = cost,&lt;br /&gt;
                slot = item_data[&amp;quot;Slot&amp;quot;] or &amp;quot;Weapon&amp;quot;,&lt;br /&gt;
                has_active_desc = item_data[&amp;quot;ActiveDescription&amp;quot;] ~= nil,&lt;br /&gt;
                cooldown = item_data[&amp;quot;AbilityCooldown&amp;quot;],&lt;br /&gt;
                duration = item_data[&amp;quot;AbilityDuration&amp;quot;],&lt;br /&gt;
                range_property = range_property,&lt;br /&gt;
                range_value = range_value&lt;br /&gt;
            })&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    table.sort(active_items, function(a, b) return a.name &amp;lt; b.name end)&lt;br /&gt;
    &lt;br /&gt;
    -- Optimized string compilation using a structural buffer table&lt;br /&gt;
    local rows = {}&lt;br /&gt;
    table.insert(rows, [=[{| class=&amp;quot;wikitable mw-collapsible sortable&amp;quot; style=&amp;quot;width:100%&amp;quot; &lt;br /&gt;
|+{{#invoke:Dictionary|translate|Active Items}}&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; | {{#invoke:Lang|get_string|Citadel_HeroBuilds_CategoryNameLabel}}&lt;br /&gt;
! {{#invoke:Lang|get_string|Citadel_UserFeedback_TypeLabel}}&lt;br /&gt;
! {{Souls|{{#invoke:Dictionary|translate|Cost}}}}&lt;br /&gt;
! {{#invoke:Lang|get_string|Citadel_Mod_Tooltip_Active}}&lt;br /&gt;
! {{#invoke:Lang|get_string|AbilityCooldown_label}}&lt;br /&gt;
! {{#invoke:Lang|get_string|AbilityDuration_label}}&lt;br /&gt;
! {{#invoke:Lang|get_string|AbilityCastRange_label}}]=])&lt;br /&gt;
    &lt;br /&gt;
    for _, item in ipairs(active_items) do&lt;br /&gt;
        local bg_color = util_module.get_slot_color(item.slot)&lt;br /&gt;
&lt;br /&gt;
		local item_type&lt;br /&gt;
		if item.slot == &amp;quot;Armor&amp;quot; then&lt;br /&gt;
		    item_type = &amp;quot;Armor&amp;quot;&lt;br /&gt;
		elseif item.slot == &amp;quot;Tech&amp;quot; then&lt;br /&gt;
		    item_type = &amp;quot;Tech&amp;quot;&lt;br /&gt;
		else&lt;br /&gt;
		    item_type = &amp;quot;Weapon&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
        &lt;br /&gt;
        local row = string.format([=[&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;background-color:%s&amp;quot; | [[File:%s.png|64x64px]]&lt;br /&gt;
! [[%s{{If_lang}}|{{#invoke:Lang|get_string|%s}}]]&lt;br /&gt;
| style=&amp;quot;text-align:center;font-weight:bold&amp;quot; | {{ItemType|%s|{{#invoke:Lang|get_string|CitadelCategory%s}}}}&lt;br /&gt;
| data-sort-value=&amp;quot;%d&amp;quot; style=&amp;quot;text-align:center;font-size:15px&amp;quot; | {{Souls|%d}}&lt;br /&gt;
| {{#invoke:Utilities|process_variables|%s_active_desc|%s}}{{#invoke:Utilities|process_variables|%s_desc|%s}}{{#invoke:Utilities|process_variables|%s_active|%s}}&lt;br /&gt;
%s&lt;br /&gt;
%s&lt;br /&gt;
%s]=],&lt;br /&gt;
            bg_color, &lt;br /&gt;
            item.name, &lt;br /&gt;
            item.name, item.key,&lt;br /&gt;
            item_type, item_type,&lt;br /&gt;
            item.cost, item.cost,&lt;br /&gt;
            item.key, item.name, item.key, item.name, item.key, item.name,&lt;br /&gt;
            stat_cell(item.cooldown, item.name, &amp;quot;AbilityCooldown&amp;quot;, &amp;quot;s&amp;quot;),&lt;br /&gt;
            stat_cell(item.duration, item.name, &amp;quot;AbilityDuration&amp;quot;, &amp;quot;s&amp;quot;),&lt;br /&gt;
            stat_cell(item.range_value, item.name, item.range_property))&lt;br /&gt;
            &lt;br /&gt;
        table.insert(rows, row)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    table.insert(rows, &amp;quot;\n|}&amp;quot;)&lt;br /&gt;
    return restyle_inline_attributes(frame:preprocess(table.concat(rows, &amp;quot;\n&amp;quot;)))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>~2026-LaneLeechSecure746</name></author>
	</entry>
</feed>