| 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["health"] = { "BonusHealth" } |
| | friendly_to_internal["health regen"] = { "BonusHealthRegen" } |
| | 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["stamina"] = { "Stamina" } |
| | friendly_to_internal["stamina recovery"] = { "StaminaCooldownReduction" } |
|
| |
|
| -- Returns a table of internal properties | | -- Returns a table of internal properties |
| Line 108: |
Line 93: |
| "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",
| |
| "BonusBulletSpeedPercent", | | "BonusBulletSpeedPercent", |
| "BulletLifestealPercent", "ActiveBonusLifesteal", "AbilityLifestealPercentHero",
| | "StaminaCooldownReduction" }, |
| "HealLifePercentOutOfCombat",
| | ["m/s"] = { "BonusMoveSpeed" } |
| "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"}
| |
| } | | } |
|
| |
|
| Line 162: |
Line 124: |
| 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 ""
| |
| end
| |
| value = tostring(value)
| |
| value = value:gsub("m", "")
| |
| value = tonumber(value) | | value = tonumber(value) |
| if not value then
| | if (value > 0) then |
| return ""
| |
| end
| |
| if (value >= 0) then | |
| return "+<b>" .. value .. "</b>" | | return "+<b>" .. value .. "</b>" |
| elseif (value < 0) then | | elseif (value < 0) then |
| Line 192: |
Line 146: |
| 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 166: |
| :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) |
| | --return 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 |