Difference between revisions of "Module:Items"

From Melvor Idle
m (Add platelegs to slot map)
(getItemDataExport: Implement)
 
(7 intermediate revisions by the same user not shown)
Line 12: Line 12:
 
local Icons = require('Module:Icons')
 
local Icons = require('Module:Icons')
  
p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon', 'Easter Egg', 'Abnormal Log', 'Red Herring', 'Cool Glasses'}
+
p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon', 'Easter Egg',
 +
'Abnormal Log', 'Red Herring', 'Cool Glasses'}
 
p.EventItems = {'Christmas Cracker', 'Christmas Coal', 'Christmas Sweater',
 
p.EventItems = {'Christmas Cracker', 'Christmas Coal', 'Christmas Sweater',
 
'Christmas Wreath', 'Candy Cane', 'Santa Hat',
 
'Christmas Wreath', 'Candy Cane', 'Santa Hat',
Line 23: Line 24:
 
'Holiday Scarf', 'Gingerbread House', 'Gingerbread Man', 'Edible Candy Cane',
 
'Holiday Scarf', 'Gingerbread House', 'Gingerbread Man', 'Edible Candy Cane',
 
'Locked Chest', 'Locked Chest Key', 'Event Token (Holiday 2021)'}
 
'Locked Chest', 'Locked Chest Key', 'Event Token (Holiday 2021)'}
p.OtherShopItems = {'Cooking Gloves', 'Mining Gloves', 'Gem Gloves', 'Smithing Gloves', 'Thieving Gloves'}
 
 
--This is hardcoded, so there's no easy way to scrape it. Hopefully it doesn't change
 
--This is hardcoded, so there's no easy way to scrape it. Hopefully it doesn't change
 
p.GemTable = {["Topaz"] = {name = 'Topaz', id = 128, chance = 50},
 
p.GemTable = {["Topaz"] = {name = 'Topaz', id = 128, chance = 50},
Line 32: Line 32:
 
--The base chance to receive a gem while mining
 
--The base chance to receive a gem while mining
 
p.GemChance = .01
 
p.GemChance = .01
--The number of different fishing junk items
 
p.junkCount = 8
 
--Items (aside from bars & gems) which can be created via Alt Magic
 
p.AltMagicProducts = {'Rune Essence', 'Bones', 'Holy Dust'}
 
--The kinds of gloves with cost & charges
 
p.GloveTable = {['Cooking Gloves'] = {cost=50000, charges=500},
 
['Mining Gloves'] = {cost=75000, charges=500},
 
['Smithing Gloves'] = {cost=100000, charges=500},
 
['Thieving Gloves'] = {cost=100000, charges=500},
 
['Gem Gloves'] = {cost=500000, charges=2000}}
 
 
 
p.specialFishWt = 6722
 
p.specialFishLoot = {{128, 2000}, {129, 1600}, {130, 1400}, {131, 1000}, {132, 400}, {667, 10}, {668, 10}, {902, 1}, {670, 1}, {669, 50}, {120, 250}}
 
 
function p.buildSpecialFishingTable()
 
--This shouldn't ever be included in a page
 
--This is for generating the above 'specialFishLoot' variable if it ever needs to change
 
--To re-run, edit the module, type in "console.log(p.buildSpecialFishingTable())" and copy+paste the result as the new value of the variable
 
--Also gives you the total fishing weight for saving time later
 
local lootArray = {}
 
local totalWt = 0
 
 
for i, item in pairs(ItemData.Items) do
 
if item.fishingCatchWeight ~= nil then
 
totalWt = totalWt + item.fishingCatchWeight
 
table.insert(lootArray, '{'..(i - 1)..', '..item.fishingCatchWeight..'}')
 
end
 
end
 
 
local result = 'p.specialFishWt = '..totalWt..'\r\n'
 
result = result..'p.specialFishLoot = {'..table.concat(lootArray, ', ')..'}'
 
return result
 
end
 
  
 
function p.getItemByID(ID)
 
function p.getItemByID(ID)
Line 79: Line 45:
 
name = string.gsub(name, "%%27", "'")
 
name = string.gsub(name, "%%27", "'")
 
name = string.gsub(name, "'", "'")
 
name = string.gsub(name, "'", "'")
for i, item in pairs(ItemData.Items) do
+
for i, item in ipairs(ItemData.Items) do
 
local itemName = string.gsub(item.name, '#', '')
 
local itemName = string.gsub(item.name, '#', '')
 
if name == itemName then
 
if name == itemName then
Line 93: Line 59:
 
function p.getItems(checkFunc)
 
function p.getItems(checkFunc)
 
local result = {}
 
local result = {}
for i, item in pairs(ItemData.Items) do
+
local itemCount = 0
 +
for i, item in ipairs(ItemData.Items) do
 
if checkFunc(item) then
 
if checkFunc(item) then
 
local newItem = Shared.clone(item)
 
local newItem = Shared.clone(item)
 
newItem.id = i - 1
 
newItem.id = i - 1
table.insert(result, newItem)
+
itemCount = itemCount + 1
 +
result[itemCount] = newItem
 
end
 
end
 
end
 
end
Line 250: Line 218:
 
local item = p.getItem(itemName)
 
local item = p.getItem(itemName)
 
if item == nil then
 
if item == nil then
return "ERROR: No item named "..ItemName.." exists in the data module[[Category:Pages with script errors]]"
+
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
 
end
 
end
 
return p._getWeaponAttackType(item)
 
return p._getWeaponAttackType(item)
Line 267: Line 235:
 
return 'ERROR: No potion named "' .. potionName .. '" was found[[Category:Pages with script errors]]'
 
return 'ERROR: No potion named "' .. potionName .. '" was found[[Category:Pages with script errors]]'
 
end
 
end
for i, tier in pairs(tiers) do
+
for i, tier in ipairs(tiers) do
 
local tierName = potionName..' '..tier
 
local tierName = potionName..' '..tier
 
local potion = p.getItemByID(tier1potion.id + i - 1)
 
local potion = p.getItemByID(tier1potion.id + i - 1)
Line 404: Line 372:
 
local skillName = frame.args ~= nil and frame.args[1] or frame
 
local skillName = frame.args ~= nil and frame.args[1] or frame
 
local cape = p.getItem(skillName..' Skillcape')
 
local cape = p.getItem(skillName..' Skillcape')
local resultPart = {}
+
if cape == nil then
table.insert(resultPart, '{| class="wikitable"\r\n')
+
return ''
table.insert(resultPart, '!Skillcape!!Name!!Effect')
+
else
table.insert(resultPart, '\r\n|-\r\n|'..Icons.Icon({cape.name, type='item', size='60', notext=true}))
+
local resultPart = {}
table.insert(resultPart, '||'..Icons.Icon({cape.name, type='item', noicon=true})..'||'..cape.description)
+
table.insert(resultPart, '{| class="wikitable"\r\n')
table.insert(resultPart, '\r\n|}')
+
table.insert(resultPart, '!Skillcape!!Name!!Effect')
return table.concat(resultPart)
+
table.insert(resultPart, '\r\n|-\r\n|'..Icons.Icon({cape.name, type='item', size='60', notext=true}))
 +
table.insert(resultPart, '||'..Icons.Icon({cape.name, type='item', noicon=true})..'||'..cape.description)
 +
table.insert(resultPart, '\r\n|}')
 +
return table.concat(resultPart)
 +
end
 
end
 
end
  
Line 425: Line 397:
 
end
 
end
 
table.insert(resultPart, '\r\n|}')
 
table.insert(resultPart, '\r\n|}')
return table.concat(resultPart)
 
end
 
 
function p.getSpecialAttackTable(frame)
 
local spAttTable = {}
 
 
for i, item in Shared.skpairs(ItemData.Items) do
 
if item.hasSpecialAttack then
 
for i, spAtt in ipairs(item.specialAttacks) do
 
if spAttTable[spAtt.id] == nil then spAttTable[spAtt.id] = {sortName=item.name, defn = spAtt, Icons = {}} end
 
table.insert(spAttTable[spAtt.id].Icons, Icons.Icon({item.name, type='item'}))
 
end
 
end
 
end
 
 
local resultPart = {}
 
table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
 
table.insert(resultPart, '\r\n|-class="headerRow-0"')
 
table.insert(resultPart, '\r\n!style="min-width:180px"|Weapon(s)!!Name!!Chance!!Effect')
 
for i, spAttData in Shared.skpairs(spAttTable) do
 
local spAtt = spAttData.defn
 
table.sort(spAttData.Icons, function(a, b) return a < b end)
 
table.insert(resultPart, '\r\n|-')
 
table.insert(resultPart, '\r\n|data-sort-value="'..spAttData.sortName..'"|'..table.concat(spAttData.Icons, '<br/>'))
 
table.insert(resultPart, '||'..spAtt.name..'||data-sort-value="'..spAtt.defaultChance..'"|'..spAtt.defaultChance..'%')
 
table.insert(resultPart, '||'..spAtt.description)
 
end
 
table.insert(resultPart, '\r\n|}')
 
 
 
return table.concat(resultPart)
 
return table.concat(resultPart)
 
end
 
end
Line 463: Line 406:
 
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
 
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
 
end
 
end
+
 
 
local ico = {
 
local ico = {
 
["Attack"] = Icons.Icon({'Attack', type='skill', notext=true}),
 
["Attack"] = Icons.Icon({'Attack', type='skill', notext=true}),
Line 477: Line 420:
 
table.insert(resultPart, '\r\n|-\r\n!colspan="2" style="border-bottom:solid thin black;"| Offensive Stats')
 
table.insert(resultPart, '\r\n|-\r\n!colspan="2" style="border-bottom:solid thin black;"| Offensive Stats')
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Defensive Stats')
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Defensive Stats')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Speed')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Speed')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. Shared.round(p._getItemStat(item, 'attackSpeed', true) / 1000, 3, 1) .. 's')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. Shared.round(p._getItemStat(item, 'attackSpeed', true) / 1000, 3, 1) .. 's')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Type')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Type')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackType'))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackType'))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Damage Reduction')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Damage Reduction')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'damageReduction', true) .. '%')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'damageReduction', true) .. '%')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedDefenceBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedDefenceBonus', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true))
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Other')
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Other')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Slayer'] .. ' Bonus Slayer XP')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Slayer'] .. ' Bonus Slayer XP')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slayerBonusXP', true) .. '%')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slayerBonusXP', true) .. '%')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Attack'] .. ' Level Required')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Attack'] .. ' Level Required')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackLevelRequired', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackLevelRequired', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Level Required')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Level Required')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedLevelRequired', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedLevelRequired', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Level Required')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Level Required')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicLevelRequired', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicLevelRequired', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| Two Handed?')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| Two Handed?')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. (p._getItemStat(item, 'isTwoHanded') and 'Yes' or 'No'))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. (p._getItemStat(item, 'isTwoHanded') and 'Yes' or 'No'))
+
 
 
table.insert(resultPart, '\r\n|}')
 
table.insert(resultPart, '\r\n|}')
 
return table.concat(resultPart)
 
return table.concat(resultPart)
Line 537: Line 480:
 
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
 
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
 
end
 
end
+
 
 
local ico = {
 
local ico = {
 
["Attack"] = Icons.Icon({'Attack', type='skill', notext=true}),
 
["Attack"] = Icons.Icon({'Attack', type='skill', notext=true}),
Line 551: Line 494:
 
table.insert(resultPart, '\r\n|-\r\n!colspan="2" style="border-bottom:solid thin black;"| Offensive Stats')
 
table.insert(resultPart, '\r\n|-\r\n!colspan="2" style="border-bottom:solid thin black;"| Offensive Stats')
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Defensive Stats')
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Defensive Stats')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', 0))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', 0))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Damage Reduction')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Damage Reduction')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'damageReduction', true) .. '%')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'damageReduction', true) .. '%')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedDefenceBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedDefenceBonus', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true))
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Other')
 
table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Other')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Slayer'] .. ' Bonus Slayer XP')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Slayer'] .. ' Bonus Slayer XP')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slayerBonusXP', true) .. '%')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slayerBonusXP', true) .. '%')
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true))
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Level Required')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Level Required')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'defenceLevelRequired', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'defenceLevelRequired', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus')
 
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Level Required')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Level Required')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedLevelRequired', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedLevelRequired', true))
+
 
 
table.insert(resultPart, '\r\n|-\r\n| colspan="2"|')
 
table.insert(resultPart, '\r\n|-\r\n| colspan="2"|')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Level Required')
 
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Level Required')
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicLevelRequired', true))
 
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicLevelRequired', true))
+
 
 
table.insert(resultPart, '\r\n|}')
 
table.insert(resultPart, '\r\n|}')
 
return table.concat(resultPart)
 
return table.concat(resultPart)
 +
end
 +
 +
function p.getItemDataExport(frame)
 +
local resultTable = mw.html.create('table')
 +
resultTable:addClass('wikitable')
 +
resultTable:tag('tr'):addClass('headerRow-0')
 +
:tag('th'):wikitext('ItemID'):done()
 +
:tag('th'):wikitext('ItemName'):done()
 +
:tag('th'):wikitext('GPValue'):done()
 +
 +
for i, item in ipairs(ItemData.Items) do
 +
resultTable:tag('tr')
 +
:tag('td'):wikitext(item.id):done()
 +
:tag('td'):wikitext(item.name):done()
 +
:tag('td'):wikitext(item.sellsFor):done()
 +
end
 +
return tostring(resultTable)
 
end
 
end
  
 
return p
 
return p

Latest revision as of 20:53, 9 March 2022

Lua module for generating various item tables. Pulls data from Module:Items/data


--This module contains all sorts of functions for getting data on items
--Several functions related to use tables can be found at Module:Items/UseTables
--Functions related to source tables can be found at Module:Items/SourceTables
--Other functions moved to Module:Items/ComparisonTables

local p = {}

local ItemData = mw.loadData('Module:Items/data')

local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Icons = require('Module:Icons')

p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon', 'Easter Egg',
				'Abnormal Log', 'Red Herring', 'Cool Glasses'}
p.EventItems = {'Christmas Cracker', 'Christmas Coal', 'Christmas Sweater',
				'Christmas Wreath', 'Candy Cane', 'Santa Hat',
				'Friendship Bracelet', 'Event Clue 1', 'Event Clue 2',
				'Event Clue 3', 'Event Clue 4', 'Candle', 'Cake Base',
				'Magical Flavouring', 'Magical Icing', 'Birthday Cake',
				'Purple Party Hat', 'Birthday Token', 'Christmas Present (Yellow)',
				'Christmas Present (Blue)', 'Christmas Present (Green)', 'Christmas Present (White)',
				'Christmas Present (Purple)', 'Christmas Present (Standard)', 'Event Token - Holiday 2021',
				'Holiday Scarf', 'Gingerbread House', 'Gingerbread Man', 'Edible Candy Cane',
				'Locked Chest', 'Locked Chest Key', 'Event Token (Holiday 2021)'}
--This is hardcoded, so there's no easy way to scrape it. Hopefully it doesn't change
p.GemTable = {["Topaz"] = {name = 'Topaz', id = 128, chance = 50},
				["Sapphire"] = {name = "Sapphire", id = 129, chance = 17.5},
				["Ruby"] = {name = "Ruby", id = 130, chance = 17.5},
				["Emerald"] = {name = "Emerald", id = 131, chance = 10},
				["Diamond"] = {name = "Diamond", id = 132, chance = 5}}
--The base chance to receive a gem while mining
p.GemChance = .01

function p.getItemByID(ID)
	local result = Shared.clone(ItemData.Items[ID + 1])
	if result ~= nil then
		result.id = ID
	end
	return result
end

function p.getItem(name)
	local result = nil
	name = string.gsub(name, "%%27", "'")
	name = string.gsub(name, "&#39;", "'")
	for i, item in ipairs(ItemData.Items) do
		local itemName = string.gsub(item.name, '#', '')
		if name == itemName then
			result = Shared.clone(item)
			--Make sure every item has an id, and account for Lua being 1-index
			result.id = i - 1
			break
		end
	end
	return result
end

function p.getItems(checkFunc)
	local result = {}
	local itemCount = 0
	for i, item in ipairs(ItemData.Items) do
		if checkFunc(item) then
			local newItem = Shared.clone(item)
			newItem.id = i - 1
			itemCount = itemCount + 1
			result[itemCount] = newItem
		end
	end
	return result
end

function p._getItemStat(item, StatName, ZeroIfNil)
	local result = item[StatName]
	--Special Overrides:
	-- Equipment stats first
	if Shared.contains(ItemData.EquipmentStatKeys, StatName) and item.equipmentStats ~= nil then
		result = item.equipmentStats[StatName]
	elseif StatName == 'isTwoHanded' then
		if item.validSlots ~= nil and item.occupiesSlots ~= nil then
			result = Shared.contains(item.validSlots, 'Weapon') and Shared.contains(item.occupiesSlots, 'Shield')
		else
			result = false
		end
	elseif string.find(StatName, '^(.+)LevelRequired$') ~= nil and item.equipRequirements ~= nil and item.equipRequirements.Level ~= nil then
		local skillName = Shared.titleCase(string.match(StatName, '^(.+)LevelRequired$'))
		if skillName ~= nil then
			local skillID = Constants.getSkillID(skillName)
			if skillID ~= nil then
				result = item.equipRequirements.Level[skillID]
			end
		end
	elseif StatName == 'attackType' then
		result = p._getWeaponAttackType(item)
	elseif StatName == 'description' then
		result = item.description
		if result == nil or result == '' then result = 'No Description' end
	elseif StatName == 'completionReq' then
		if item.ignoreCompletion == nil or not item.ignoreCompletion then
			result = 'Yes'
		else
			result = 'No'
		end
	elseif StatName == 'slayerBonusXP' then
		return p._getItemModifier(item, 'increasedSkillXP', 'Slayer', false)
	elseif StatName == 'hasCombatStats' then
		return tostring(p.hasCombatStats(item) or p._hasLevelRequirements(item))
	end
	if result == nil and ZeroIfNil then result = 0 end
	return result
end

function p.getItemStat(frame)
	local args = frame.args ~= nil and frame.args or frame
	local ItemName = args[1]
	local StatName = args[2]
	local ZeroIfNil = args.ForceZero ~= nil and args.ForceZero ~= '' and args.ForceZero ~= 'false'
	local formatNum = args.formatNum ~= nil and args.formatNum ~= '' and args.formatNum ~= 'false'
	local item = p.getItem(ItemName)
	if item == nil then
		return "ERROR: No item named "..ItemName.." exists in the data module[[Category:Pages with script errors]]"
	end
	local result = p._getItemStat(item, StatName, ZeroIfNil)
	if formatNum then result = Shared.formatnum(result) end
	return result
end

--Gets the value of a given modifier for a given item
--asString is false by default, when true it writes the full bonus text
function p._getItemModifier(item, modifier, skill, asString)
	if asString == nil then asString = false end
	if skill == '' then
		skill = nil
	elseif type(skill) == 'string' then
		skill = Constants.getSkillID(skill)
	end

	local result = 0

	if item.modifiers ~= nil and item.modifiers[modifier] ~= nil then
		if type(item.modifiers[modifier]) == 'table' then
			for i, subVal in Shared.skpairs(item.modifiers[modifier]) do
				if subVal[1] == skill then
					result = subVal[2]
					break
				end
			end
		else
			result = item.modifiers[modifier]
		end
	end

	if asString then
		if skill ~= nil then
			return Constants._getModifierText(modifier, {skill, result})
		else
			return Constants._getModifierText(modifier, result)
		end
	else
		return result
	end
end

function p.hasCombatStats(item)
	if item.isEquipment or (item.validSlots == nil and item.equipmentStats ~= nil) then
		-- Ensure at least one stat has a non-zero value
		for statName, statVal in pairs(item.equipmentStats) do
			if statVal ~= 0 then return true end
		end
	end
	return false
end

function p._hasLevelRequirements(item)
	--Function true if an item has at least one level requirement to equip
	if item.equipRequirements ~= nil and item.equipRequirements.Level ~= nil then
		for skillID, lvl in pairs(item.equipRequirements.Level) do
			if lvl ~= nil and lvl > 1 then
				return true
			end
		end
		return false
	else
		return false
	end
end

function p.getItemModifier(frame)
	local itemName = frame.args ~= nil and frame.args[1] or frame[1]
	local modName = frame.args ~= nil and frame.args[2] or frame[2]
	local skillName = frame.args ~= nil and frame.args[3] or frame[3]
	local asString = frame.args ~= nil and frame.args[4] or frame[4]
	if asString ~= nil then
		asString = (string.upper(asString) ~= 'FALSE')
	end

	local item = p.getItem(itemName)
	if item == nil then
		return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
	end

	return p._getItemModifier(item, modName, skillName, asString)
end

function p._getWeaponAttackType(item)
	if item.isEquipment == true and (item.validSlots ~= nil and Shared.contains(item.validSlots, 'Weapon')) or
									(item.occupiesSlots ~= nil and Shared.contains(item.occupiesSlots, 'Weapon')) then
		if Shared.contains({'melee', 'ranged', 'magic'}, item.attackType) then
			local iconType = item.attackType ~= 'melee' and 'skill' or nil
			return Icons.Icon({Shared.titleCase(item.attackType), type=iconType, nolink='true'})
		end
	end
	return 'Invalid'
end

function p.getWeaponAttackType(frame)
	local itemName = frame.args ~= nil and frame.args[1] or frame
	local item = p.getItem(itemName)
	if item == nil then
		return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
	end
	return p._getWeaponAttackType(item)
end

function p.getPotionTable(frame)
	local potionName = frame.args ~= nil and frame.args[1] or frame
	local tiers = {'I', 'II', 'III', 'IV'}

	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable"')
	table.insert(resultPart, '\r\n!Potion!!Tier!!Charges!!Effect')

	local tier1potion = p.getItem(potionName..' I')
	if tier1potion == nil then
		return 'ERROR: No potion named "' .. potionName .. '" was found[[Category:Pages with script errors]]'
	end
	for i, tier in ipairs(tiers) do
		local tierName = potionName..' '..tier
		local potion = p.getItemByID(tier1potion.id + i - 1)
		if potion ~= nil then
			table.insert(resultPart, '\r\n|-')
			table.insert(resultPart, '\r\n|'..Icons.Icon({tierName, type='item', notext=true, size='60'}))
			table.insert(resultPart, '||'..Icons.Icon({tierName, tier, type='item', noicon=true}))
			table.insert(resultPart, '||'..potion.potionCharges..'||'..potion.description)
		end
	end

	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

function p._getOtherItemBoxText(item)
	resultPart = {}
	--For equipment, show the slot they go in
	if item.validSlots ~= nil then
		local slotLinkMap = {
			["Helmet"] = 'Equipment#Helmets',
			["Platebody"] = 'Equipment#Platebodies',
			["Platelegs"] = 'Equipment#Platelegs',
			["Boots"] = 'Equipment#Boots',
			["Weapon"] = 'Equipment#Weapons',
			["Shield"] = 'Equipment#Offhand',
			["Amulet"] = 'Equipment#Amulets',
			["Ring"] = 'Equipment#Rings',
			["Gloves"] = 'Equipment#Gloves',
			["Quiver"] = 'Equipment#Ammunition',
			["Cape"] = 'Equipment#Capes',
			["Passive"] = 'Combat Passive Slot',
			["Summon1"] = 'Summoning',
			["Summon2"] = 'Summoning'
		}
		local slotText = {}
		for i, slot in ipairs(item.validSlots) do
			local slotLink = slotLinkMap[slot]
			if slotLink == nil then
				table.insert(slotText, slot)
			else
				table.insert(slotText, '[[' .. slotLink .. '|' .. slot .. ']]')
			end
		end
		table.insert(resultPart, "\r\n|-\r\n|'''Equipment Slot:''' "..table.concat(slotText, ', '))
	end
	--For weapons with a special attack, show the details
	if item.hasSpecialAttack then
		table.insert(resultPart, "\r\n|-\r\n|'''Special Attack:'''")
		for i, spAtt in ipairs(item.specialAttacks) do
			table.insert(resultPart, '\r\n* ' .. spAtt.defaultChance .. '% chance for ' .. spAtt.name .. ':')
			table.insert(resultPart, '\r\n** ' .. spAtt.description)
		end
	end
	--For potions, show the number of charges
	if item.potionCharges ~= nil then
		table.insert(resultPart, "\r\n|-\r\n|'''Charges:''' "..item.potionCharges)
	end
	--For food, show how much it heals for
	if item.healsFor ~= nil then
		table.insert(resultPart, "\r\n|-\r\n|'''Heals for:''' "..Icons.Icon({"Hitpoints", type="skill", notext="true"})..' '..(item.healsFor * 10))
	end
	--For Prayer Points, show how many you get
	if item.prayerPoints ~= nil then
		table.insert(resultPart, "\r\n|-\r\n|'''"..Icons.Icon({'Prayer', type='skill'}).." Points:''' "..item.prayerPoints)
	end
	--For items with modifiers, show what those are
	if item.modifiers ~= nil and Shared.tableCount(item.modifiers) > 0 then
		table.insert(resultPart, "\r\n|-\r\n|'''Modifiers:'''\r\n"..Constants.getModifiersText(item.modifiers, true))
	end
	return table.concat(resultPart)
end

function p.getOtherItemBoxText(frame)
	local itemName = frame.args ~= nil and frame.args[1] or frame
	local item = p.getItem(itemName)
	local asList = false
	if frame.args ~= nil then
		asList = frame.args.asList ~= nil and frame.args.asList ~= '' and frame.args.asList ~= 'false'
	end
	if item == nil then
		return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
	end

	return p._getOtherItemBoxText(item, asList)
end

function p._getItemCategories(item)
	local resultPart = {}
	if item.category ~= nil then table.insert(resultPart, '[[Category:'..item.category..']]') end
	if item.type ~= nil then table.insert(resultPart, '[[Category:'..item.type..']]') end
	if item.tier ~= nil then table.insert(resultPart, '[[Category:'..Shared.titleCase(item.tier)..' '..item.type..']]') end
	if item.hasSpecialAttack then table.insert(resultPart, '[[Category:Items With Special Attacks]]') end
	if item.validSlots ~= nil then
		local slotRemap = {
			['Passive'] = 'Passive Items',
			['Summon1'] = 'Summoning Familiars',
			['Summon2'] = ''
		}
		for i, slotName in ipairs(item.validSlots) do
			local slotRemapName = slotName
			if slotRemap[slotName] ~= nil then slotRemapName = slotRemap[slotName] end
			if slotRemapName ~= '' then table.insert(resultPart, '[[Category:' .. slotRemapName .. ']]') end
		end
	end
	if item.modifiers ~= nil then
		local modsDL = {
			'increasedChanceToDoubleLootCombat',
			'decreasedChanceToDoubleLootCombat',
			'increasedChanceToDoubleLootThieving',
			'decreasedChanceToDoubleLootThieving',
			'increasedChanceToDoubleItemsGlobal',
			'decreasedChanceToDoubleItemsGlobal'
		}
		for modName, val in pairs(item.modifiers) do
			if Shared.contains(modsDL, modName) then
				table.insert(resultPart, '[[Category:Double Loot Chance Items]]')
				break
			end
		end
	end
	return table.concat(resultPart)
end

function p.getItemCategories(frame)
	local itemName = frame.args ~= nil and frame.args[1] or frame
	local item = p.getItem(itemName)
	if item == nil then
		return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
	end

	return p._getItemCategories(item)
end

function p.getSkillcapeTable(frame)
	local skillName = frame.args ~= nil and frame.args[1] or frame
	local cape = p.getItem(skillName..' Skillcape')
	if cape == nil then
		return ''
	else
		local resultPart = {}
		table.insert(resultPart, '{| class="wikitable"\r\n')
		table.insert(resultPart, '!Skillcape!!Name!!Effect')
		table.insert(resultPart, '\r\n|-\r\n|'..Icons.Icon({cape.name, type='item', size='60', notext=true}))
		table.insert(resultPart, '||'..Icons.Icon({cape.name, type='item', noicon=true})..'||'..cape.description)
		table.insert(resultPart, '\r\n|}')
		return table.concat(resultPart)
	end
end

function p.getItemGrid(frame)
	local resultPart = {}
	table.insert(resultPart, '{|')
	for i, item in Shared.skpairs(ItemData.Items) do
		if i % 17 == 1 then
			table.insert(resultPart, '\r\n|-\r\n|')
		else
			table.insert(resultPart, '||')
		end
		table.insert(resultPart, 'style="padding:3px"|'..Icons.Icon({item.name, type='item', notext=true, size='40'}))
	end
	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

function p.getWeaponStatsBox(frame)
	local itemName = frame.args ~= nil and frame.args[1] or frame
	local item = p.getItem(itemName)
	if item == nil then
		return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
	end

	local ico = {
		["Attack"] = Icons.Icon({'Attack', type='skill', notext=true}),
		["Combat"] = Icons.Icon({'Combat', notext=true}),
		["Defence"] = Icons.Icon({'Defence', type='skill', notext=true}),
		["Magic"] = Icons.Icon({'Magic', type='skill', notext=true}),
		["Ranged"] = Icons.Icon({'Ranged', type='skill', notext=true}),
		["Strength"] = Icons.Icon({'Strength', type='skill', notext=true}),
		["Slayer"] = Icons.Icon({'Slayer', type='skill', notext=true})
	}
	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable"\r\n|-\r\n!colspan="4" style="border-bottom:solid medium black;"| Weapon Stats')
	table.insert(resultPart, '\r\n|-\r\n!colspan="2" style="border-bottom:solid thin black;"| Offensive Stats')
	table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Defensive Stats')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Speed')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. Shared.round(p._getItemStat(item, 'attackSpeed', true) / 1000, 3, 1) .. 's')
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Type')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackType'))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Damage Reduction')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'damageReduction', true) .. '%')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Defence Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedDefenceBonus', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true))
	table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Other')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Slayer'] .. ' Bonus Slayer XP')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slayerBonusXP', true) .. '%')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Attack'] .. ' Level Required')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackLevelRequired', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Level Required')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedLevelRequired', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Level Required')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicLevelRequired', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%')
	table.insert(resultPart, '\r\n!style="text-align:right;"| Two Handed?')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. (p._getItemStat(item, 'isTwoHanded') and 'Yes' or 'No'))

	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

function p.getArmourStatsBox(frame)
	local itemName = frame.args ~= nil and frame.args[1] or frame
	local item = p.getItem(itemName)
	if item == nil then
		return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
	end

	local ico = {
		["Attack"] = Icons.Icon({'Attack', type='skill', notext=true}),
		["Combat"] = Icons.Icon({'Combat', notext=true}),
		["Defence"] = Icons.Icon({'Defence', type='skill', notext=true}),
		["Magic"] = Icons.Icon({'Magic', type='skill', notext=true}),
		["Ranged"] = Icons.Icon({'Ranged', type='skill', notext=true}),
		["Strength"] = Icons.Icon({'Strength', type='skill', notext=true}),
		["Slayer"] = Icons.Icon({'Slayer', type='skill', notext=true})
	}
	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable"\r\n|-\r\n!colspan="4" style="border-bottom:solid medium black;"| Armour Stats')
	table.insert(resultPart, '\r\n|-\r\n!colspan="2" style="border-bottom:solid thin black;"| Offensive Stats')
	table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Defensive Stats')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', 0))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Damage Reduction')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'damageReduction', true) .. '%')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Defence Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedDefenceBonus', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true))
	table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Other')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Slayer'] .. ' Bonus Slayer XP')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slayerBonusXP', true) .. '%')

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true))
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Level Required')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'defenceLevelRequired', true))

	table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%')
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Level Required')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedLevelRequired', true))

	table.insert(resultPart, '\r\n|-\r\n| colspan="2"|')
	table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Level Required')
	table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicLevelRequired', true))

	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

function p.getItemDataExport(frame)
	local resultTable = mw.html.create('table')
	resultTable:addClass('wikitable')
	resultTable:tag('tr'):addClass('headerRow-0')
		:tag('th'):wikitext('ItemID'):done()
		:tag('th'):wikitext('ItemName'):done()
		:tag('th'):wikitext('GPValue'):done()
	
	for i, item in ipairs(ItemData.Items) do
		resultTable:tag('tr')
			:tag('td'):wikitext(item.id):done()
			:tag('td'):wikitext(item.name):done()
			:tag('td'):wikitext(item.sellsFor):done()
	end
	return tostring(resultTable)
end

return p