Module:ItemTables: Difference between revisions

From Deadlock Wiki
Jump to navigation Jump to search
Sylphoid (talk | contribs)
cleanup, remove local functions in favor for main module passing functionality
Cypress (talk | contribs)
m ...also add % suffix to Spirit Lifesteal
 
(65 intermediate revisions by 2 users not shown)
Line 2: Line 2:
local data = mw.loadJsonData("Data:ItemData.json")
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 commas = require("Module:Addcommas")


-- returns the table of a specific item
-- Returns an array of item tables that have the same properties
function get_json_item(name)
-- @function  get_similar_items_array
for i,v in pairs(data) do
-- @param      {array}
if (v["Name"] == name) then
-- @return    {array of tables}
return v
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
end
end
return nil
return noDuplicates
end
 
-- Adds commas delimiter to the thousands place
function Format(amount)
    local formatted = amount
    while true do
        formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
        if (k == 0) then
            break
        end
    end
    return formatted
end
end


Line 43: Line 50:
end
end


local function get_type(item_name)
-- local link_patterns = {}
local item = get_json_item(item_name)
-- link_patterns["BonusClipSizePercent"] = { "[Aa]mmo" }
if(item == nil) then return "<span style=\"color:red;\">Item Not Found.</span>" end
-- link_patterns["CloseRangeBonusWeaponPower"] = { "[Cc]lose [Ww]eapon [Dd]amage" }
-- link_patterns["BaseAttackDamagePercent"] = { "[Ww]eapon [Dd]amage" }
if (item["Slot"] == "Weapon") then
-- link_patterns["BulletLifestealPercent"] = { "[Bb]ullet [Ll]ifesteal" }
return "Weapon"
-- link_patterns["BonusHealthRegen"] = { "[Hh]ealth [Rr]egen" }
elseif (item["Slot"] == "Armor") then
-- link_patterns["BonusHealth"] = { "[Hh]ealth" }
return "Vitality"
-- link_patterns["BonusFireRate"] = { "[Ff]ire [Rr]ate" }
elseif (item["Slot"] == "Tech") then
--
return "Spirit"
-- function FriendlyNames(desc)
else
-- for link, patterns in pairs(link_patterns) do
return nil
-- 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
end
return keysTable
end
end


p.get_type = function(frame)
local unitSuffix = {
local item_name = frame.args[1]
["%"] = { "BonusClipSizePercent", "ActiveReloadPercent",
return get_type(item_name)
"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
end


local sortByWeapon = {}
sortByWeapon["Weapon"] = 1
sortByWeapon["Armor"] = 10000
sortByWeapon["Tech"] = 100000000


local link_patterns = {}
-- Sort the order of items in a preset as it appears when no filtered ordering is applied.
link_patterns["BonusClipSizePercent"] = { "[Aa]mmo" }
-- Ordered first by slot and cost increasing, then alphabetical within same slot and cost.
link_patterns["BulletLifestealPercent"] = { "[Bb]ullet [Ll]ifesteal" }
function defaultSort()
link_patterns["BonusHealth"] = { "[Hh]ealth" }
    return function(a, b)
link_patterns["BonusHealthRegen"] = { "[Hh]ealth [Rr]egen" }
    if (get_cost(a["Name"]) == get_cost(b["Name"]) and sortByWeapon[a["Slot"]] == sortByWeapon[b["Slot"]]) then return a["Name"] < b["Name"] end
link_patterns["BonusFireRate"] = { "[Ff]ire [Rr]ate" }
        return get_cost(a["Name"]) * sortByWeapon[a["Slot"]] < get_cost(b["Name"]) * sortByWeapon[b["Slot"]]
    end
end


function FriendlyNames(desc)
-- Formats the value of the stat with a + or -
for link, patterns in pairs(link_patterns) do
-- @function   signPrefix
for i, v in ipairs(patterns) do
-- @param      {string}
    local a, b = desc:find(v)
-- @return    {string}
if a then
local function signPrefix(value)
        desc = link
local signString = ""
        break
value = value:gsub( "m", "" )
    end
value = tonumber(value)
    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 listofItems = ""
local property = frame.args[1] or mw.title.getCurrentTitle().text
local property = frame:getParent().args[1] or mw.title.getCurrentTitle().text
property = FriendlyNames(property)
local copyVar = property
-- local item = get_json_item(item_name)
listofKeysTable = friendlyNames(property)  
-- if(item == nil) then return "Item Not Found what" end
local filteredData = {}
filteredData = get_similar_items_array(listofKeysTable)
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 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('Cost'):done()
:tag('th'):wikitext(soulIcon .. 'Cost'):done()
:tag('th'):wikitext('Category'):done()
:tag('th'):wikitext('Category'):done()
:tag('th'):wikitext('Stat change'):done()
createTable:node(createTableRow)
createTable:node(createTableHeader)
-- query all the filtered items. itemName is the item table.
for internalName, 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 = {
args = {
statName["Name"]
itemName["Name"]
}
}
}
}
if(statName[property] ~= nil and statName["Name"] ~= nil) then
for k, t in pairs(listofKeysTable) do
listofItems = listofItems .. statName["Name"] .. "<br/>"
-- 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')
local tableData = mw.html.create('tr')
tableData
tableData
:tag('td'):wikitext(display):done()
:tag('td'):wikitext(display):done()
:tag('td'):wikitext(get_cost(statName["Name"])):done()
:tag('td'):wikitext(commas._add(get_cost(itemName["Name"]))):done()
:tag('td'):wikitext(get_type(statName["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)
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
end
for _, row in ipairs(requirements) do
for _, row in ipairs(requirements) do
createTableRow:node(row)
createTableHeader:node(row)
end
end
--createTable:node(createTableRow)
return tostring(createTable)
return tostring(createTable) --, listofItems -- this is just a string list, same thing as createTable. delete this when line when finished
--return listofItems -- this is just a string list, same thing as createTable. delete this when line when finished
--return table.concat(TableValues, ", ")


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