Editing Module:ItemTables

Jump to navigation Jump to search
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 get_cost = require("Module:ItemData")._get_cost
local data = mw.loadJsonData("Data:ItemData.json")
local get_type = require("Module:ItemData")._get_type
local commas = require("Module:Addcommas")
local GameData = require("Module:GameData")


-- Translate internal attribute names to plain text for module calls
-- returns the table of a specific item
local friendly_to_internal = {}
function get_json_item(name)
friendly_to_internal["ammo"] = { "BonusClipSizePercent", "BonusClipSize", "ActiveReloadPercent" }
for i,v in pairs(data) do
friendly_to_internal["weapon damage"] = { "BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded" }
if (v["Name"] == name) then
friendly_to_internal["spirit damage"] = { "ProcBonusMagicDamage" }
return v
friendly_to_internal["bullet shield health"] = { "BulletShieldMaxHealth", "BulletShieldOnCast", "SaviorBulletShieldHealth", "FlyingBulletShield", "VexBarrierBulletMaxHealth" }
end
friendly_to_internal["spirit shield health"] = { "TechShieldMaxHealth", "TechShieldOnCast", "SaviorMagicShieldHealth", "FlyingTechShield", "VexBarrierTechMaxHealth" }
end
friendly_to_internal["barrier"] = { "CombatBarrier", "GuardianWardCombatBarrier", "VexBarrierCombatBarrier" }
return nil
friendly_to_internal["bullet resist"] = { "BulletResist", "LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletResistPerStack" }
end
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["bonus base health"] = { "BonusBaseHealth", "MaxHealthLossPercent" }
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["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 }
-- Adds commas delimiter to the thousands place
local deadStatOverrides = {
function Format(amount)
     ["Witchmail"] = { CooldownReduction = "0" },
    local formatted = amount
    ["Refresher"] = { BulletResist = "0", TechResist = "0" },
     while true do
    ["Glass Cannon"] = { SlowPercent = "0", MovementSpeedSlow = "0" },
        formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
     ["Majestic Leap"] = { SlowPercent = "0", MovementSpeedSlow = "0" },
        if (k == 0) then
     ["Improved Spirit"] = { BonusSprintSpeed = "0"},
            break
}
        end
     end
     return formatted
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)
--- 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 43:
end
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
 
-- @function  friendlyNames
--{{#invoke:Sandbox/Sylphoid|get_prop|ITEM_NAME|PROPERTY}}--
-- @param      {string}
--check Data:ItemData.json for properties
-- @return    {table}
p.get_prop = function(frame)
local function friendlyNames(desc)
local item_name = frame.args[1]
local keysTable = {}
local property = frame.args[2]
desc = string.lower(desc or "")
local item = get_json_item(item_name)
for link, patterns in pairs(friendly_to_internal) do
if(item == nil) then return "Item Not Found" end
if (desc == link) then keysTable = patterns end  
end
return Deepcopy(item[property])
return keysTable
end
end


local unitSuffix = {
["%"] = { "BonusClipSizePercent", "ActiveReloadPercent",
"BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded",
"TechResist", "BulletResist",
"BonusFireRate", "FireRateWhenShielded", "FervorFireRate", "FireRateBonus", "AmbushBonusFireRate", "ActiveBonusFireRate", "ActivatedFireRate", "FireRateSlow",
"LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletArmorReduction", "BulletResistReduction", "BulletResistPerStack",
"TechArmorDamageReduction", "MagicResistReduction",
"BonusBulletSpeedPercent",
"BulletLifestealPercent", "ActiveBonusLifesteal", "AbilityLifestealPercentHero",
"HealLifePercentOutOfCombat",
"ReloadSpeedMultipler",
"MeleeDistanceScale", "BonusHeavyMeleeDamage", "BonusMeleeDamagePercent", "MeleeResistPercent", "AmbushBonusMeleeDamage",
"SlideScale",
"StaminaCooldownReduction",
"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"}
}


local function appendSuffix(internal)
--{{#invoke:ItemData|get_cost|ITEM_NAME}}--
local unitName = ""
p.get_cost = function(frame)
for key, s in pairs(unitSuffix) do
local item_name = frame.args[1]
for _, pattern in pairs(s) do
local item = get_json_item(item_name)
if (internal == pattern) then return key end
if(item == nil) then return "<span style=\"color:red;\">Item Not Found.</span>" end
local cost = 0
local cur_item = item
repeat
cost = cost + cur_item["Cost"]
if(cur_item["Components"] == nil) then
break
end
end
end
cur_item = data[cur_item["Components"][1]]
return unitName
until cur_item == nil
 
return Format(cost)
end
end


local sortByWeapon = {}
local link_patterns = {}
sortByWeapon["Weapon"] = 1
link_patterns["BonusClipSizePercent"] = { "[Aa]mmo" }
sortByWeapon["Armor"] = 10000
link_patterns["BulletLifestealPercent"] = { "[Bb]ullet [Ll]ifesteal" }
sortByWeapon["Tech"] = 100000000
link_patterns["BonusHealth"] = { "[Hh]ealth" }
link_patterns["BonusHealthRegen"] = { "[Hh]ealth [Rr]egen" }
link_patterns["BonusFireRate"] = { "[Ff]ire [Rr]ate" }


-- Sort the order of items in a preset as it appears when no filtered ordering is applied.
function FriendlyNames(desc)
-- Ordered first by slot and cost increasing, then alphabetical within same slot and cost.
for link, patterns in pairs(link_patterns) do
function defaultSort()
for i, v in ipairs(patterns) do
    return function(a, b)
    local a, b = desc:find(v)
    if (get_cost(a["Name"]) == get_cost(b["Name"]) and sortByWeapon[a["Slot"]] == sortByWeapon[b["Slot"]]) then return a["Name"] < b["Name"] end
if a then
        return get_cost(a["Name"]) * sortByWeapon[a["Slot"]] < get_cost(b["Name"]) * sortByWeapon[b["Slot"]]
        desc = link
    end
        break
end
    end
 
    end
-- Formats a stat value with a leading + or - sign and makes it bold.
-- The function is robust and handles nil, number, string, or table inputs safely.
-- @function  signPrefix
-- @param      {any} The stat value to format.
-- @return    {string} The formatted wikitext string.
local function signPrefix(value)
if value == nil then
return ""
end
value = tostring(value)
value = value:gsub("m", "")
value = tonumber(value)
if not value then
return ""
end
if (value >= 0) then
return "+<b>" .. value .. "</b>"
elseif (value < 0) then
value = math.abs(value)
return "-<b>" .. value .. "</b>"
end
end
return desc
end
end


-- Outputs a wikitable of items that increase a specified stat. Invoked by {{Item stat table}}
-- @function  p.itemPropTable
-- @param      {string}
-- @return    {string}
p.itemPropTable = function(frame)
p.itemPropTable = function(frame)
local TableValues = {}
local requirements = {}
local requirements = {}
local listofKeysTable = {}
local listofItems = ""
local property = frame:getParent().args[1] or mw.title.getCurrentTitle().text
local property = frame.args[1] or mw.title.getCurrentTitle().text
local copyVar = property
property = FriendlyNames(property)
 
-- local item = get_json_item(item_name)
-- Get internal keys corresponding to the friendly property name
-- if(item == nil) then return "Item Not Found what" end
listofKeysTable = friendlyNames(property)  
 
local filteredData = GameData.get_entities(GameData.Dataset.ITEMS, listofKeysTable)
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()
 
local createTableRow = mw.html.create('tr')
local soulIcon = frame:expandTemplate{ title = 'Souls' }
createTableRow
 
local createTableHeader = mw.html.create('tr')
createTableHeader
:tag('th'):wikitext('Name'):done()
:tag('th'):wikitext('Name'):done()
:tag('th'):wikitext(soulIcon .. 'Cost'):done()
:tag('th'):wikitext('Cost'):done()
:tag('th'):wikitext('Category'):done()
:tag('th'):wikitext('Stat change'):done()
createTable:node(createTableRow)
createTable:node(createTableHeader)


-- Track rowspans for items with multiple stats
local rowspanTracker = {}


for _, itemName in ipairs(filteredData) do  
for internalName, statName in pairs(data) do --statName is the key. go through whole table. in this case itemName can be upgrade_improved_stamina
local display = frame:expandTemplate{
local display = frame:expandTemplate{
title = 'ItemIcon',
title = 'ItemIcon',
args = { itemName["Name"] }
args = {
statName["Name"]
}
}
}
 
local statCount = 0
if(statName[property] ~= nil and statName["Name"] ~= nil) then
for _, t in pairs(listofKeysTable) do
listofItems = listofItems .. statName["Name"] .. "<br/>"
local statVal = resolveStatValue(itemName, t)
if(statVal ~= nil and statVal ~= "0") then
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)
 
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()
tableData
:tag('td'):wikitext(statName["Cost"]):done()
:tag('td'):attr('rowspan', statCount):wikitext(display):done()
:tag('td'):attr('rowspan', statCount):wikitext(
(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)
-- TableValues = table.insert(TableValues, statName["Name"]) -- i may want to make a table first, so it includes weapon and cost to make it sortable.
end
end
end
end
for _, row in ipairs(requirements) do
createTableRow:node(row)
end
end
--createTable:node(createTableRow)
return tostring(createTable)
--return listofItems -- this is just a string list, same thing as createTable. delete this when line when finished
--return table.concat(TableValues, ", ")


    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: