Anonymous

Module:Items: Difference between revisions

From Melvor Idle
12,157 bytes added ,  9 March 2022
getItemDataExport: Implement
(Added Passive slot mention for passive items)
(getItemDataExport: Implement)
(41 intermediate revisions by 4 users not shown)
Line 6: Line 6:
local p = {}
local p = {}


local MonsterData = mw.loadData('Module:Monsters/data')
local ItemData = mw.loadData('Module:Items/data')
local ItemData = mw.loadData('Module:Items/data')
local SkillData = mw.loadData('Module:Skills/data')
local Constants = mw.loadData('Module:Constants/data')


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


p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon'}
p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon', 'Easter Egg',
p.OtherShopItems = {'Cooking Gloves', 'Mining Gloves', 'Gem Gloves', 'Smithing Gloves', 'Thieving Gloves'}
'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
--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},
                  ["Sapphire"] = {name = "Sapphire", id = 129, chance = 17.5},  
["Sapphire"] = {name = "Sapphire", id = 129, chance = 17.5},
                  ["Ruby"] = {name = "Ruby", id = 130, chance = 17.5},  
["Ruby"] = {name = "Ruby", id = 130, chance = 17.5},
                  ["Emerald"] = {name = "Emerald", id = 131, chance = 10},  
["Emerald"] = {name = "Emerald", id = 131, chance = 10},
                  ["Diamond"] = {name = "Diamond", id = 132, chance = 5}}
["Diamond"] = {name = "Diamond", id = 132, chance = 5}}
--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
local 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}}


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


p.specialFishWt = 6722
function p.getItem(name)
p.specialFishLoot = {{128, 2000}, {129, 1600}, {130, 1400}, {131, 1000}, {132, 400}, {667, 10}, {668, 10}, {902, 1}, {670, 1}, {669, 50}, {120, 250}}
local result = nil
name = string.gsub(name, "%%27", "'")
name = string.gsub(name, "'", "'")
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.buildSpecialFishingTable()
function p.getItems(checkFunc)
  --This shouldn't ever be included in a page
local result = {}
  --This is for generating the above 'specialFishLoot' variable if it ever needs to change
local itemCount = 0
  --To re-run, edit the module, type in "console.log(p.buildSpecialFishingTable())" and copy+paste the result as the new value of the variable
for i, item in ipairs(ItemData.Items) do
  --Also gives you the total fishing weight for saving time later
if checkFunc(item) then
  local lootArray = {}
local newItem = Shared.clone(item)
  local totalWt = 0
newItem.id = i - 1
itemCount = itemCount + 1
result[itemCount] = newItem
end
end
return result
end


  for i, item in pairs(ItemData.Items) do
function p._getItemStat(item, StatName, ZeroIfNil)
    if item.fishingCatchWeight ~= nil then
local result = item[StatName]
      totalWt = totalWt + item.fishingCatchWeight
--Special Overrides:
      table.insert(lootArray, '{'..(i - 1)..', '..item.fishingCatchWeight..'}')
-- Equipment stats first
    end
if Shared.contains(ItemData.EquipmentStatKeys, StatName) and item.equipmentStats ~= nil then
  end
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


  local result = 'p.specialFishWt = '..totalWt..'\r\n'
function p.getItemStat(frame)
  result = result..'p.specialFishLoot = {'..table.concat(lootArray, ', ')..'}'
local args = frame.args ~= nil and frame.args or frame
  return result
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
end


function p.getSpecialAttackByID(ID)
--Gets the value of a given modifier for a given item
  local result = Shared.clone(ItemData.SpecialAttacks[ID + 1])
--asString is false by default, when true it writes the full bonus text
  if result ~= nil then
function p._getItemModifier(item, modifier, skill, asString)
    result.id = ID
if asString == nil then asString = false end
  end
if skill == '' then
  return result
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
end


function p.getItemByID(ID)
function p.hasCombatStats(item)
  local result = Shared.clone(ItemData.Items[ID + 1])
if item.isEquipment or (item.validSlots == nil and item.equipmentStats ~= nil) then
  if result ~= nil then
-- Ensure at least one stat has a non-zero value
    result.id = ID
for statName, statVal in pairs(item.equipmentStats) do
  end
if statVal ~= 0 then return true end
  return result
end
end
return false
end
end


function p.getItem(name)
function p._hasLevelRequirements(item)
  local result = nil
--Function true if an item has at least one level requirement to equip
  name = string.gsub(name, "%%27", "'")
if item.equipRequirements ~= nil and item.equipRequirements.Level ~= nil then
  name = string.gsub(name, "'", "'")
for skillID, lvl in pairs(item.equipRequirements.Level) do
  name = string.gsub(name, "'", "'")
if lvl ~= nil and lvl > 1 then
  for i, item in pairs(ItemData.Items) do
return true
    local itemName = string.gsub(item.name, '#', '')
end
    if(name == itemName) then
end
      result = Shared.clone(item)
return false
      --Make sure every item has an id, and account for Lua being 1-index
else
      result.id = i - 1
return false
      break
end
    end
  end
  return result
end
end


function p.getItems(checkFunc)
function p.getItemModifier(frame)
  local result = {}
local itemName = frame.args ~= nil and frame.args[1] or frame[1]
  for i, item in pairs(ItemData.Items) do
local modName = frame.args ~= nil and frame.args[2] or frame[2]
    if checkFunc(item) then
local skillName = frame.args ~= nil and frame.args[3] or frame[3]
      local newItem = Shared.clone(item)
local asString = frame.args ~= nil and frame.args[4] or frame[4]
      newItem.id = i - 1
if asString ~= nil then
      table.insert(result, newItem)
asString = (string.upper(asString) ~= 'FALSE')
    end
end
  end
  return result
end


function p._getItemStat(item, StatName, ZeroIfNil)
local item = p.getItem(itemName)
  local result = item[StatName]
if item == nil then
  --Special Overrides:
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  if StatName == 'stabAttackBonus' then
end
    if item.attackBonus == nil then  
      result = nil
    else
      result = item.attackBonus[1]
    end
  elseif StatName == 'slashAttackBonus' then
    if item.attackBonus == nil then
      result = nil
    else
      result = item.attackBonus[2]
    end
  elseif StatName == 'blockAttackBonus' then
    if item.attackBonus == nil then
      result = nil
    else
      result = item.attackBonus[3]
    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
      return 'Yes'
    else
      return 'No'
    end
  end
  if result == nil and ZeroIfNil then result = 0 end
  return result
end


function p.getItemStat(frame)
return p._getItemModifier(item, modName, skillName, asString)
  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"
  end
  local result = p._getItemStat(item, StatName, ZeroIfNil)
  if formatNum then result = Shared.formatnum(result) end
  return result
end
end


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


function p.getWeaponAttackType(frame)
function p.getWeaponAttackType(frame)
  local itemName = frame.args ~= nil and frame.args[1] or frame
local itemName = frame.args ~= nil and frame.args[1] or frame
  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"
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)
end
end


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


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


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


  result = result..'\r\n|}'
table.insert(resultPart, '\r\n|}')
  return result
return table.concat(resultPart)
end
 
function p.getEquipmentSlotName(id)
  for slotName, i in Shared.skpairs(Constants.equipmentSlot) do
    if i == id then
      return slotName
    end
  end
  return 'Invalid'
end
end


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


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


  return p._getOtherItemBoxText(item, asList)
return p._getOtherItemBoxText(item, asList)
end
end


function p._getItemCategories(item)
function p._getItemCategories(item)
  local result = ''
local resultPart = {}
  if item.category ~= nil then result = result..'[[Category:'..item.category..']]' end
if item.category ~= nil then table.insert(resultPart, '[[Category:'..item.category..']]') end
  if item.type ~= nil then result = result..'[[Category:'..item.type..']]' end
if item.type ~= nil then table.insert(resultPart, '[[Category:'..item.type..']]') end
  if item.tier ~= nil then result = result..'[[Category:'..Shared.titleCase(item.tier)..' '..item.type..']]' end
if item.tier ~= nil then table.insert(resultPart, '[[Category:'..Shared.titleCase(item.tier)..' '..item.type..']]') end
  if item.hasSpecialAttack then result = result..'[[Category:Items With Special Attacks]]' end
if item.hasSpecialAttack then table.insert(resultPart, '[[Category:Items With Special Attacks]]') end
  if item.isPassiveItem then result = result..'[[Category:Passive Items]]' end
if item.validSlots ~= nil then
  if item.chanceToDoubleLoot ~= nil and item.chanceToDoubleLoot > 0 then result = result..'[[Category:Double Loot Chance Items]]' end
local slotRemap = {
  return result
['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
end


function p.getItemCategories(frame)
function p.getItemCategories(frame)
  local itemName = frame.args ~= nil and frame.args[1] or frame
local itemName = frame.args ~= nil and frame.args[1] or frame
  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"
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
end


  return p._getItemCategories(item)
return p._getItemCategories(item)
end
end


function p.getSkillcapeTable(frame)
function p.getSkillcapeTable(frame)
  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 result = '{| class="wikitable"\r\n'
if cape == nil then
  result = result..'!Skillcape!!Name!!Effect'
return ''
  result = result..'\r\n|-\r\n|'..Icons.Icon({cape.name, type='item', size='60', notext=true})
else
  result = result..'||[['..cape.name..']]||'..cape.description
local resultPart = {}
  result = result..'\r\n|}'
table.insert(resultPart, '{| class="wikitable"\r\n')
  return result
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
end


function p.getShopSkillcapeTable()
function p.getItemGrid(frame)
  local result = ''
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))


  local capeList = {}
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Type')
  for i, item in pairs(ItemData.Items) do
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackType'))
    if Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion' then
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Damage Reduction')
      table.insert(capeList, item)
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'damageReduction', true) .. '%')
    end
  end


  result = result..'\r\n{|class="wikitable sortable"'
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus')
  result = result..'\r\n!colspan="2" style="width:200px"|Cape'
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true))
  result = result..'!!Description!!style="width:120px"|Price'
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))


  --Sort the table by cost and then name
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus')
  table.sort(capeList, function(a, b)
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', true))
                        if a.buysFor == b.buysFor then
table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus')
                          return a.name < b.name
table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true))
                        else
                          return a.sellsFor < b.buysFor
                        end
                      end)
  for i, thisItem in pairs(capeList) do
    result = result..'\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item', size='50', notext=true})
    result = result..'||[['..thisItem.name..']]'
    result = result..'\r\n||'..thisItem.description
    result = result..'||style="text-align:left" data-sort-value="'..thisItem.buysFor..'"'
    result = result..'|'..Icons.GP(thisItem.buysFor)
  end
  result = result..'\r\n|}'


  return result
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
end


function p.getItemGrid(frame)
function p.getArmourStatsBox(frame)
  result = '{|'
local itemName = frame.args ~= nil and frame.args[1] or frame
  for i, item in Shared.skpairs(ItemData.Items) do
local item = p.getItem(itemName)
    if i % 17 == 1 then
if item == nil then
      result = result..'\r\n|-\r\n|'
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
    else
end
      result = result..'||'
 
    end
local ico = {
    result = result..'style="padding:3px"|'..Icons.Icon({item.name, type='item', notext=true, size='40'})
["Attack"] = Icons.Icon({'Attack', type='skill', notext=true}),
  end
["Combat"] = Icons.Icon({'Combat', notext=true}),
  result = result..'\r\n|}'
["Defence"] = Icons.Icon({'Defence', type='skill', notext=true}),
  return result
["Magic"] = Icons.Icon({'Magic', type='skill', notext=true}),
end
["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))


function p.getSpecialAttackTable(frame)
table.insert(resultPart, '\r\n|-\r\n| colspan="2"|')
  local spAttTable = {}
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))
  for i, item in Shared.skpairs(ItemData.Items) do
    if item.hasSpecialAttack then
      if spAttTable[item.specialAttackID] == nil then spAttTable[item.specialAttackID] = {sortName=item.name, Icons = {}} end
      table.insert(spAttTable[item.specialAttackID].Icons, Icons.Icon({item.name, type='item'}))
    end
  end 


  local result = '{|class="wikitable sortable stickyHeader"'
table.insert(resultPart, '\r\n|}')
  result = result..'\r\n|-class="headerRow-0"'
return table.concat(resultPart)
  result = result..'\r\n!style="min-width:180px"|Weapon(s)!!Name!!Chance!!Effect'
end
  for i, spAttData in Shared.skpairs(spAttTable) do
    local spAtt = p.getSpecialAttackByID(i)
    table.sort(spAttData.Icons, function(a, b) return a < b end)
    result = result..'\r\n|-'
    result = result..'\r\n|data-sort-value="'..spAttData.sortName..'"|'..table.concat(spAttData.Icons, '<br/>')
    result = result..'||'..spAtt.name..'||data-sort-value="'..spAtt.chance..'"|'..spAtt.chance..'%'
    result = result..'||'..spAtt.description
  end
  result = result..'\r\n|}'


  return result
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