Editing Module:ItemTables

Warning: You are not logged in. Once you make an edit, a temporary account will be created for you. Learn more. Log in or create an account to continue receiving notifications after this account expires, and to access other features.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
local p = {};
local p = {};
local data = mw.loadJsonData("Data:ItemData.json")
local get_cost = require("Module:ItemData")._get_cost
local get_cost = require("Module:ItemData")._get_cost
local get_type = require("Module:ItemData")._get_type
local get_type = require("Module:ItemData")._get_type
local commas = require("Module:Addcommas")
local commas = require("Module:Addcommas")
local GameData = require("Module:GameData")


-- Translate internal attribute names to plain text for module calls
-- Returns an array of item tables that have the same properties
-- @function  get_similar_items_array
-- @param      {array}
-- @return    {array of tables}
local function get_similar_items_array(property)
local similarItems = {}
local hash = {}
local noDuplicates = {}
for _, v in pairs(data) do
for _, value in ipairs(property) do
if (v[value] ~= nil and v["IsDisabled"] == false and v["Name"] ~= nil and v[value] ~= "0" and v[value] ~= "0m" and v[value] ~= "") then
table.insert(similarItems, v)
end
end
end
-- remove duplicate items if that item contains multiple keys of the same stat increase (eg. Fleetfoot has both "BonusMoveSpeed", "ActiveBonusMoveSpeed" in move speed).
-- there might be a more efficient way to prevent adding duplicate items in the first place in the above for loop
for _, v in pairs(similarItems) do
if (not hash[v]) then
noDuplicates[#noDuplicates+1] = v
hash[v] = true
end
end
return noDuplicates
end
 
--- Copies original table with its children as deep as possible. Does not handle metatables. (Copy is needed because Lua passes by reference, not value)
-- @function  Deepcopy
-- @param      {n-D table}
-- @return    {n-D table}
function Deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[Deepcopy(orig_key)] = Deepcopy(orig_value)
        end
    else
        copy = orig
    end
    return copy
end
 
local friendly_to_internal = {}
local friendly_to_internal = {}
friendly_to_internal["ammo"] = { "BonusClipSizePercent", "BonusClipSize", "ActiveReloadPercent" }
friendly_to_internal["ammo"] = { "BonusClipSizePercent", "BonusClipSize", "ActiveReloadPercent" }
Line 12: Line 56:
friendly_to_internal["bullet shield health"] = { "BulletShieldMaxHealth", "BulletShieldOnCast", "SaviorBulletShieldHealth", "FlyingBulletShield", "VexBarrierBulletMaxHealth" }
friendly_to_internal["bullet shield health"] = { "BulletShieldMaxHealth", "BulletShieldOnCast", "SaviorBulletShieldHealth", "FlyingBulletShield", "VexBarrierBulletMaxHealth" }
friendly_to_internal["spirit shield health"] = { "TechShieldMaxHealth", "TechShieldOnCast", "SaviorMagicShieldHealth", "FlyingTechShield", "VexBarrierTechMaxHealth" }
friendly_to_internal["spirit shield health"] = { "TechShieldMaxHealth", "TechShieldOnCast", "SaviorMagicShieldHealth", "FlyingTechShield", "VexBarrierTechMaxHealth" }
friendly_to_internal["barrier"] = { "CombatBarrier", "GuardianWardCombatBarrier", "VexBarrierCombatBarrier" }
friendly_to_internal["barrier"] = { "CombatBarrier" }
friendly_to_internal["bullet resist"] = { "BulletResist", "LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletResistPerStack" }
friendly_to_internal["bullet resist"] = { "BulletResist", "LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletResistPerStack" }
friendly_to_internal["bullet resist reduction"] = { "BulletArmorReduction", "BulletResistReduction" }
friendly_to_internal["bullet resist reduction"] = { "BulletArmorReduction", "BulletResistReduction" }
Line 18: Line 62:
friendly_to_internal["spirit resist reduction"] = { "TechArmorDamageReduction", "MagicResistReduction" }
friendly_to_internal["spirit resist reduction"] = { "TechArmorDamageReduction", "MagicResistReduction" }
friendly_to_internal["bonus health"] = { "BonusHealth" }
friendly_to_internal["bonus health"] = { "BonusHealth" }
friendly_to_internal["bonus base health"] = { "BonusBaseHealth", "MaxHealthLossPercent" }
friendly_to_internal["health regen"] = { "BonusHealthRegen" }
friendly_to_internal["health regen"] = { "BonusHealthRegen" }
friendly_to_internal["regeneration"] = { "Regeneration" }
friendly_to_internal["regeneration duration"] = { "RegenerationDuration" }
friendly_to_internal["out of combat health regen"] = { "OutOfCombatHealthRegen" }
friendly_to_internal["max health regen"] = { "HealLifePercentOutOfCombat" }
friendly_to_internal["max health regen"] = { "HealLifePercentOutOfCombat" }
friendly_to_internal["fire rate"] = { "BonusFireRate", "FireRateWhenShielded", "FireRateBonus", "FervorFireRate", "AmbushBonusFireRate", "ActiveBonusFireRate", "ActivatedFireRate" }
friendly_to_internal["fire rate"] = { "BonusFireRate", "FireRateWhenShielded", "FireRateBonus", "FervorFireRate", "AmbushBonusFireRate", "ActiveBonusFireRate" }
friendly_to_internal["fire rate slow"] = { "FireRateSlow" }
friendly_to_internal["fire rate slow"] = { "FireRateSlow" }
friendly_to_internal["bullet velocity"] = { "BonusBulletSpeedPercent" }
friendly_to_internal["bullet velocity"] = { "BonusBulletSpeedPercent" }
friendly_to_internal["spirit power"] = { "TechPower", "BonusSpirit", "SpiritPower", "BonusSpiritWithMagicShield", "ImbuedTechPower", "AmbushBonusTechPower", "TechPowerPercent" }
friendly_to_internal["spirit power"] = { "TechPower", "BonusSpirit", "SpiritPower", "BonusSpiritWithMagicShield", "ImbuedTechPower", "AmbushBonusTechPower" }
friendly_to_internal["bullet lifesteal"] = { "BulletLifestealPercent", "ActiveBonusLifesteal" }
friendly_to_internal["bullet lifesteal"] = { "BulletLifestealPercent", "ActiveBonusLifesteal" }
friendly_to_internal["spirit lifesteal"] = { "AbilityLifestealPercentHero" }
friendly_to_internal["spirit lifesteal"] = { "AbilityLifestealPercentHero" }
friendly_to_internal["move speed"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "FervorMovespeed",}
friendly_to_internal["move speed"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed" }
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed", "InvisMoveSpeedMod" }
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed" }
friendly_to_internal["movement slow"] = { "SlowPercent", "MovementSpeedSlow", "MaxSlowPercent" }
friendly_to_internal["movement slow"] = { "SlowPercent", "MovementSpeedSlow" }
friendly_to_internal["reload time"] = { "ReloadSpeedMultipler" }
friendly_to_internal["reload time"] = { "ReloadSpeedMultipler" }
friendly_to_internal["heavy melee distance"] = { "MeleeDistanceScale" }
friendly_to_internal["heavy melee distance"] = { "MeleeDistanceScale" }
friendly_to_internal["bonus heavy damage"] = { "BonusHeavyMeleeDamage" }
friendly_to_internal["bonus heavy damage"] = { "BonusHeavyMeleeDamage" }
friendly_to_internal["bonus melee damage"] = { "BonusMeleeDamagePercent", "AmbushBonusMeleeDamage" }
friendly_to_internal["bonus melee damage"] = { "BonusMeleeDamagePercent" }
friendly_to_internal["melee resist"] = { "MeleeResistPercent" }
friendly_to_internal["melee resist"] = { "MeleeResistPercent" }
friendly_to_internal["stamina"] = { "Stamina" }
friendly_to_internal["stamina"] = { "Stamina" }
friendly_to_internal["slide distance"] = { "SlideScale" }
friendly_to_internal["slide distance"] = { "SlideScale" }
friendly_to_internal["stamina recovery"] = { "StaminaCooldownReduction" }
friendly_to_internal["stamina recovery"] = { "StaminaCooldownReduction" }
friendly_to_internal["healing reduction"] = { "HealAmpRegenPenaltyPercent" }
friendly_to_internal["healing reduction"] = { "HealAmpReceivePenaltyPercent" }
friendly_to_internal["ability duration"] = { "ImbuedBonusDuration", "BonusAbilityDurationPercent" }
friendly_to_internal["ability duration"] = { "ImbuedBonusDuration", "BonusAbilityDurationPercent" }
friendly_to_internal["ability cooldown reduction"] = { "ImbuedCooldownReduction", "CooldownReduction" }
friendly_to_internal["ability cooldown reduction"] = { "ImbuedCooldownReduction", "CooldownReduction" }
friendly_to_internal["item cooldown reduction"] = { "ItemCooldownReduction" }
friendly_to_internal["charge cooldown reduction"] = { "CooldownReductionOnChargedAbilities" }
friendly_to_internal["charge cooldown reduction"] = { "CooldownReductionOnChargedAbilities" }
friendly_to_internal["debuff resist"] = { "StatusResistancePercent", "FervorStatusResistancePercent" }
friendly_to_internal["debuff resist"] = { "StatusResistancePercent" }
friendly_to_internal["ability range"] = { "TechRangeMultiplier", "ImbuedTechRangeMultiplier"}
friendly_to_internal["ability range"] = { "TechRangeMultiplier", "ImbuedTechRangeMultiplier"}
friendly_to_internal["falloff range"] = { "BonusAttackRangePercent" }
friendly_to_internal["falloff range"] = { "BonusAttackRangePercent" }
friendly_to_internal["spirit amp"] = { "ShreddersTechAmp", "MagicIncreasePerStack" }
friendly_to_internal["spirit amp"] = { "ShreddersTechAmp", "MagicIncreasePerStack" }
friendly_to_internal["spirit damage reduction"] = { "TechDamageReduction" }
friendly_to_internal["spirit damage reduction"] = { "TechDamageReduction" }
friendly_to_internal["dash distance"] = { "GroundDashReductionPercent", "AirMoveIncreasePercent" }
friendly_to_internal["damage reduction"] = { "OutgoingDamagePenaltyPercent" }
friendly_to_internal["damage reduction"] = { "OutgoingDamagePenaltyPercent", "DeathImmunityDamageReduction" }
friendly_to_internal["gravity scale"] = { "GravityScale" }
 
-- Override dead/hidden stats that exist in data but don't actually work in‑game.
-- Keys are item Names, values are tables of { [internalStatName] = replacementValue }
local deadStatOverrides = {
    ["Witchmail"] = { CooldownReduction = "0" },
    ["Refresher"] = { BulletResist = "0", TechResist = "0" },
    ["Glass Cannon"] = { SlowPercent = "0", MovementSpeedSlow = "0" },
    ["Majestic Leap"] = { SlowPercent = "0", MovementSpeedSlow = "0" },
    ["Improved Spirit"] = { BonusSprintSpeed = "0"},
}
 
--- Copies original table with its children as deep as possible. Does not handle metatables. (Copy is needed because Lua passes by reference, not value)
-- @function  Deepcopy
-- @param      {n-D table}
-- @return    {n-D table}
function Deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[Deepcopy(orig_key)] = Deepcopy(orig_value)
        end
    else
        copy = orig
    end
    return copy
end
 
-- Helper to resolve a stat value, applying any dead‑stat override if defined.
local function resolveStatValue(itemName, t)
    if deadStatOverrides[itemName.Name] and deadStatOverrides[itemName.Name][t] ~= nil then
        return deadStatOverrides[itemName.Name][t]
    end
    return itemName[t]
end


-- Returns a table of internal properties  
-- Returns a table of internal properties  
Line 108: Line 109:
"BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded",
"BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded",
"TechResist", "BulletResist",
"TechResist", "BulletResist",
"BonusFireRate", "FireRateWhenShielded", "FervorFireRate", "FireRateBonus", "AmbushBonusFireRate", "ActiveBonusFireRate", "ActivatedFireRate", "FireRateSlow",
"BonusFireRate", "FireRateWhenShielded", "FervorFireRate", "FireRateBonus", "AmbushBonusFireRate", "ActiveBonusFireRate", "FireRateSlow",
"LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletArmorReduction", "BulletResistReduction", "BulletResistPerStack",
"LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletArmorReduction", "BulletResistReduction", "BulletResistPerStack",
"TechArmorDamageReduction", "MagicResistReduction",
"TechArmorDamageReduction", "MagicResistReduction",
Line 115: Line 116:
"HealLifePercentOutOfCombat",
"HealLifePercentOutOfCombat",
"ReloadSpeedMultipler",
"ReloadSpeedMultipler",
"MeleeDistanceScale", "BonusHeavyMeleeDamage", "BonusMeleeDamagePercent", "MeleeResistPercent", "AmbushBonusMeleeDamage",
"MeleeDistanceScale", "BonusHeavyMeleeDamage", "BonusMeleeDamagePercent", "MeleeResistPercent",
"SlideScale",
"SlideScale",
"StaminaCooldownReduction",
"StaminaCooldownReduction",
"SlowPercent", "MovementSpeedSlow", "MaxSlowPercent",
"SlowPercent", "MovementSpeedSlow",
"HealAmpReceivePenaltyPercent", "HealAmpRegenPenaltyPercent",
"HealAmpReceivePenaltyPercent",
"ImbuedBonusDuration", "NonImbuedBonusDuration", "BonusAbilityDurationPercent",
"ImbuedBonusDuration", "NonImbuedBonusDuration", "BonusAbilityDurationPercent",
"ImbuedCooldownReduction", "CooldownReduction",
"ImbuedCooldownReduction", "CooldownReduction",
"ItemCooldownReduction",
"CooldownReductionOnChargedAbilities",
"CooldownReductionOnChargedAbilities",
"StatusResistancePercent",
"StatusResistancePercent",
Line 129: Line 129:
"ShreddersTechAmp", "BonusAmpPerHeadshot", "MagicIncreasePerStack",
"ShreddersTechAmp", "BonusAmpPerHeadshot", "MagicIncreasePerStack",
"TechDamageReduction",
"TechDamageReduction",
"OutgoingDamagePenaltyPercent", "DeathImmunityDamageReduction", "TechPowerPercent",
"OutgoingDamagePenaltyPercent"
"GroundDashReductionPercent", "AirMoveIncreasePercent",
"GravityScale",
"BonusBaseHealth", "MaxHealthLossPercent"
     },
     },
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed", "FervorMovespeed", "InvisMoveSpeedMod" },
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed" },
[" HP"] = {"CombatBarrier", "GuardianWardCombatBarrier", "VexBarrierCombatBarrier"}
[" HP"] = {"CombatBarrier"}
}
}


Line 162: Line 159:
end
end


-- Formats a stat value with a leading + or - sign and makes it bold.
-- Formats the value of the stat with a + or -
-- The function is robust and handles nil, number, string, or table inputs safely.
-- @function  signPrefix
-- @function  signPrefix
-- @param      {any} The stat value to format.
-- @param      {string}
-- @return    {string} The formatted wikitext string.
-- @return    {string}
local function signPrefix(value)
local function signPrefix(value)
if value == nil then
local signString = ""
return ""
value = value:gsub( "m", "" )
end
value = tostring(value)
value = value:gsub("m", "")
value = tonumber(value)
value = tonumber(value)
if not value then
return ""
end
if (value >= 0) then
if (value >= 0) then
return "+<b>" .. value .. "</b>"
return "+<b>" .. value .. "</b>"
Line 192: Line 182:
local requirements = {}
local requirements = {}
local listofKeysTable = {}
local listofKeysTable = {}
local listofItems = ""
local property = frame:getParent().args[1] or mw.title.getCurrentTitle().text
local property = frame:getParent().args[1] or mw.title.getCurrentTitle().text
local copyVar = property
local copyVar = property
-- Get internal keys corresponding to the friendly property name
listofKeysTable = friendlyNames(property)  
listofKeysTable = friendlyNames(property)  
 
local filteredData = {}
local filteredData = GameData.get_entities(GameData.Dataset.ITEMS, listofKeysTable)
filteredData = get_similar_items_array(listofKeysTable)
table.sort(filteredData, defaultSort())
table.sort(filteredData, defaultSort())
 
local createTable = mw.html.create('table')
local createTable = mw.html.create('table')
    :addClass('wikitable sortable item-stat-table')
:addClass('wikitable sortable')
    :tag('caption'):done()
:tag('caption'):wikitext("List of items"):done()
 
local soulIcon = frame:expandTemplate{ title = 'Souls' }
local soulIcon = frame:expandTemplate{ title = 'Souls' }
 
local createTableHeader = mw.html.create('tr')
local createTableHeader = mw.html.create('tr')
createTableHeader
createTableHeader
Line 213: Line 202:
:tag('th'):wikitext('Category'):done()
:tag('th'):wikitext('Category'):done()
:tag('th'):wikitext('Stat change'):done()
:tag('th'):wikitext('Stat change'):done()
createTable:node(createTableHeader)
createTable:node(createTableHeader)
 
-- Track rowspans for items with multiple stats
-- query all the filtered items. itemName is the item table.
local rowspanTracker = {}
for internalName, itemName in ipairs(filteredData) do  
 
for _, itemName in ipairs(filteredData) do  
local display = frame:expandTemplate{
local display = frame:expandTemplate{
title = 'ItemIcon',
title = 'ItemIcon',
args = { itemName["Name"] }
args = {
itemName["Name"]
}
}
}
 
local statCount = 0
for k, t in pairs(listofKeysTable) do
for _, t in pairs(listofKeysTable) do
-- filter out items that: don't have the property and the value isn't zero
local statVal = resolveStatValue(itemName, t)
if(itemName[t] ~= nil and itemName[t] ~= "0" ) then
if(statVal ~= nil and statVal ~= "0") then
listofItems = listofItems .. itemName["Name"] .. "<br/>"
statCount = statCount + 1
end
end
if statCount == 0 then statCount = 1 end
rowspanTracker[itemName["Name"]] = statCount
 
local firstStat = true
for _, t in pairs(listofKeysTable) do
local statValue = resolveStatValue(itemName, t)
if(statValue ~= nil and statValue ~= "0") then
-- Handles complex stat values from the JSON data.
if type(statValue) == 'table' and statValue.Value ~= nil then
statValue = statValue.Value
end
 
copyVar = copyVar:gsub("^%l", string.upper)
copyVar = copyVar:gsub("^%l", string.upper)
 
-- Get category display using ItemType template with appropriate parameters
local categoryDisplay
local categoryDisplay
if itemName["Slot"] == "Armor" then
if itemName["Slot"] == "Armor" then
Line 256: Line 232:
args = { "Tech", "Spirit" }
args = { "Tech", "Spirit" }
}
}
else
else -- Weapon
categoryDisplay = frame:expandTemplate{
categoryDisplay = frame:expandTemplate{
title = 'ItemType',
title = 'ItemType',
Line 262: Line 238:
}
}
end
end
 
local tableData = mw.html.create('tr')
local tableData = mw.html.create('tr')
 
tableData
if firstStat then
:tag('td'):wikitext(display):done()
tableData
:tag('td'):wikitext(commas._add(get_cost(itemName["Name"]))):done()
:tag('td'):attr('rowspan', statCount):wikitext(display):done()
:tag('td'):wikitext(categoryDisplay):done()
:tag('td'):attr('rowspan', statCount):wikitext(
(get_cost(itemName["Name"]) == 9999)
if (t == "LocalBulletArmorReduction") then
and "Legendary"
tableData
or commas._add(get_cost(itemName["Name"]))
:tag('td'):wikitext("<span style=\"color:red;\">" .. signPrefix(itemName[t]) .. appendSuffix(t) .. "</span> " .. copyVar):done()
):done()
else
:tag('td'):attr('rowspan', statCount):wikitext(categoryDisplay):done()
tableData
firstStat = false
:tag('td'):wikitext(signPrefix(itemName[t]) .. appendSuffix(t) .. "</span> " .. copyVar):done()
end
end
 
tableData:tag('td'):wikitext(signPrefix(statValue) .. appendSuffix(t) .. " " .. copyVar):done()
table.insert(requirements, tableData)
table.insert(requirements, tableData)
end
end
end
end
end
for _, row in ipairs(requirements) do
createTable:node(row)
end
end
 
    for _, row in ipairs(requirements) do
return tostring(createTable)
        createTable:node(row)
    end
 
    local edit_url = mw.uri.fullUrl("Module:ItemTables", { action = "edit" })
    local disclaimer = frame:preprocess(
        '<div class="item-stat-table-disclaimer">'
        .. 'This is a dynamic list '
        .. '<span class="item-stat-table-list-name">"' .. property .. '"</span>. '
        .. '[' .. tostring(edit_url) .. ' Edit contents].'
        .. '</div>'
    )
 
    return disclaimer .. tostring(createTable)
end
end


return p
return p
Please note that all contributions to The Deadlock Wiki are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see Deadlock:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template

Page included on this page: