Module:ItemTables: Difference between revisions
Jump to navigation
Jump to search
add combat barrier to weapon damage |
m ...also add % suffix to Spirit Lifesteal |
||
(40 intermediate revisions by 2 users not shown) | |||
Line 4: | Line 4: | ||
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") | ||
-- Returns an array of item tables that have the same properties | -- Returns an array of item tables that have the same properties | ||
Line 25: | Line 11: | ||
local function get_similar_items_array(property) | local function get_similar_items_array(property) | ||
local similarItems = {} | local similarItems = {} | ||
local hash = {} | |||
local noDuplicates = {} | |||
for _, v in pairs(data) do | for _, v in pairs(data) do | ||
for _, value in ipairs(property) do | for _, value in ipairs(property) do | ||
if (v[value] ~= nil and v["Disabled"] == false and v["Name"] ~= nil and v[value] ~= "0" ) then | if (v[value] ~= nil and v["Disabled"] == false and v["Name"] ~= nil and v[value] ~= "0" and v[value] ~= "0m") then | ||
table.insert(similarItems, v) | table.insert(similarItems, v) | ||
end | end | ||
end | end | ||
end | end | ||
return | |||
-- 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 | end | ||
Line 52: | Line 49: | ||
return copy | return copy | ||
end | end | ||
-- local link_patterns = {} | -- local link_patterns = {} | ||
Line 77: | Line 73: | ||
friendly_to_internal["ammo"] = { "BonusClipSizePercent", "BonusClipSize", "ActiveReloadPercent" } | friendly_to_internal["ammo"] = { "BonusClipSizePercent", "BonusClipSize", "ActiveReloadPercent" } | ||
friendly_to_internal["weapon damage"] = { "BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded" } | friendly_to_internal["weapon damage"] = { "BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded" } | ||
friendly_to_internal["bullet shield health"] = { "BulletShieldMaxHealth", "BulletShieldOnCast", "SaviorBulletShieldHealth", "FlyingBulletShield" } | friendly_to_internal["spirit damage"] = { "ProcBonusMagicDamage" } | ||
friendly_to_internal["spirit shield health"] = { "TechShieldMaxHealth", "TechShieldOnCast", "SaviorMagicShieldHealth", "FlyingTechShield" } | 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"] = { "TechResist" } | ||
friendly_to_internal[" | friendly_to_internal["spirit resist reduction"] = { "TechArmorDamageReduction", "MagicResistReduction" } | ||
friendly_to_internal["health"] = { "BonusHealth" } | friendly_to_internal["bonus health"] = { "BonusHealth" } | ||
friendly_to_internal["health regen"] = { "BonusHealthRegen" } | friendly_to_internal["health regen"] = { "BonusHealthRegen" } | ||
friendly_to_internal["fire rate"] = { "BonusFireRate" } | 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["spirit lifesteal"] = { "AbilityLifestealPercentHero" } | |||
friendly_to_internal["move speed"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed" } | |||
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed" } | |||
friendly_to_internal["movement slow"] = { "SlowPercent", "MovementSpeedSlow" } | |||
friendly_to_internal["reload time"] = { "ReloadSpeedMultipler" } | |||
friendly_to_internal["heavy melee distance"] = { "MeleeDistanceScale" } | |||
friendly_to_internal["bonus heavy damage"] = { "BonusHeavyMeleeDamage" } | |||
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["stamina recovery"] = { "StaminaCooldownReduction" } | friendly_to_internal["stamina recovery"] = { "StaminaCooldownReduction" } | ||
friendly_to_internal["healing reduction"] = { "HealAmpRegenPenaltyPercent" } | |||
-- Returns a table of internal properties | -- Returns a table of internal properties | ||
Line 103: | Line 117: | ||
["%"] = { "BonusClipSizePercent", "ActiveReloadPercent", | ["%"] = { "BonusClipSizePercent", "ActiveReloadPercent", | ||
"BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded", | "BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded", | ||
"TechResist", "BulletResist", | |||
["m/s"] = { "BonusMoveSpeed" } | "BonusFireRate", "FireRateWhenShielded", "FervorFireRate", "FireRateBonus", "AmbushBonusFireRate", "ActiveBonusFireRate", "FireRateSlow", | ||
"LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletArmorReduction", "BulletResistReduction", "BulletResistPerStack", | |||
"TechArmorDamageReduction", "MagicResistReduction", | |||
"BonusBulletSpeedPercent", | |||
"BulletLifestealPercent", "ActiveBonusLifesteal", "AbilityLifestealPercentHero", | |||
"HealLifePercentOutOfCombat", | |||
"ReloadSpeedMultipler", | |||
"MeleeDistanceScale", "BonusHeavyMeleeDamage", "MeleeResistPercent", | |||
"SlideScale", | |||
"StaminaCooldownReduction", | |||
"SlowPercent", "MovementSpeedSlow", | |||
"HealAmpRegenPenaltyPercent" }, | |||
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed" } | |||
} | } | ||
Line 129: | Line 155: | ||
return get_cost(a["Name"]) * sortByWeapon[a["Slot"]] < get_cost(b["Name"]) * sortByWeapon[b["Slot"]] | return get_cost(a["Name"]) * sortByWeapon[a["Slot"]] < get_cost(b["Name"]) * sortByWeapon[b["Slot"]] | ||
end | end | ||
end | |||
-- Formats the value of the stat with a + or - | |||
-- @function signPrefix | |||
-- @param {string} | |||
-- @return {string} | |||
local function signPrefix(value) | |||
local signString = "" | |||
value = value:gsub( "m", "" ) | |||
value = tonumber(value) | |||
if (value >= 0) then | |||
return "+<b>" .. value .. "</b>" | |||
elseif (value < 0) then | |||
value = math.abs(value) | |||
return "-<b>" .. value .. "</b>" | |||
end | |||
end | end | ||
Line 136: | Line 178: | ||
-- @return {string} | -- @return {string} | ||
p.itemPropTable = function(frame) | p.itemPropTable = function(frame) | ||
local requirements = {} | local requirements = {} | ||
local listofKeysTable = {} | local listofKeysTable = {} | ||
Line 149: | Line 190: | ||
local createTable = mw.html.create('table') | local createTable = mw.html.create('table') | ||
:addClass('wikitable sortable') | :addClass('wikitable sortable') | ||
:tag('caption'):wikitext("List of | :tag('caption'):wikitext("List of items"):done() | ||
local soulIcon = frame:expandTemplate{ title = 'Souls' } | |||
local createTableHeader = mw.html.create('tr') | local createTableHeader = mw.html.create('tr') | ||
createTableHeader | createTableHeader | ||
:tag('th'):wikitext('Name'):done() | :tag('th'):wikitext('Name'):done() | ||
:tag('th'):wikitext('Cost'):done() | :tag('th'):wikitext(soulIcon .. 'Cost'):done() | ||
:tag('th'):wikitext('Category'):done() | :tag('th'):wikitext('Category'):done() | ||
:tag('th'):wikitext('Stat change'):done() | :tag('th'):wikitext('Stat change'):done() | ||
Line 160: | Line 203: | ||
createTable:node(createTableHeader) | createTable:node(createTableHeader) | ||
-- query the filtered items | -- query all the filtered items. itemName is the item table. | ||
for internalName, itemName in ipairs(filteredData) do | for internalName, itemName in ipairs(filteredData) do | ||
local display = frame:expandTemplate{ | local display = frame:expandTemplate{ | ||
Line 181: | Line 224: | ||
:tag('td'):wikitext(commas._add(get_cost(itemName["Name"]))):done() | :tag('td'):wikitext(commas._add(get_cost(itemName["Name"]))):done() | ||
:tag('td'):wikitext(get_type(itemName["Name"])):done() | :tag('td'):wikitext(get_type(itemName["Name"])):done() | ||
:tag('td'):wikitext(" | |||
if (t == "LocalBulletArmorReduction") then | |||
tableData | |||
:tag('td'):wikitext("<span style=\"color:red;\">" .. signPrefix(itemName[t]) .. appendSuffix(t) .. "</span> " .. copyVar):done() | |||
else | |||
tableData | |||
:tag('td'):wikitext(signPrefix(itemName[t]) .. appendSuffix(t) .. "</span> " .. copyVar):done() | |||
end | |||
table.insert(requirements, tableData) | table.insert(requirements, tableData) | ||
end | end | ||
end | end | ||
Line 193: | Line 242: | ||
end | end | ||
return tostring(createTable) | return tostring(createTable) --, listofItems -- this is just a string list, same thing as createTable. delete this when line when finished | ||
end | end | ||
return p | return p |
Latest revision as of 20:49, 12 November 2024
Documentation for this module may be created at Module:ItemTables/doc
local p = {};
local data = mw.loadJsonData("Data:ItemData.json")
local get_cost = require("Module:ItemData")._get_cost
local get_type = require("Module:ItemData")._get_type
local commas = require("Module:Addcommas")
-- 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["Disabled"] == false and v["Name"] ~= nil and v[value] ~= "0" and v[value] ~= "0m") 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 link_patterns = {}
-- link_patterns["BonusClipSizePercent"] = { "[Aa]mmo" }
-- link_patterns["CloseRangeBonusWeaponPower"] = { "[Cc]lose [Ww]eapon [Dd]amage" }
-- link_patterns["BaseAttackDamagePercent"] = { "[Ww]eapon [Dd]amage" }
-- link_patterns["BulletLifestealPercent"] = { "[Bb]ullet [Ll]ifesteal" }
-- link_patterns["BonusHealthRegen"] = { "[Hh]ealth [Rr]egen" }
-- 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["spirit damage"] = { "ProcBonusMagicDamage" }
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["spirit lifesteal"] = { "AbilityLifestealPercentHero" }
friendly_to_internal["move speed"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed" }
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed" }
friendly_to_internal["movement slow"] = { "SlowPercent", "MovementSpeedSlow" }
friendly_to_internal["reload time"] = { "ReloadSpeedMultipler" }
friendly_to_internal["heavy melee distance"] = { "MeleeDistanceScale" }
friendly_to_internal["bonus heavy damage"] = { "BonusHeavyMeleeDamage" }
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" }
-- Returns a table of internal properties
-- @function friendlyNames
-- @param {string}
-- @return {table}
local function friendlyNames(desc)
local keysTable = {}
desc = string.lower(desc or "")
for link, patterns in pairs(friendly_to_internal) do
if (desc == link) then keysTable = patterns end
end
return keysTable
end
local unitSuffix = {
["%"] = { "BonusClipSizePercent", "ActiveReloadPercent",
"BaseAttackDamagePercent", "CloseRangeBonusWeaponPower", "LongRangeBonusWeaponPower", "AttackDamageWhenShielded",
"TechResist", "BulletResist",
"BonusFireRate", "FireRateWhenShielded", "FervorFireRate", "FireRateBonus", "AmbushBonusFireRate", "ActiveBonusFireRate", "FireRateSlow",
"LocalBulletArmorReduction", "ReturnFireBulletResist", "BulletArmorReduction", "BulletResistReduction", "BulletResistPerStack",
"TechArmorDamageReduction", "MagicResistReduction",
"BonusBulletSpeedPercent",
"BulletLifestealPercent", "ActiveBonusLifesteal", "AbilityLifestealPercentHero",
"HealLifePercentOutOfCombat",
"ReloadSpeedMultipler",
"MeleeDistanceScale", "BonusHeavyMeleeDamage", "MeleeResistPercent",
"SlideScale",
"StaminaCooldownReduction",
"SlowPercent", "MovementSpeedSlow",
"HealAmpRegenPenaltyPercent" },
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed" }
}
local function appendSuffix(internal)
local unitName = ""
for key, s in pairs(unitSuffix) do
for _, pattern in pairs(s) do
if (internal == pattern) then return key end
end
end
return unitName
end
local sortByWeapon = {}
sortByWeapon["Weapon"] = 1
sortByWeapon["Armor"] = 10000
sortByWeapon["Tech"] = 100000000
-- Sort the order of items in a preset as it appears when no filtered ordering is applied.
-- Ordered first by slot and cost increasing, then alphabetical within same slot and cost.
function defaultSort()
return function(a, b)
if (get_cost(a["Name"]) == get_cost(b["Name"]) and sortByWeapon[a["Slot"]] == sortByWeapon[b["Slot"]]) then return a["Name"] < b["Name"] end
return get_cost(a["Name"]) * sortByWeapon[a["Slot"]] < get_cost(b["Name"]) * sortByWeapon[b["Slot"]]
end
end
-- Formats the value of the stat with a + or -
-- @function signPrefix
-- @param {string}
-- @return {string}
local function signPrefix(value)
local signString = ""
value = value:gsub( "m", "" )
value = tonumber(value)
if (value >= 0) then
return "+<b>" .. value .. "</b>"
elseif (value < 0) then
value = math.abs(value)
return "-<b>" .. value .. "</b>"
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)
local requirements = {}
local listofKeysTable = {}
local listofItems = ""
local property = frame:getParent().args[1] or mw.title.getCurrentTitle().text
local copyVar = property
listofKeysTable = friendlyNames(property)
local filteredData = {}
filteredData = get_similar_items_array(listofKeysTable)
table.sort(filteredData, defaultSort())
local createTable = mw.html.create('table')
:addClass('wikitable sortable')
:tag('caption'):wikitext("List of items"):done()
local soulIcon = frame:expandTemplate{ title = 'Souls' }
local createTableHeader = mw.html.create('tr')
createTableHeader
:tag('th'):wikitext('Name'):done()
:tag('th'):wikitext(soulIcon .. 'Cost'):done()
:tag('th'):wikitext('Category'):done()
:tag('th'):wikitext('Stat change'):done()
createTable:node(createTableHeader)
-- query all the filtered items. itemName is the item table.
for internalName, itemName in ipairs(filteredData) do
local display = frame:expandTemplate{
title = 'ItemIcon',
args = {
itemName["Name"]
}
}
for k, t in pairs(listofKeysTable) do
-- filter out items that: don't have the property and the value isn't zero
if(itemName[t] ~= nil and itemName[t] ~= "0" ) then
listofItems = listofItems .. itemName["Name"] .. "<br/>"
copyVar = copyVar:gsub("^%l", string.upper)
local tableData = mw.html.create('tr')
tableData
: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
:tag('td'):wikitext(signPrefix(itemName[t]) .. appendSuffix(t) .. "</span> " .. copyVar):done()
end
table.insert(requirements, tableData)
end
end
end
for _, row in ipairs(requirements) do
createTableHeader:node(row)
end
return tostring(createTable) --, listofItems -- this is just a string list, same thing as createTable. delete this when line when finished
end
return p