Module:ItemTables: Difference between revisions

No edit summary
Instead of removing duplicates, keep all stats and use rowspan to merge the item info across multiple rows. Added FervorMovespeed to move speed
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
-- @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)
--- 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 73: Line 46:
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" }
friendly_to_internal["move speed"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "FervorMovespeed"}
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed" }
friendly_to_internal["sprint speed"] = { "BonusSprintSpeed" }
friendly_to_internal["movement slow"] = { "SlowPercent", "MovementSpeedSlow" }
friendly_to_internal["movement slow"] = { "SlowPercent", "MovementSpeedSlow" }
Line 138: Line 111:
"GroundDashReductionPercent"
"GroundDashReductionPercent"
     },
     },
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed" },
["m/s"] = { "BonusMoveSpeed", "ActiveBonusMoveSpeed", "BonusSprintSpeed", "FervorMovespeed"},
[" HP"] = {"CombatBarrier", "GuardianWardCombatBarrier", "VexBarrierCombatBarrier"}
[" HP"] = {"CombatBarrier", "GuardianWardCombatBarrier", "VexBarrierCombatBarrier"}
}
}
Line 172: Line 145:
-- @return    {string} The formatted wikitext string.
-- @return    {string} The formatted wikitext string.
local function signPrefix(value)
local function signPrefix(value)
-- Returns an empty string if the input is nil to prevent errors.
if value == nil then
if value == nil then
return ""
return ""
end
end
-- Converts the input to a string to safely use string methods. This allows
-- the function to handle numbers from JSON (e.g., 10) that are not strings.
value = tostring(value)
value = tostring(value)
-- Removes the 'm' suffix if it exists (e.g., from range values like "7m").
value = value:gsub("m", "")
value = value:gsub("m", "")
-- Convert the cleaned string into a number for comparison.
value = tonumber(value)
value = tonumber(value)
-- Returns an empty string if the value cannot be converted to a number,
-- which prevents errors and malformed output.
if not value then
if not value then
return ""
return ""
end
end
if (value >= 0) then
if (value >= 0) then
return "+<b>" .. value .. "</b>"
return "+<b>" .. value .. "</b>"
Line 207: Line 169:
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 = {}
filteredData = get_similar_items_array(listofKeysTable)
for _, v in pairs(data) do
for _, t in ipairs(listofKeysTable) do
if v[t] ~= nil and v["IsDisabled"] == false and v["Name"] ~= nil and v[t] ~= "0" and v[t] ~= "0m" and v[t] ~= "" then
table.insert(filteredData, v)
break
end
end
end
 
table.sort(filteredData, defaultSort())
table.sort(filteredData, defaultSort())
 
local createTable = mw.html.create('table')
local createTable = mw.html.create('table')
:addClass('wikitable sortable')
:addClass('wikitable sortable')
:tag('caption'):wikitext("List of items"):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 227: Line 199:
: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.
-- Track rowspans for items with multiple stats
for internalName, itemName in ipairs(filteredData) do  
local rowspanTracker = {}
local display = frame:expandTemplate{
 
title = 'ItemIcon',
for _, itemName in ipairs(filteredData) do  
args = {
local display = frame:expandTemplate{
itemName["Name"]
title = 'ItemIcon',
}
args = { itemName["Name"] }
}
}
 
for k, t in pairs(listofKeysTable) do
local statCount = 0
-- filter out items that: don't have the property and the value isn't zero
for _, t in pairs(listofKeysTable) do
if(itemName[t] ~= nil and itemName[t] ~= "0" ) then
if(itemName[t] ~= nil and itemName[t] ~= "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
if(itemName[t] ~= nil and itemName[t] ~= "0") then
-- Handles complex stat values from the JSON data.
-- Handles complex stat values from the JSON data.
-- A stat can be a simple value (e.g., "BonusMoveSpeed": "1") or a table containing
-- A stat can be a simple value (e.g., "BonusMoveSpeed": "1") or a table containing
-- scaling info (e.g., "BonusFireRate": { "Value": 10, "Scale": ... }).
-- scaling info (e.g., "BonusFireRate": { "Value": 10, "Scale": ... }).
-- This code checks if the stat is a table and extracts the base numerical value from its 'Value' key.
-- This code checks if the stat is a table and extracts the base numerical value from its 'Value' key.
local statValue = itemName[t]
local statValue = itemName[t]
if type(statValue) == 'table' and statValue.Value ~= nil then
if type(statValue) == 'table' and statValue.Value ~= nil then
statValue = statValue.Value
statValue = statValue.Value
end
end
 
listofItems = listofItems .. itemName["Name"] .. "<br/>"
copyVar = copyVar:gsub("^%l", string.upper)
copyVar = copyVar:gsub("^%l", string.upper)
 
local categoryDisplay
-- Get category display using ItemType template with appropriate parameters
if itemName["Slot"] == "Armor" then
local categoryDisplay
categoryDisplay = frame:expandTemplate{
if itemName["Slot"] == "Armor" then
title = 'ItemType',
categoryDisplay = frame:expandTemplate{
args = { "Armor", "Vitality" }
title = 'ItemType',
}
args = { "Armor", "Vitality" }
elseif itemName["Slot"] == "Tech" then
}
categoryDisplay = frame:expandTemplate{
elseif itemName["Slot"] == "Tech" then
title = 'ItemType',
categoryDisplay = frame:expandTemplate{
args = { "Tech", "Spirit" }
title = 'ItemType',
}
args = { "Tech", "Spirit" }
else
}
categoryDisplay = frame:expandTemplate{
else -- Weapon
title = 'ItemType',
categoryDisplay = frame:expandTemplate{
args = { "Weapon", "Weapon" }
title = 'ItemType',
}
args = { "Weapon", "Weapon" }
end
}
 
end
local tableData = mw.html.create('tr')
 
local tableData = mw.html.create('tr')
if firstStat then
tableData
tableData
:tag('td'):wikitext(display):done()
:tag('td'):attr('rowspan', statCount):wikitext(display):done()
:tag('td'):wikitext(commas._add(get_cost(itemName["Name"]))):done()
:tag('td'):attr('rowspan', statCount):wikitext(commas._add(get_cost(itemName["Name"]))):done()
:tag('td'):wikitext(categoryDisplay):done()
:tag('td'):attr('rowspan', statCount):wikitext(categoryDisplay):done()
-- Construct the stat change string.
firstStat = false
:tag('td'):wikitext(signPrefix(statValue) .. appendSuffix(t) .. " " .. copyVar):done()
table.insert(requirements, tableData)
end
end
tableData:tag('td'):wikitext(signPrefix(statValue) .. appendSuffix(t) .. " " .. copyVar):done()
table.insert(requirements, tableData)
end
end
end
end
end
 
 
for _, row in ipairs(requirements) do
for _, row in ipairs(requirements) do
createTable:node(row)
createTable:node(row)
end
end
 
return tostring(createTable)
return tostring(createTable)
end
end


return p
return p