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
local friendly_to_internal = {}
-- @function  get_similar_items_array
friendly_to_internal["ammo"] = { "BonusClipSizePercent", "BonusClipSize", "ActiveReloadPercent" }
-- @param      {array}
friendly_to_internal["weapon damage"] = { "BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded" }
-- @return    {array of tables}
friendly_to_internal["spirit damage"] = { "ProcBonusMagicDamage" }
local function get_similar_items_array(property)
friendly_to_internal["bullet shield health"] = { "BulletShieldMaxHealth", "BulletShieldOnCast", "SaviorBulletShieldHealth", "FlyingBulletShield", "VexBarrierBulletMaxHealth" }
local similarItems = {}
friendly_to_internal["spirit shield health"] = { "TechShieldMaxHealth", "TechShieldOnCast", "SaviorMagicShieldHealth", "FlyingTechShield", "VexBarrierTechMaxHealth" }
for _, v in pairs(data) do
friendly_to_internal["barrier"] = { "CombatBarrier", "GuardianWardCombatBarrier", "VexBarrierCombatBarrier" }
for _, value in ipairs(property) do
friendly_to_internal["bullet resist"] = { "BulletResist", "LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletResistPerStack" }
if (v[value] ~= nil and v["Disabled"] == false and v["Name"] ~= nil and v[value] ~= "0" ) then
friendly_to_internal["bullet resist reduction"] = { "BulletArmorReduction", "BulletResistReduction" }
table.insert(similarItems, v)
friendly_to_internal["spirit resist"] = { "TechResist" }
end
friendly_to_internal["spirit resist reduction"] = { "TechArmorDamageReduction", "MagicResistReduction" }
end
friendly_to_internal["bonus health"] = { "BonusHealth" }
end
friendly_to_internal["bonus base health"] = { "BonusBaseHealth", "MaxHealthLossPercent" }
return similarItems
friendly_to_internal["health regen"] = { "BonusHealthRegen" }
end
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["fire rate"] = { "BonusFireRate", "FireRateWhenShielded", "FireRateBonus", "FervorFireRate", "AmbushBonusFireRate", "ActiveBonusFireRate", "ActivatedFireRate" }
friendly_to_internal["fire rate slow"] = { "FireRateSlow" }
friendly_to_internal["bullet velocity"] = { "BonusBulletSpeedPercent" }
friendly_to_internal["spirit power"] = { "TechPower", "BonusSpirit", "SpiritPower", "BonusSpiritWithMagicShield", "ImbuedTechPower", "AmbushBonusTechPower", "TechPowerPercent" }
friendly_to_internal["bullet lifesteal"] = { "BulletLifestealPercent", "ActiveBonusLifesteal" }
friendly_to_internal["spirit lifesteal"] = { "AbilityLifestealPercentHero" }
friendly_to_internal["move speed"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "FervorMovespeed",}
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed", "InvisMoveSpeedMod" }
friendly_to_internal["movement slow"] = { "SlowPercent", "MovementSpeedSlow", "MaxSlowPercent" }
friendly_to_internal["reload time"] = { "ReloadSpeedMultipler" }
friendly_to_internal["heavy melee distance"] = { "MeleeDistanceScale" }
friendly_to_internal["bonus heavy damage"] = { "BonusHeavyMeleeDamage" }
friendly_to_internal["bonus melee damage"] = { "BonusMeleeDamagePercent", "AmbushBonusMeleeDamage" }
friendly_to_internal["melee resist"] = { "MeleeResistPercent" }
friendly_to_internal["stamina"] = { "Stamina" }
friendly_to_internal["slide distance"] = { "SlideScale" }
friendly_to_internal["stamina recovery"] = { "StaminaCooldownReduction" }
friendly_to_internal["healing reduction"] = { "HealAmpRegenPenaltyPercent" }
friendly_to_internal["ability duration"] = { "ImbuedBonusDuration", "BonusAbilityDurationPercent" }
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["debuff resist"] = { "StatusResistancePercent", "FervorStatusResistancePercent" }
friendly_to_internal["ability range"] = { "TechRangeMultiplier", "ImbuedTechRangeMultiplier"}
friendly_to_internal["falloff range"] = { "BonusAttackRangePercent" }
friendly_to_internal["spirit amp"] = { "ShreddersTechAmp", "MagicIncreasePerStack" }
friendly_to_internal["spirit damage reduction"] = { "TechDamageReduction" }
friendly_to_internal["dash distance"] = { "GroundDashReductionPercent", "AirMoveIncreasePercent" }
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)
--- Copies original table with its children as deep as possible. Does not handle metatables. (Copy is needed because Lua passes by reference, not value)
Line 83: Line 39:
end
end


-- Helper to resolve a stat value, applying any dead‑stat override if defined.
-- local link_patterns = {}
local function resolveStatValue(itemName, t)
-- link_patterns["BonusClipSizePercent"] = { "[Aa]mmo" }
    if deadStatOverrides[itemName.Name] and deadStatOverrides[itemName.Name][t] ~= nil then
-- link_patterns["CloseRangeBonusWeaponPower"] = { "[Cc]lose [Ww]eapon [Dd]amage" }
        return deadStatOverrides[itemName.Name][t]
-- link_patterns["BaseAttackDamagePercent"] = { "[Ww]eapon [Dd]amage" }
    end
-- link_patterns["BulletLifestealPercent"] = { "[Bb]ullet [Ll]ifesteal" }
    return itemName[t]
-- link_patterns["BonusHealthRegen"] = { "[Hh]ealth [Rr]egen" }
end
-- link_patterns["BonusHealth"] = { "[Hh]ealth" }
-- link_patterns["BonusFireRate"] = { "[Ff]ire [Rr]ate" }
--
-- function FriendlyNames(desc)
-- for link, patterns in pairs(link_patterns) do
-- for i, v in ipairs(patterns) do
--     local a = string.find(desc, v)
-- if a then desc = link break
--     end
--     end
-- end
-- return desc
-- end
 
local friendly_to_internal = {}
friendly_to_internal["ammo"] = { "BonusClipSizePercent", "BonusClipSize", "ActiveReloadPercent" }
friendly_to_internal["weapon damage"] = { "BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded" }
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["bullet resist"] = { "BulletResist", "LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletResistPerStack" }
friendly_to_internal["bullet resist reduction"] = { "BulletArmorReduction", "BulletResistReduction" }
friendly_to_internal["spirit resist"] = { "TechResist" }
friendly_to_internal["spirit resist reduction"] = { "TechArmorDamageReduction", "MagicResistReduction" }
friendly_to_internal["bonus health"] = { "BonusHealth" }
friendly_to_internal["health regen"] = { "BonusHealthRegen" }
friendly_to_internal["max health regen"] = { "HealLifePercentOutOfCombat" }
friendly_to_internal["fire rate"] = { "BonusFireRate", "FireRateWhenShielded", "FireRateBonus", "FervorFireRate", "AmbushBonusFireRate", "ActiveBonusFireRate" }
friendly_to_internal["fire rate slow"] = { "FireRateSlow" }
friendly_to_internal["bullet velocity"] = { "BonusBulletSpeedPercent" }
friendly_to_internal["spirit power"] = { "TechPower", "BonusSpirit", "SpiritPower", "BonusSpiritWithMagicShield", "ImbuedTechPower", "AmbushBonusTechPower" }
friendly_to_internal["bullet lifesteal"] = { "BulletLifestealPercent", "ActiveBonusLifesteal" }
friendly_to_internal["move speed"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed" }
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed" }
friendly_to_internal["reload time"] = { "ReloadSpeedMultipler" }
friendly_to_internal["heavy melee distance"] = { "BonusHeavyMeleeDamage" }
friendly_to_internal["stamina"] = { "Stamina" }
friendly_to_internal["stamina recovery"] = { "StaminaCooldownReduction" }


-- Returns a table of internal properties  
-- Returns a table of internal properties  
Line 108: Line 100:
"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",
"BonusBulletSpeedPercent",
"BonusBulletSpeedPercent",
"BulletLifestealPercent", "ActiveBonusLifesteal", "AbilityLifestealPercentHero",
"BulletLifestealPercent", "ActiveBonusLifesteal",
"HealLifePercentOutOfCombat",
"HealLifePercentOutOfCombat",
"ReloadSpeedMultipler",
"ReloadSpeedMultipler",
"MeleeDistanceScale", "BonusHeavyMeleeDamage", "BonusMeleeDamagePercent", "MeleeResistPercent", "AmbushBonusMeleeDamage",
"BonusHeavyMeleeDamage",
"SlideScale",
"StaminaCooldownReduction" },
"StaminaCooldownReduction",
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed" }
"SlowPercent", "MovementSpeedSlow", "MaxSlowPercent",
"HealAmpReceivePenaltyPercent", "HealAmpRegenPenaltyPercent",
"ImbuedBonusDuration", "NonImbuedBonusDuration", "BonusAbilityDurationPercent",
"ImbuedCooldownReduction", "CooldownReduction",
"ItemCooldownReduction",
"CooldownReductionOnChargedAbilities",
"StatusResistancePercent",
"TechRangeMultiplier", "ImbuedTechRangeMultiplier",
"BonusAttackRangePercent",
"ShreddersTechAmp", "BonusAmpPerHeadshot", "MagicIncreasePerStack",
"TechDamageReduction",
"OutgoingDamagePenaltyPercent", "DeathImmunityDamageReduction", "TechPowerPercent",
"GroundDashReductionPercent", "AirMoveIncreasePercent",
"GravityScale",
"BonusBaseHealth", "MaxHealthLossPercent"
    },
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed", "FervorMovespeed", "InvisMoveSpeedMod" },
[" HP"] = {"CombatBarrier", "GuardianWardCombatBarrier", "VexBarrierCombatBarrier"}
}
}


Line 162: Line 136:
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 159:
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 179:
: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)
-- query all the filtered items. itemName is the item table.
for internalName, itemName in ipairs(filteredData) do


-- Track rowspans for items with multiple stats
local rowspanTracker = {}
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)
 
local categoryDisplay
if itemName["Slot"] == "Armor" then
categoryDisplay = frame:expandTemplate{
title = 'ItemType',
args = { "Armor", "Vitality" }
}
elseif itemName["Slot"] == "Tech" then
categoryDisplay = frame:expandTemplate{
title = 'ItemType',
args = { "Tech", "Spirit" }
}
else
categoryDisplay = frame:expandTemplate{
title = 'ItemType',
args = { "Weapon", "Weapon" }
}
end
 
local tableData = mw.html.create('tr')
local tableData = mw.html.create('tr')
 
tableData
if firstStat then
:tag('td'):wikitext(display):done()
:tag('td'):wikitext(commas._add(get_cost(itemName["Name"]))):done()
:tag('td'):wikitext(get_type(itemName["Name"])):done()
if (t == "LocalBulletArmorReduction") then  
tableData
:tag('td'):wikitext("<span style=\"color:red;\">" .. signPrefix(itemName[t]) .. appendSuffix(t) .. "</span> " .. copyVar):done()
else
tableData
tableData
:tag('td'):attr('rowspan', statCount):wikitext(display):done()
:tag('td'):wikitext(signPrefix(itemName[t]) .. appendSuffix(t) .. "</span> " .. copyVar):done()
:tag('td'):attr('rowspan', statCount):wikitext(
end
(get_cost(itemName["Name"]) == 9999)
and "Legendary"
or commas._add(get_cost(itemName["Name"]))
):done()
:tag('td'):attr('rowspan', statCount):wikitext(categoryDisplay):done()
firstStat = false
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
createTableHeader:node(row)
end
end
return tostring(createTable) --, listofItems -- this is just a string list, same thing as createTable. delete this when line when finished


    for _, row in ipairs(requirements) do
        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: