Module:Items/UseTables: Difference between revisions

From Melvor Idle
(_getItemUses: Classify items with special attacks as used in combat)
(Fixed indenting)
Line 17: Line 17:
--Brute forcing some item uses to make things easier
--Brute forcing some item uses to make things easier
local itemUseArray = {
local itemUseArray = {
  Agility = {},
Agility = {},
  Astrology = {'Stardust', 'Golden Stardust'},
Astrology = {'Stardust', 'Golden Stardust'},
  Attack = {},
Attack = {},
  Combat = {'Gold Emerald Ring'},
Combat = {'Gold Emerald Ring'},
  Cooking = {'Cooking Gloves', 'Crown of Rhaelyx'},
Cooking = {'Cooking Gloves', 'Crown of Rhaelyx'},
  Crafting = {'Crown of Rhaelyx'},
Crafting = {'Crown of Rhaelyx'},
  Defence = {},
Defence = {},
  Farming = {'Compost', 'Weird Gloop', 'Bob's Rake'},
Farming = {'Compost', 'Weird Gloop', 'Bob's Rake'},
  Firemaking = {'Crown of Rhaelyx'},
Firemaking = {'Crown of Rhaelyx'},
  Fishing = {'Amulet of Fishing', 'Message in a Bottle'},
Fishing = {'Amulet of Fishing', 'Message in a Bottle'},
  Fletching = {'Crown of Rhaelyx'},
Fletching = {'Crown of Rhaelyx'},
  Herblore = {'Crown of Rhaelyx'},
Herblore = {'Crown of Rhaelyx'},
  Hitpoints = {},
Hitpoints = {},
  Magic = {},
Magic = {},
  Mining = {'Mining Gloves', 'Gem Gloves'},
Mining = {'Mining Gloves', 'Gem Gloves'},
  Prayer = {},
Prayer = {},
  Ranged = {},
Ranged = {},
  Runecrafting = {'Crown of Rhaelyx'},
Runecrafting = {'Crown of Rhaelyx'},
  Slayer = {},
Slayer = {},
  Smithing = {'Smithing Gloves', 'Crown of Rhaelyx'},
Smithing = {'Smithing Gloves', 'Crown of Rhaelyx'},
  Strength = {},
Strength = {},
  Summoning = {'Crown of Rhaelyx'},
Summoning = {'Crown of Rhaelyx'},
  Thieving = {'Chapeau Noir', 'Thieving Gloves', 'Gloves of Silence'},
Thieving = {'Chapeau Noir', 'Thieving Gloves', 'Gloves of Silence'},
  Woodcutting = {},
Woodcutting = {},
  }
}
local potionUseArray = {
local potionUseArray = {
  [0] = 'Combat',
[0] = 'Combat',
  [1] = 'Combat',
[1] = 'Combat',
  [2] = 'Combat',
[2] = 'Combat',
  [3] = 'Combat',
[3] = 'Combat',
  [4] = 'Combat',
[4] = 'Combat',
  [5] = 'Combat',
[5] = 'Combat',
  [6] = 'Combat',
[6] = 'Combat',
  [7] = 'Woodcutting',
[7] = 'Woodcutting',
  [8] = 'Fishing',
[8] = 'Fishing',
  [9] = 'Firemaking',
[9] = 'Firemaking',
  [10] = 'Cooking',
[10] = 'Cooking',
  [11] = 'Mining',
[11] = 'Mining',
  [12] = 'Smithing',
[12] = 'Smithing',
  [13] = 'Thieving',
[13] = 'Thieving',
  [14] = 'Farming',
[14] = 'Farming',
  [15] = 'Fletching',
[15] = 'Fletching',
  [16] = 'Crafting',
[16] = 'Crafting',
  [17] = 'Runecrafting',
[17] = 'Runecrafting',
  [18] = 'Herblore',
[18] = 'Herblore',
  [19] = 'Combat',
[19] = 'Combat',
  [20] = 'Combat',
[20] = 'Combat',
  [21] = 'Combat',
[21] = 'Combat',
  [22] = 'Combat',
[22] = 'Combat',
  [23] = 'Combat',
[23] = 'Combat',
  [24] = 'Agility',
[24] = 'Agility',
  [25] = 'Summoning',
[25] = 'Summoning',
  [26] = 'Combat',
[26] = 'Combat',
  [27] = 'Combat',
[27] = 'Combat',
  [28] = 'Combat',
[28] = 'Combat',
  [29] = 'Astrology'
[29] = 'Astrology'
}
}


function p._getItemUses(item, asList, addCategories)
function p._getItemUses(item, asList, addCategories)
  local useArray = {}
local useArray = {}
  local categoryArray = {}
local categoryArray = {}
  local chr = asList and '* ' or ''
local chr = asList and '* ' or ''
  --Another fun one. This time getting all the different possible ways an item can be used
--Another fun one. This time getting all the different possible ways an item can be used


  --Before anything else, if this is a potion add it to the appropriate override section
--Before anything else, if this is a potion add it to the appropriate override section
  if item.masteryID ~= nil and item.masteryID[1] == 19 then
if item.masteryID ~= nil and item.masteryID[1] == 19 then
  if potionUseArray[item.masteryID[2]] ~= nil then
if potionUseArray[item.masteryID[2]] ~= nil then
  table.insert(itemUseArray[potionUseArray[item.masteryID[2]]], item.name)
table.insert(itemUseArray[potionUseArray[item.masteryID[2]]], item.name)
  else
else
  table.insert(itemUseArray["Combat"], item.name)
table.insert(itemUseArray["Combat"], item.name)
end
end
end
  end


  --If the item has any modifiers that affect a given skill, add it to those lists
--If the item has any modifiers that affect a given skill, add it to those lists
  --Added an exception for Mastery Tokens since they were being incorrectly flagged as usable for all skills
--Added an exception for Mastery Tokens since they were being incorrectly flagged as usable for all skills
  if item.modifiers ~= nil and (item.isToken == nil or not item.isToken) then
if item.modifiers ~= nil and (item.isToken == nil or not item.isToken) then
    local skillArray = Constants.getModifierSkills(item.modifiers)
local skillArray = Constants.getModifierSkills(item.modifiers)
    for i, skillName in Shared.skpairs(skillArray) do
for i, skillName in Shared.skpairs(skillArray) do
      table.insert(itemUseArray[skillName], item.name)
table.insert(itemUseArray[skillName], item.name)
    end
end
  end
end


  --First things added to the list are non-skill things that are easy to check
--First things added to the list are non-skill things that are easy to check
  if Items.hasCombatStats(item) or item.specialAttacks ~= nil or Shared.contains(itemUseArray.Combat, item.name) then
if Items.hasCombatStats(item) or item.specialAttacks ~= nil or Shared.contains(itemUseArray.Combat, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Combat'}))
table.insert(useArray, chr..Icons.Icon({'Combat'}))
  end
end


  if item.healsFor ~= nil then
if item.healsFor ~= nil then
    table.insert(categoryArray, '[[Category:Food Items]]')
table.insert(categoryArray, '[[Category:Food Items]]')
    table.insert(useArray, chr..'[[Food]]')
table.insert(useArray, chr..'[[Food]]')
  end
end


  if item.dropTable ~= nil then
if item.dropTable ~= nil then
    table.insert(categoryArray, '[[Category:Openable Items]]')
table.insert(categoryArray, '[[Category:Openable Items]]')
    table.insert(useArray, chr..'[[Chest Drop Tables|Can Be Opened]]')
table.insert(useArray, chr..'[[Chest Drop Tables|Can Be Opened]]')
  end
end


  -- Check if the item is an entry requirement for any Slayer area
-- Check if the item is an entry requirement for any Slayer area
  local isSlayerAreaReq = false
local isSlayerAreaReq = false
  if item.isEquipment then
if item.isEquipment then
    local slayerAreas = Areas.getAreas(function(area) return area.type == 'slayer' end)
local slayerAreas = Areas.getAreas(function(area) return area.type == 'slayer' end)
    for i, area in pairs(slayerAreas) do
for i, area in pairs(slayerAreas) do
      if area.entryRequirements ~= nil and type(area.entryRequirements) == 'table' then
if area.entryRequirements ~= nil and type(area.entryRequirements) == 'table' then
        for j, req in pairs(area.entryRequirements) do
for j, req in pairs(area.entryRequirements) do
          if req.type == "SlayerItem" and req.itemID == item.id then
if req.type == "SlayerItem" and req.itemID == item.id then
            isSlayerAreaReq = true
isSlayerAreaReq = true
            break
break
          end
end
        end
end
        if isSlayerAreaReq then break end
if isSlayerAreaReq then break end
      end
end
    end
end
  end
end


  --Next, upgrading, crafting, herblore, fletching, and runecrafting since we have to sift through other items for these
--Next, upgrading, crafting, herblore, fletching, and runecrafting since we have to sift through other items for these
  local canUpgrade = false
local canUpgrade = false
  local canCraft = false
local canCraft = false
  local canFletch = false
local canFletch = false
  local canRunecraft = false
local canRunecraft = false
  local canHerblore = false
local canHerblore = false
  local canAgile = false
local canAgile = false
  local canSummon = false
local canSummon = false
  local canCook = false
local canCook = false


  if item.trimmedItemID ~= nil then
if item.trimmedItemID ~= nil then
    canUpgrade = true
canUpgrade = true
  end
end


  for i, item2 in pairs(ItemData.Items) do
for i, item2 in pairs(ItemData.Items) do
    if item2.itemsRequired ~= nil then
if item2.itemsRequired ~= nil then
      for j, req in pairs(item2.itemsRequired) do
for j, req in pairs(item2.itemsRequired) do
        if req[1] == item.id then
if req[1] == item.id then
          canUpgrade = true
canUpgrade = true
          break
break
        end
end
      end
end
    end
end


    if item2.craftReq ~= nil then
if item2.craftReq ~= nil then
      for j, req in pairs(item2.craftReq) do
for j, req in pairs(item2.craftReq) do
        if req.id == item.id then
if req.id == item.id then
          canCraft = true
canCraft = true
          break
break
        end
end
      end
end
    end
end
    if item2.fletchReq ~= nil then
if item2.fletchReq ~= nil then
      for j, req in pairs(item2.fletchReq) do
for j, req in pairs(item2.fletchReq) do
        if req.id == item.id then
if req.id == item.id then
          canFletch = true
canFletch = true
          break
break
        end
end
      end
end
    end
end
    if item2.runecraftReq ~= nil then
if item2.runecraftReq ~= nil then
      for j, req in pairs(item2.runecraftReq) do
for j, req in pairs(item2.runecraftReq) do
        if req.id == item.id then
if req.id == item.id then
          canRunecraft = true
canRunecraft = true
          break
break
        end
end
      end
end
    end
end


    if item2.herbloreReq ~= nil then
if item2.herbloreReq ~= nil then
      for j, req in pairs(item2.herbloreReq) do
for j, req in pairs(item2.herbloreReq) do
        if req.id == item.id then
if req.id == item.id then
          canHerblore = true
canHerblore = true
          break
break
        end
end
      end
end
    end
end


    if item2.summoningReq ~= nil then
if item2.summoningReq ~= nil then
      for j, reqSet in pairs(item2.summoningReq) do
for j, reqSet in pairs(item2.summoningReq) do
        for k, req in pairs(reqSet) do
for k, req in pairs(reqSet) do
          if req.id == item.id then
if req.id == item.id then
            canSummon = true
canSummon = true
            break
break
          end
end
        end
end
      end
end
    end
end
   
    --Handling for new Cooking method
--Handling for new Cooking method
    if item2.recipeRequirements ~= nil and item2.recipeRequirements[1] ~= nil then
if item2.recipeRequirements ~= nil and item2.recipeRequirements[1] ~= nil then
    for j, reqSet in pairs(item2.recipeRequirements) do
for j, reqSet in pairs(item2.recipeRequirements) do
    for k, req in pairs(reqSet) do
for k, req in pairs(reqSet) do
    if req.id == item.id then
if req.id == item.id then
    canCook = true
canCook = true
    break
break
    end
end
    end
end
    end
end
    end
end
  end
end


  --Check if Agility applies here
--Check if Agility applies here
  canAgile = Shared.tableCount(Agility.getObstaclesForItem(item.id)) > 0
canAgile = Shared.tableCount(Agility.getObstaclesForItem(item.id)) > 0


  --Agility
--Agility
  if canAgile or Shared.contains(itemUseArray.Agility, item.name) then
if canAgile or Shared.contains(itemUseArray.Agility, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Agility', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Agility', type='skill'}))
  end
end
  --Astrology
--Astrology
  if Shared.contains(itemUseArray.Astrology, item.name) then
if Shared.contains(itemUseArray.Astrology, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Astrology', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Astrology', type='skill'}))
  end
end
  --Cooking
--Cooking
  if canCook or Shared.contains(itemUseArray.Cooking, item.name) then
if canCook or Shared.contains(itemUseArray.Cooking, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Cooking', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Cooking', type='skill'}))
  end
end
  --Crafting
--Crafting
  if canCraft or Shared.contains(itemUseArray.Crafting, item.name) then
if canCraft or Shared.contains(itemUseArray.Crafting, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Crafting', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Crafting', type='skill'}))
  end
end
  --Farming
--Farming
  if item.grownItemID ~= nil or Shared.contains(itemUseArray.Farming, item.name) then
if item.grownItemID ~= nil or Shared.contains(itemUseArray.Farming, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Farming', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Farming', type='skill'}))
  end
end
  --Firemaking
--Firemaking
  if item.firemakingID ~= nil or Shared.contains(itemUseArray.Firemaking, item.name) then
if item.firemakingID ~= nil or Shared.contains(itemUseArray.Firemaking, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Firemaking', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Firemaking', type='skill'}))
  end
end
  --Fishing
--Fishing
  if Shared.contains(itemUseArray.Fishing, item.name) then
if Shared.contains(itemUseArray.Fishing, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Fishing', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Fishing', type='skill'}))
  end
end
  --Fletching
--Fletching
  if canFletch or Shared.contains(itemUseArray.Fletching, item.name) then
if canFletch or Shared.contains(itemUseArray.Fletching, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Fletching', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Fletching', type='skill'}))
  end
end
  --Herblore
--Herblore
  if canHerblore or Shared.contains(itemUseArray.Herblore, item.name) then
if canHerblore or Shared.contains(itemUseArray.Herblore, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Herblore', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Herblore', type='skill'}))
  end
end
  --Mining
--Mining
  if Shared.contains(itemUseArray.Mining, item.name) then
if Shared.contains(itemUseArray.Mining, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Mining', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Mining', type='skill'}))
  end
end
  --Prayer
--Prayer
  if item.prayerPoints ~= nil or (Shared.contains(itemUseArray.Prayer, item.name) and not Shared.contains(itemUseArray.Combat, item.name)) then
if item.prayerPoints ~= nil or (Shared.contains(itemUseArray.Prayer, item.name) and not Shared.contains(itemUseArray.Combat, item.name)) then
    if item.prayerPoints ~= nil then table.insert(categoryArray, '[[Category:Buriable Items]]') end
if item.prayerPoints ~= nil then table.insert(categoryArray, '[[Category:Buriable Items]]') end
    table.insert(useArray, chr..Icons.Icon({'Prayer', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Prayer', type='skill'}))
  end
end
  --Runecrafting
--Runecrafting
  if canRunecraft or Shared.contains(itemUseArray.Runecrafting, item.name) then
if canRunecraft or Shared.contains(itemUseArray.Runecrafting, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Runecrafting', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Runecrafting', type='skill'}))
  end
end
  --Slayer
--Slayer
  if isSlayerAreaReq or Shared.contains(itemUseArray.Slayer, item.name) then
if isSlayerAreaReq or Shared.contains(itemUseArray.Slayer, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Slayer', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Slayer', type='skill'}))
  end
end
  --Smithing
--Smithing
  if item.type == 'Bar' or item.type == 'Ore' or Shared.contains(itemUseArray.Smithing, item.name) then
if item.type == 'Bar' or item.type == 'Ore' or Shared.contains(itemUseArray.Smithing, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Smithing', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Smithing', type='skill'}))
  end
end
  --Summoning
--Summoning
  if canSummon or (item.type == 'Shard' and item.category == 'Summoning') or item.type == 'Familiar' or Shared.contains(itemUseArray.Summoning, item.name) then
if canSummon or (item.type == 'Shard' and item.category == 'Summoning') or item.type == 'Familiar' or Shared.contains(itemUseArray.Summoning, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Summoning', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Summoning', type='skill'}))
  end
end
  --Thieving
--Thieving
  if Shared.contains(itemUseArray.Thieving, item.name) then
if Shared.contains(itemUseArray.Thieving, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Thieving', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Thieving', type='skill'}))
  end
end
  --Woodcutting
--Woodcutting
  if Shared.contains(itemUseArray.Woodcutting, item.name) then
if Shared.contains(itemUseArray.Woodcutting, item.name) then
    table.insert(useArray, chr..Icons.Icon({'Woodcutting', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Woodcutting', type='skill'}))
  end
end


  --Other odds and ends:
--Other odds and ends:


  --Mastery Tokens are tied to 'Mastery'
--Mastery Tokens are tied to 'Mastery'
  if item.isToken and item.skill ~= nil then
if item.isToken and item.skill ~= nil then
    table.insert(useArray, chr..Icons.Icon({'Mastery'}))
table.insert(useArray, chr..Icons.Icon({'Mastery'}))
  end
end


  --Skillcapes are tied to the appropriate skill
--Skillcapes are tied to the appropriate skill
  --Except Maximum Skillcape, which is tied to all skills. (And so is the Signet Ring)
--Except Maximum Skillcape, which is tied to all skills. (And so is the Signet Ring)
  --And combat skillcapes, since combat skills don't get special treatment
--And combat skillcapes, since combat skills don't get special treatment


  local ignoreCapes = {'Ranged Skillcape', 'Attack Skillcape', 'Strength Skillcape', 'HP Skillcape', 'Defence Skillcape'}
local ignoreCapes = {'Ranged Skillcape', 'Attack Skillcape', 'Strength Skillcape', 'HP Skillcape', 'Defence Skillcape'}
  if Shared.contains({'Maximum Skillcape', 'Aorpheat's Signet Ring', 'Cape of Completion'}, item.name) then
if Shared.contains({'Maximum Skillcape', 'Aorpheat's Signet Ring', 'Cape of Completion'}, item.name) then
    table.insert(useArray, chr..'All skills')
table.insert(useArray, chr..'All skills')
  elseif item.name == 'Magic Skillcape' then
elseif item.name == 'Magic Skillcape' then
    table.insert(useArray, chr..Icons.Icon({'Magic', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Magic', type='skill'}))
    table.insert(useArray, chr..Icons.Icon({'Alt. Magic', type='skill'}))
table.insert(useArray, chr..Icons.Icon({'Alt. Magic', type='skill'}))
  elseif Shared.contains(item.name, 'Skillcape') and not Shared.contains(ignoreCapes, item.name) then
elseif Shared.contains(item.name, 'Skillcape') and not Shared.contains(ignoreCapes, item.name) then
    local skillName = Shared.splitString(item.name, ' ')[1]
local skillName = Shared.splitString(item.name, ' ')[1]
    --Avoiding double-listing the same skill twice
--Avoiding double-listing the same skill twice
    if not Shared.contains(itemUseArray[skillName], item.name) then
if not Shared.contains(itemUseArray[skillName], item.name) then
      table.insert(useArray, chr..Icons.Icon({skillName, type='skill'}))
table.insert(useArray, chr..Icons.Icon({skillName, type='skill'}))
    end
end
  end
end


  if Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion' then table.insert(categoryArray, '[[Category:Skillcapes]]') end
if Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion' then table.insert(categoryArray, '[[Category:Skillcapes]]') end


  --Special note for Charge Stone of Rhaelyx
--Special note for Charge Stone of Rhaelyx
  if item.name == 'Charge Stone of Rhaelyx' then
if item.name == 'Charge Stone of Rhaelyx' then
    table.insert(useArray, chr..'Powering '..Icons.Icon({'Crown of Rhaelyx', type='item'}))
table.insert(useArray, chr..'Powering '..Icons.Icon({'Crown of Rhaelyx', type='item'}))
  end
end


  --Some items are needed to make shop purchases
--Some items are needed to make shop purchases
  local shopArray = Shop.getItemCostArray(item.id)
local shopArray = Shop.getItemCostArray(item.id)
  if Shared.tableCount(shopArray) > 0 then
if Shared.tableCount(shopArray) > 0 then
    table.insert(useArray, chr..Icons.Icon({'Shop'}))
table.insert(useArray, chr..Icons.Icon({'Shop'}))
  end
end


  if canUpgrade then
if canUpgrade then
    if item.canUpgrade or (item.type == 'Armour' and item.canUpgrade == nil) then
if item.canUpgrade or (item.type == 'Armour' and item.canUpgrade == nil) then
      table.insert(categoryArray, '[[Category:Upgradeable Items]]')
table.insert(categoryArray, '[[Category:Upgradeable Items]]')
    end
end
    table.insert(useArray, chr..'[[Upgrading Items]]')
table.insert(useArray, chr..'[[Upgrading Items]]')
  end
end


  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, asList and table.concat(useArray,'\r\n') or table.concat(useArray, '<br/>'))
table.insert(resultPart, asList and table.concat(useArray,'\r\n') or table.concat(useArray, '<br/>'))
  if addCategories then table.insert(resultPart, table.concat(categoryArray, '')) end
if addCategories then table.insert(resultPart, table.concat(categoryArray, '')) end
  return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.getItemUses(frame)
function p.getItemUses(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 = Items.getItem(itemName)
local item = Items.getItem(itemName)
  local addCategories = false
local addCategories = false
  local asList = true
local asList = true
  if frame.args ~= nil then
if frame.args ~= nil then
    addCategories = frame.args.addCategories ~= nil and frame.args.addCategories ~= '' and frame.args.addCategories ~= 'false'
addCategories = frame.args.addCategories ~= nil and frame.args.addCategories ~= '' and frame.args.addCategories ~= 'false'
    asList = frame.args.addCategories == nil or frame.args.addCategories == '' or frame.args.addCategories == 'true'
asList = frame.args.addCategories == nil or frame.args.addCategories == '' or frame.args.addCategories == 'true'
  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"
  end
end


  return p._getItemUses(item, asList, addCategories)
return p._getItemUses(item, asList, addCategories)
end
end


function p._getItemUseTable(item)
function p._getItemUseTable(item)
  local useArray = {}
local useArray = {}
  local potTierMastery = {[0] = 0, [1] = 20, [2] = 50, [3] = 90}
local potTierMastery = {[0] = 0, [1] = 20, [2] = 50, [3] = 90}


  --First, loop through all items to find anything that can be made or upgraded into using our source
--First, loop through all items to find anything that can be made or upgraded into using our source
  for i, item2 in pairs(ItemData.Items) do
for i, item2 in pairs(ItemData.Items) do
    if item2.itemsRequired ~= nil then
if item2.itemsRequired ~= nil then
      for j, req in pairs(item2.itemsRequired) do
for j, req in pairs(item2.itemsRequired) do
        if req[1] == item.id then
if req[1] == item.id then
          local mat = item2.itemsRequired
local mat = item2.itemsRequired
          local xp = 'N/A'
local xp = 'N/A'
          local rowReq = 'None'
local rowReq = 'None'
          --Potions do have upgrade requirements though
--Potions do have upgrade requirements though
          if item2.potionTier ~= nil then
if item2.potionTier ~= nil then
            rowReq = Icons._MasteryReq(item2.name, potTierMastery[item2.potionTier])
rowReq = Icons._MasteryReq(item2.name, potTierMastery[item2.potionTier])
          end
end
          table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Upgrade', req = rowReq, xp = xp, gp = item2.trimmedGPCost})
table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Upgrade', req = rowReq, xp = xp, gp = item2.trimmedGPCost})
          break
break
        end
end
      end
end
    end
end
    if item2.craftReq ~= nil then
if item2.craftReq ~= nil then
      for j, req in pairs(item2.craftReq) do
for j, req in pairs(item2.craftReq) do
        if req.id == item.id then
if req.id == item.id then
          local mat = item2.craftReq
local mat = item2.craftReq
          local xp = item2.craftingXP
local xp = item2.craftingXP
          local rowReq = item2.craftingLevel
local rowReq = item2.craftingLevel
          local qty = item2.craftQty
local qty = item2.craftQty
          table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Crafting', req = rowReq, xp = xp, gp = item2.craftGPCost})
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Crafting', req = rowReq, xp = xp, gp = item2.craftGPCost})
          break
break
        end
end
      end
end
    end
end
    if item2.fletchReq ~= nil then
if item2.fletchReq ~= nil then
      for j, req in pairs(item2.fletchReq) do
for j, req in pairs(item2.fletchReq) do
        if req.id == item.id then
if req.id == item.id then
          local xp = item2.fletchingXP
local xp = item2.fletchingXP
          local rowReq = item2.fletchingLevel
local rowReq = item2.fletchingLevel
          --Arrow Shafts are special and have to be treated specially
--Arrow Shafts are special and have to be treated specially
          local qty = item2.fletchQty
local qty = item2.fletchQty
          local mat = item2.fletchReq
local mat = item2.fletchReq
          if item2.name == 'Arrow Shafts' then
if item2.name == 'Arrow Shafts' then
            mat = {{id = item.id, qty = 1}}
mat = {{id = item.id, qty = 1}}
            qty =  qty + (qty * item.id)
qty =  qty + (qty * item.id)
          end
end
          table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Fletching', req = rowReq, xp = xp})
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Fletching', req = rowReq, xp = xp})
          break
break
        end
end
      end
end
    end
end
    if item2.smithReq ~= nil then
if item2.smithReq ~= nil then
      for j, req in pairs(item2.smithReq) do
for j, req in pairs(item2.smithReq) do
        if req.id == item.id then
if req.id == item.id then
          local mat = item2.smithReq
local mat = item2.smithReq
          local xp = item2.smithingXP
local xp = item2.smithingXP
          local rowReq = item2.smithingLevel
local rowReq = item2.smithingLevel
          local qty = item2.smithingQty
local qty = item2.smithingQty
          table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Smithing', req = rowReq, xp = xp})
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Smithing', req = rowReq, xp = xp})
          break
break
        end
end
      end
end
    end
end
    --Handling for new Cooking method
--Handling for new Cooking method
    if item2.recipeRequirements ~= nil then
if item2.recipeRequirements ~= nil then
    for j, reqSet in pairs(item2.recipeRequirements) do
for j, reqSet in pairs(item2.recipeRequirements) do
    for k, req in pairs(reqSet) do
for k, req in pairs(reqSet) do
    if req.id == item.id then
if req.id == item.id then
    local mat = reqSet
local mat = reqSet
    local xp = item2.cookingXP
local xp = item2.cookingXP
    local rowReq = item2.cookingLevel
local rowReq = item2.cookingLevel
    local qty = item2.cookingQty
local qty = item2.cookingQty
    table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})
   
    if item2.perfectItem ~= nil then
if item2.perfectItem ~= nil then
    local perfectItem = Items.getItemByID(item2.perfectItem)
local perfectItem = Items.getItemByID(item2.perfectItem)
    table.insert(useArray, {item = perfectItem, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})
table.insert(useArray, {item = perfectItem, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})
    end
end
    end
end
    end
end
    end
end
    end
end
    if item2.runecraftReq ~= nil then
if item2.runecraftReq ~= nil then
      for j, req in pairs(item2.runecraftReq) do
for j, req in pairs(item2.runecraftReq) do
        if req.id == item.id then
if req.id == item.id then
          local mat = item2.runecraftReq
local mat = item2.runecraftReq
          local xp = item2.runecraftingXP
local xp = item2.runecraftingXP
          local rowReq = item2.runecraftingLevel
local rowReq = item2.runecraftingLevel
          local qty = item2.runecraftQty
local qty = item2.runecraftQty
          table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Runecrafting', req = rowReq, xp = xp})
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Runecrafting', req = rowReq, xp = xp})
          break
break
        end
end
      end
end
    end
end
    if item2.herbloreReq ~= nil then
if item2.herbloreReq ~= nil then
      for j, req in pairs(item2.herbloreReq) do
for j, req in pairs(item2.herbloreReq) do
        if req.id == item.id then
if req.id == item.id then
          local potionData = SkillData.Herblore.ItemData[item2.masteryID[2] + 1]
local potionData = SkillData.Herblore.ItemData[item2.masteryID[2] + 1]
          local mat = item2.herbloreReq
local mat = item2.herbloreReq
          local xp = potionData.herbloreXP
local xp = potionData.herbloreXP
          --Potions do have upgrade requirements though
--Potions do have upgrade requirements though
          local rowReq = Icons._SkillReq('Herblore', potionData.level)
local rowReq = Icons._SkillReq('Herblore', potionData.level)
          local masteryLvl = potTierMastery[item2.potionTier]
local masteryLvl = potTierMastery[item2.potionTier]
          if masteryLvl > 0 then
if masteryLvl > 0 then
            rowReq = rowReq..'<br/>'..Icons._MasteryReq(item2.name, masteryLvl)
rowReq = rowReq..'<br/>'..Icons._MasteryReq(item2.name, masteryLvl)
          end
end
          local reqVal = potionData.level + (masteryLvl * 0.01)
local reqVal = potionData.level + (masteryLvl * 0.01)
          table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Herblore', reqVal = reqVal, req = rowReq, xp = xp})
table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Herblore', reqVal = reqVal, req = rowReq, xp = xp})
          break
break
        end
end
      end
end
    end
end


    if item2.summoningReq ~= nil then
if item2.summoningReq ~= nil then
      for j, reqSet in pairs(item2.summoningReq) do
for j, reqSet in pairs(item2.summoningReq) do
        for k, req in pairs(reqSet) do
for k, req in pairs(reqSet) do
          if req.id == item.id then
if req.id == item.id then
            local mat = Shared.clone(reqSet)
local mat = Shared.clone(reqSet)
            mat[k].qty = math.max(math.floor(1000 / math.max(item.sellsFor, 20)), 1)
mat[k].qty = math.max(math.floor(1000 / math.max(item.sellsFor, 20)), 1)
            local xp = 5 + 2 * math.floor(item2.summoningLevel * 0.2)
local xp = 5 + 2 * math.floor(item2.summoningLevel * 0.2)
            local rowReq = item2.summoningLevel
local rowReq = item2.summoningLevel
            table.insert(useArray, {item = item2, qty = 25, mats = mat, skill = 'Summoning', req = rowReq, xp = xp})
table.insert(useArray, {item = item2, qty = 25, mats = mat, skill = 'Summoning', req = rowReq, xp = xp})
          end
end
        end
end
      end
end
    end
end
  end
end
  if item.grownItemID ~= nil then
if item.grownItemID ~= nil then
    local item2 = Items.getItemByID(item.grownItemID)
local item2 = Items.getItemByID(item.grownItemID)
    local mat = {{id = item.id, qty = item.seedsRequired}}
local mat = {{id = item.id, qty = item.seedsRequired}}
    local xp = item.farmingXP
local xp = item.farmingXP
    local rowReq = item.farmingLevel
local rowReq = item.farmingLevel
    local qty = (item.tier ~= nil and item.tier == 'Tree' and 35 or 15)
local qty = (item.tier ~= nil and item.tier == 'Tree' and 35 or 15)
    table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Farming', req = rowReq, xp = xp})
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Farming', req = rowReq, xp = xp})
  end
end


  --Handle shop purchases using Module:Shop
--Handle shop purchases using Module:Shop
  local shopUses = Shop.getItemCostArray(item.id)
local shopUses = Shop.getItemCostArray(item.id)
  for i, purchase in Shared.skpairs(shopUses) do
for i, purchase in Shared.skpairs(shopUses) do
    local rowReq = Shop.getRequirementString(purchase.unlockRequirements)
local rowReq = Shop.getRequirementString(purchase.unlockRequirements)
    local iconType = (purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0) and 'item' or 'upgrade'
local iconType = (purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0) and 'item' or 'upgrade'
    table.insert(useArray, {item = {name = purchase.name}, qty = 1, mats = purchase.cost.items, skill = 'Shop', req = rowReq, xp = 'N/A', gp = purchase.cost.gp, type = iconType})
table.insert(useArray, {item = {name = purchase.name}, qty = 1, mats = purchase.cost.items, skill = 'Shop', req = rowReq, xp = 'N/A', gp = purchase.cost.gp, type = iconType})
  end
end


  --Finally build the table using what we've learned
--Finally build the table using what we've learned
  table.sort(useArray, function(a, b)
table.sort(useArray, function(a, b)
                        local aReqVal = a.reqVal ~= nil and a.reqVal or a.req
          local aReqVal = a.reqVal ~= nil and a.reqVal or a.req
                        local bReqVal = b.reqVal ~= nil and b.reqVal or b.req
          local bReqVal = b.reqVal ~= nil and b.reqVal or b.req
                        if a.skill ~= b.skill then
          if a.skill ~= b.skill then
                          return a.skill < b.skill
            return a.skill < b.skill
                        elseif type(aReqVal) ~= type(bReqVal) then
          elseif type(aReqVal) ~= type(bReqVal) then
                          return tostring(aReqVal) < tostring(bReqVal)
            return tostring(aReqVal) < tostring(bReqVal)
                        elseif aReqVal ~= bReqVal then
          elseif aReqVal ~= bReqVal then
                          return aReqVal < bReqVal
            return aReqVal < bReqVal
                        else
          else
                          return a.item.name < b.item.name
            return a.item.name < b.item.name
                        end end)
          end end)


  local obstacles = Agility.getObstaclesForItem(item.id)
local obstacles = Agility.getObstaclesForItem(item.id)


  local spellUseTable = p._getSpellUseTable(item)
local spellUseTable = p._getSpellUseTable(item)
  local resultPart = {}
local resultPart = {}
  if Shared.tableCount(useArray) == 0 and Shared.tableCount(obstacles) == 0 then
if Shared.tableCount(useArray) == 0 and Shared.tableCount(obstacles) == 0 then
    if string.len(spellUseTable) > 0 then
if string.len(spellUseTable) > 0 then
      return '==Uses==\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable
return '==Uses==\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable
    else
else
      return ''
return ''
    end
end
  end
end
  table.insert(resultPart, '{| class="wikitable sortable"')
table.insert(resultPart, '{| class="wikitable sortable"')
  table.insert(resultPart, '\r\n!colspan=2|Item Created!!Type!!Requirements!!XP!!Ingredients')
table.insert(resultPart, '\r\n!colspan=2|Item Created!!Type!!Requirements!!XP!!Ingredients')
  for i, row in pairs(useArray) do
for i, row in pairs(useArray) do
    local qty = row.qty ~= nil and row.qty or 1
local qty = row.qty ~= nil and row.qty or 1
    local iconType = row.type ~= nil and row.type or 'item'
local iconType = row.type ~= nil and row.type or 'item'
    table.insert(resultPart, '\r\n|-\r\n|data-sort-value="'..row.item.name..'"|')
table.insert(resultPart, '\r\n|-\r\n|data-sort-value="'..row.item.name..'"|')
    table.insert(resultPart, Icons.Icon({row.item.name, type=iconType, notext=true, size=50})..'||')
table.insert(resultPart, Icons.Icon({row.item.name, type=iconType, notext=true, size=50})..'||')
    if qty > 1 then table.insert(resultPart, "'''"..qty.."x''' ") end
if qty > 1 then table.insert(resultPart, "'''"..qty.."x''' ") end
    table.insert(resultPart, Icons.Icon({row.item.name, type='item', noicon=true}))
table.insert(resultPart, Icons.Icon({row.item.name, type='item', noicon=true}))
    if row.skill == 'Upgrade' then
if row.skill == 'Upgrade' then
      table.insert(resultPart, '||data-sort-value="Upgrade"|[[Upgrading Items|Upgrade]]')
table.insert(resultPart, '||data-sort-value="Upgrade"|[[Upgrading Items|Upgrade]]')
    elseif row.skill == 'Shop' then
elseif row.skill == 'Shop' then
      table.insert(resultPart, '||data-sort-value="Shop"|'..Icons.Icon({'Shop'}))
table.insert(resultPart, '||data-sort-value="Shop"|'..Icons.Icon({'Shop'}))
    else
else
      table.insert(resultPart, '||data-sort-value="'..row.skill..'"|'..Icons.Icon({row.skill, type='skill'}))
table.insert(resultPart, '||data-sort-value="'..row.skill..'"|'..Icons.Icon({row.skill, type='skill'}))
    end
end
    if type(row.req) == 'number' then
if type(row.req) == 'number' then
      table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.req..'"|'..Icons._SkillReq(row.skill, row.req))
table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.req..'"|'..Icons._SkillReq(row.skill, row.req))
    elseif row.reqVal ~= nil then
elseif row.reqVal ~= nil then
      table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.reqVal..'"|'..row.req)
table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.reqVal..'"|'..row.req)
    else
else
      table.insert(resultPart, '||'..row.req)
table.insert(resultPart, '||'..row.req)
    end
end
    if type(row.xp) == 'string' then
if type(row.xp) == 'string' then
      table.insert(resultPart, '||style="text-align:right" data-sort-value="0"|'..row.xp)
table.insert(resultPart, '||style="text-align:right" data-sort-value="0"|'..row.xp)
    else
else
      table.insert(resultPart, '||style="text-align:right" data-sort-value="'..row.xp..'"|'..row.xp..' '..Icons.Icon({row.skill, type='skill', notext=true})..' XP')
table.insert(resultPart, '||style="text-align:right" data-sort-value="'..row.xp..'"|'..row.xp..' '..Icons.Icon({row.skill, type='skill', notext=true})..' XP')
    end
end
    table.insert(resultPart, '||')
table.insert(resultPart, '||')
    for i, mat in Shared.skpairs(row.mats) do
for i, mat in Shared.skpairs(row.mats) do
      local matID = mat.id ~= nil and mat.id or mat[1]
local matID = mat.id ~= nil and mat.id or mat[1]
      local matQty = mat.qty ~= nil and mat.qty or mat[2]
local matQty = mat.qty ~= nil and mat.qty or mat[2]
      local matText = ''
local matText = ''


      if i > 1 then table.insert(resultPart, '<br/>') end
if i > 1 then table.insert(resultPart, '<br/>') end
      if matID >= 0 then
if matID >= 0 then
        -- Item
-- Item
        local matItem = Items.getItemByID(matID)
local matItem = Items.getItemByID(matID)
        if matItem == nil then
if matItem == nil then
          matText = 'ERROR: Failed to find item with ID ' .. matID .. '[[Category:Pages with Script Errors]]'
matText = 'ERROR: Failed to find item with ID ' .. matID .. '[[Category:Pages with Script Errors]]'
        else
else
          matText = Icons.Icon({matItem.name, type='item', qty=matQty})
matText = Icons.Icon({matItem.name, type='item', qty=matQty})
        end
end
      elseif matID == -4 then
elseif matID == -4 then
        -- GP
-- GP
        matText = Icons.GP(SkillData.Summoning.Settings.recipeGPCost)
matText = Icons.GP(SkillData.Summoning.Settings.recipeGPCost)
      elseif matID == -5 then
elseif matID == -5 then
        -- Slayer Coins
-- Slayer Coins
        matText = Icons.SC(SkillData.Summoning.Settings.recipeGPCost)
matText = Icons.SC(SkillData.Summoning.Settings.recipeGPCost)
      else
else
        matText = 'ERROR: Unknown item ID: ' .. matID .. ' [[Category:Pages with Script Errors]]'
matText = 'ERROR: Unknown item ID: ' .. matID .. ' [[Category:Pages with Script Errors]]'
      end
end
      table.insert(resultPart, matText)
table.insert(resultPart, matText)
    end
end
    if row.gp ~= nil then table.insert(resultPart, '<br/>'..Icons.GP(row.gp)) end
if row.gp ~= nil then table.insert(resultPart, '<br/>'..Icons.GP(row.gp)) end
  end
end


  --Agility obstacles are weird and get their own section
--Agility obstacles are weird and get their own section
  for i, obst in Shared.skpairs(obstacles) do
for i, obst in Shared.skpairs(obstacles) do
    table.insert(resultPart, '\r\n|-\r\n|')
table.insert(resultPart, '\r\n|-\r\n|')
    table.insert(resultPart, Icons.Icon({"Agility", type="skill", size="50", notext=true}))
table.insert(resultPart, Icons.Icon({"Agility", type="skill", size="50", notext=true}))
    table.insert(resultPart, '||[[Agility#Obstacles|'..obst.name..']]')
table.insert(resultPart, '||[[Agility#Obstacles|'..obst.name..']]')
    table.insert(resultPart, '||'..Icons.Icon({"Agility", type="skill"}))
table.insert(resultPart, '||'..Icons.Icon({"Agility", type="skill"}))


    --Adding the requirements for the Agility Obstacle
--Adding the requirements for the Agility Obstacle
    local reqArray = {}
local reqArray = {}
    if obst.category == nil then --nil category means this is a passive pillar
if obst.category == nil then --nil category means this is a passive pillar
      table.insert(reqArray, Icons._SkillReq('Agility', 99))
table.insert(reqArray, Icons._SkillReq('Agility', 99))
    elseif obst.category > 0 then --Otherwise it's category * 10
elseif obst.category > 0 then --Otherwise it's category * 10
      table.insert(reqArray, Icons._SkillReq('Agility', obst.category * 10))
table.insert(reqArray, Icons._SkillReq('Agility', obst.category * 10))
    end
end
    --Then the other skill levels if any are added
--Then the other skill levels if any are added
    if obst.requirements ~= nil and obst.requirements.skillLevel ~= nil then
if obst.requirements ~= nil and obst.requirements.skillLevel ~= nil then
      for j, req in Shared.skpairs(obst.requirements.skillLevel) do
for j, req in Shared.skpairs(obst.requirements.skillLevel) do
        table.insert(reqArray, Icons._SkillReq(Constants.getSkillName(req[1]), req[2]))
table.insert(reqArray, Icons._SkillReq(Constants.getSkillName(req[1]), req[2]))
      end
end
    end
end
    table.insert(resultPart, '||style="text-align:right"|'..table.concat(reqArray, '<br/>'))
table.insert(resultPart, '||style="text-align:right"|'..table.concat(reqArray, '<br/>'))


    --Just including 'N/A' for XP since it doesn't really apply for Agility Obstacles
--Just including 'N/A' for XP since it doesn't really apply for Agility Obstacles
    table.insert(resultPart, '||style="text-align:right"|N/A')
table.insert(resultPart, '||style="text-align:right"|N/A')


    --Finally the cost
--Finally the cost
    local cost = obst.cost
local cost = obst.cost
    local costArray = {}
local costArray = {}
    if cost.gp ~= nil and cost.gp > 0 then
if cost.gp ~= nil and cost.gp > 0 then
      table.insert(costArray, Icons.GP(cost.gp))
table.insert(costArray, Icons.GP(cost.gp))
    end
end
    if cost.slayerCoins ~= nil and cost.slayerCoins > 0 then
if cost.slayerCoins ~= nil and cost.slayerCoins > 0 then
      table.insert(costArray, Icons.SC(cost.slayerCoins))
table.insert(costArray, Icons.SC(cost.slayerCoins))
    end
end
    for j, mat in Shared.skpairs(cost.items) do
for j, mat in Shared.skpairs(cost.items) do
      local item = Items.getItemByID(mat[1])
local item = Items.getItemByID(mat[1])
      table.insert(costArray, Icons.Icon({item.name, type="item", qty=mat[2]}))
table.insert(costArray, Icons.Icon({item.name, type="item", qty=mat[2]}))
    end
end


    table.insert(resultPart, '||'..table.concat(costArray, '<br/>'))
table.insert(resultPart, '||'..table.concat(costArray, '<br/>'))


  end
end


  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')
  if string.len(spellUseTable) > 0 then
if string.len(spellUseTable) > 0 then
    table.insert(resultPart, '\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable)
table.insert(resultPart, '\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable)
  end
end
  return '==Uses==\r\n'..table.concat(resultPart)
return '==Uses==\r\n'..table.concat(resultPart)
end
end


function p.getItemUseTable(frame)
function p.getItemUseTable(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 = Items.getItem(itemName)
local item = Items.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"
  end
end


  return p._getItemUseTable(item)
return p._getItemUseTable(item)
end
end


function p._getSpellUseTable(item)
function p._getSpellUseTable(item)
  local spellList = Magic.getSpellsForRune(item.id)
local spellList = Magic.getSpellsForRune(item.id)
  --Bail immediately if no spells are found
--Bail immediately if no spells are found
  if Shared.tableCount(spellList) == 0 then
if Shared.tableCount(spellList) == 0 then
    return ''
return ''
  end
end


  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{|class="wikitable sortable"\r\n!colspan="2"|Spell')
table.insert(resultPart, '{|class="wikitable sortable"\r\n!colspan="2"|Spell')
  table.insert(resultPart, '!!Requirements')
table.insert(resultPart, '!!Requirements')
  table.insert(resultPart, '!!Type!!style="width:275px"|Description')
table.insert(resultPart, '!!Type!!style="width:275px"|Description')
  table.insert(resultPart, '!!Runes')
table.insert(resultPart, '!!Runes')
  for i, spell in pairs(spellList) do
for i, spell in pairs(spellList) do
    local rowPart = {}
local rowPart = {}
    table.insert(rowPart, '\r\n|-\r\n|data-sort-value="'..spell.name..'"|')
table.insert(rowPart, '\r\n|-\r\n|data-sort-value="'..spell.name..'"|')
    local iconType = (spell.type == 'Auroras' and 'aurora') or (spell.type == 'Curses' and 'curse') or 'spell'
local iconType = (spell.type == 'Auroras' and 'aurora') or (spell.type == 'Curses' and 'curse') or 'spell'
    table.insert(rowPart, Icons.Icon({spell.name, type=iconType, notext=true, size=50}))
table.insert(rowPart, Icons.Icon({spell.name, type=iconType, notext=true, size=50}))
    table.insert(rowPart, '||'..Icons.Icon({spell.name, type=iconType, noicon=true}))
table.insert(rowPart, '||'..Icons.Icon({spell.name, type=iconType, noicon=true}))
    table.insert(rowPart, '||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level))
table.insert(rowPart, '||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level))
    --Handle required items/dungeon clears
--Handle required items/dungeon clears
    if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
      local reqItem = Items.getItemByID(spell.requiredItem)
local reqItem = Items.getItemByID(spell.requiredItem)
      table.insert(rowPart, '<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped')
table.insert(rowPart, '<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped')
    end
end
    if spell.requiredDungeonCompletion ~= nil then
if spell.requiredDungeonCompletion ~= nil then
      local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
      table.insert(rowPart, '<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears')
table.insert(rowPart, '<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears')
    end
end
    table.insert(rowPart, '||data-sort-value="'..Magic.getSpellTypeIndex(spell.type)..'"|')
table.insert(rowPart, '||data-sort-value="'..Magic.getSpellTypeIndex(spell.type)..'"|')
    table.insert(rowPart, Magic.getSpellTypeLink(spell.type))
table.insert(rowPart, Magic.getSpellTypeLink(spell.type))
    table.insert(rowPart, '||'..Magic._getSpellStat(spell, 'description'))
table.insert(rowPart, '||'..Magic._getSpellStat(spell, 'description'))
    table.insert(rowPart, '||style="text-align:center"|')
table.insert(rowPart, '||style="text-align:center"|')
    table.insert(rowPart, Magic._getSpellRunes(spell))
table.insert(rowPart, Magic._getSpellRunes(spell))
    table.insert(resultPart, table.concat(rowPart))
table.insert(resultPart, table.concat(rowPart))
  end
end
  --Add the table end and add the table to the result string
--Add the table end and add the table to the result string
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')
  return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.getSpellUseTable(frame)
function p.getSpellUseTable(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 = Items.getItem(itemName)
local item = Items.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"
  end
end


  return p._getSpellUseTable(item)
return p._getSpellUseTable(item)
end
end


return p
return p

Revision as of 19:16, 8 December 2021

Documentation for this module may be created at Module:Items/UseTables/doc

local p = {}

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

local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Magic = require('Module:Magic')
local Areas = require('Module:CombatAreas')
local Items = require('Module:Items')
local Icons = require('Module:Icons')
local Agility = require('Module:Skills/Agility')
local Shop = require('Module:Shop')


--Brute forcing some item uses to make things easier
local itemUseArray = {
	Agility = {},
	Astrology = {'Stardust', 'Golden Stardust'},
	Attack = {},
	Combat = {'Gold Emerald Ring'},
	Cooking = {'Cooking Gloves', 'Crown of Rhaelyx'},
	Crafting = {'Crown of Rhaelyx'},
	Defence = {},
	Farming = {'Compost', 'Weird Gloop', 'Bob&apos;s Rake'},
	Firemaking = {'Crown of Rhaelyx'},
	Fishing = {'Amulet of Fishing', 'Message in a Bottle'},
	Fletching = {'Crown of Rhaelyx'},
	Herblore = {'Crown of Rhaelyx'},
	Hitpoints = {},
	Magic = {},
	Mining = {'Mining Gloves', 'Gem Gloves'},
	Prayer = {},
	Ranged = {},
	Runecrafting = {'Crown of Rhaelyx'},
	Slayer = {},
	Smithing = {'Smithing Gloves', 'Crown of Rhaelyx'},
	Strength = {},
	Summoning = {'Crown of Rhaelyx'},
	Thieving = {'Chapeau Noir', 'Thieving Gloves', 'Gloves of Silence'},
	Woodcutting = {},
	}
local potionUseArray = {
	[0] = 'Combat',
	[1] = 'Combat',
	[2] = 'Combat',
	[3] = 'Combat',
	[4] = 'Combat',
	[5] = 'Combat',
	[6] = 'Combat',
	[7] = 'Woodcutting',
	[8] = 'Fishing',
	[9] = 'Firemaking',
	[10] = 'Cooking',
	[11] = 'Mining',
	[12] = 'Smithing',
	[13] = 'Thieving',
	[14] = 'Farming',
	[15] = 'Fletching',
	[16] = 'Crafting',
	[17] = 'Runecrafting',
	[18] = 'Herblore',
	[19] = 'Combat',
	[20] = 'Combat',
	[21] = 'Combat',
	[22] = 'Combat',
	[23] = 'Combat',
	[24] = 'Agility',
	[25] = 'Summoning',
	[26] = 'Combat',
	[27] = 'Combat',
	[28] = 'Combat',
	[29] = 'Astrology'
}

function p._getItemUses(item, asList, addCategories)
	local useArray = {}
	local categoryArray = {}
	local chr = asList and '* ' or ''
	--Another fun one. This time getting all the different possible ways an item can be used

	--Before anything else, if this is a potion add it to the appropriate override section
	if item.masteryID ~= nil and item.masteryID[1] == 19 then
		if potionUseArray[item.masteryID[2]] ~= nil then
			table.insert(itemUseArray[potionUseArray[item.masteryID[2]]], item.name)
		else
			table.insert(itemUseArray["Combat"], item.name)
		end
	end

	--If the item has any modifiers that affect a given skill, add it to those lists
	--Added an exception for Mastery Tokens since they were being incorrectly flagged as usable for all skills
	if item.modifiers ~= nil and (item.isToken == nil or not item.isToken) then
		local skillArray = Constants.getModifierSkills(item.modifiers)
		for i, skillName in Shared.skpairs(skillArray) do
			table.insert(itemUseArray[skillName], item.name)
		end
	end

	--First things added to the list are non-skill things that are easy to check
	if Items.hasCombatStats(item) or item.specialAttacks ~= nil or Shared.contains(itemUseArray.Combat, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Combat'}))
	end

	if item.healsFor ~= nil then
		table.insert(categoryArray, '[[Category:Food Items]]')
		table.insert(useArray, chr..'[[Food]]')
	end

	if item.dropTable ~= nil then
		table.insert(categoryArray, '[[Category:Openable Items]]')
		table.insert(useArray, chr..'[[Chest Drop Tables|Can Be Opened]]')
	end

	-- Check if the item is an entry requirement for any Slayer area
	local isSlayerAreaReq = false
	if item.isEquipment then
		local slayerAreas = Areas.getAreas(function(area) return area.type == 'slayer' end)
		for i, area in pairs(slayerAreas) do
			if area.entryRequirements ~= nil and type(area.entryRequirements) == 'table' then
				for j, req in pairs(area.entryRequirements) do
					if req.type == "SlayerItem" and req.itemID == item.id then
						isSlayerAreaReq = true
						break
					end
				end
				if isSlayerAreaReq then break end
			end
		end
	end

	--Next, upgrading, crafting, herblore, fletching, and runecrafting since we have to sift through other items for these
	local canUpgrade = false
	local canCraft = false
	local canFletch = false
	local canRunecraft = false
	local canHerblore = false
	local canAgile = false
	local canSummon = false
	local canCook = false

	if item.trimmedItemID ~= nil then
		canUpgrade = true
	end

	for i, item2 in pairs(ItemData.Items) do
		if item2.itemsRequired ~= nil then
			for j, req in pairs(item2.itemsRequired) do
				if req[1] == item.id then
					canUpgrade = true
					break
				end
			end
		end

		if item2.craftReq ~= nil then
			for j, req in pairs(item2.craftReq) do
				if req.id == item.id then
					canCraft = true
					break
				end
			end
		end
		if item2.fletchReq ~= nil then
			for j, req in pairs(item2.fletchReq) do
				if req.id == item.id then
					canFletch = true
					break
				end
			end
		end
		if item2.runecraftReq ~= nil then
			for j, req in pairs(item2.runecraftReq) do
				if req.id == item.id then
					canRunecraft = true
					break
				end
			end
		end

		if item2.herbloreReq ~= nil then
			for j, req in pairs(item2.herbloreReq) do
				if req.id == item.id then
					canHerblore = true
					break
				end
			end
		end

		if item2.summoningReq ~= nil then
			for j, reqSet in pairs(item2.summoningReq) do
				for k, req in pairs(reqSet) do
					if req.id == item.id then
						canSummon = true
						break
					end
				end
			end
		end
		
		--Handling for new Cooking method
		if item2.recipeRequirements ~= nil and item2.recipeRequirements[1] ~= nil then
			for j, reqSet in pairs(item2.recipeRequirements) do
				for k, req in pairs(reqSet) do
					if req.id == item.id then
						canCook = true
						break
					end
				end
			end
		end
	end

	--Check if Agility applies here
	canAgile = Shared.tableCount(Agility.getObstaclesForItem(item.id)) > 0

	--Agility
	if canAgile or Shared.contains(itemUseArray.Agility, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Agility', type='skill'}))
	end
	--Astrology
	if Shared.contains(itemUseArray.Astrology, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Astrology', type='skill'}))
	end
	--Cooking
	if canCook or Shared.contains(itemUseArray.Cooking, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Cooking', type='skill'}))
	end
	--Crafting
	if canCraft or Shared.contains(itemUseArray.Crafting, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Crafting', type='skill'}))
	end
	--Farming
	if item.grownItemID ~= nil or Shared.contains(itemUseArray.Farming, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Farming', type='skill'}))
	end
	--Firemaking
	if item.firemakingID ~= nil or Shared.contains(itemUseArray.Firemaking, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Firemaking', type='skill'}))
	end
	--Fishing
	if Shared.contains(itemUseArray.Fishing, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Fishing', type='skill'}))
	end
	--Fletching
	if canFletch or Shared.contains(itemUseArray.Fletching, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Fletching', type='skill'}))
	end
	--Herblore
	if canHerblore or Shared.contains(itemUseArray.Herblore, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Herblore', type='skill'}))
	end
	--Mining
	if Shared.contains(itemUseArray.Mining, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Mining', type='skill'}))
	end
	--Prayer
	if item.prayerPoints ~= nil or (Shared.contains(itemUseArray.Prayer, item.name) and not Shared.contains(itemUseArray.Combat, item.name)) then
		if item.prayerPoints ~= nil then table.insert(categoryArray, '[[Category:Buriable Items]]') end
		table.insert(useArray, chr..Icons.Icon({'Prayer', type='skill'}))
	end
	--Runecrafting
	if canRunecraft or Shared.contains(itemUseArray.Runecrafting, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Runecrafting', type='skill'}))
	end
	--Slayer
	if isSlayerAreaReq or Shared.contains(itemUseArray.Slayer, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Slayer', type='skill'}))
	end
	--Smithing
	if item.type == 'Bar' or item.type == 'Ore' or Shared.contains(itemUseArray.Smithing, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Smithing', type='skill'}))
	end
	--Summoning
	if canSummon or (item.type == 'Shard' and item.category == 'Summoning') or item.type == 'Familiar' or Shared.contains(itemUseArray.Summoning, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Summoning', type='skill'}))
	end
	--Thieving
	if Shared.contains(itemUseArray.Thieving, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Thieving', type='skill'}))
	end
	--Woodcutting
	if Shared.contains(itemUseArray.Woodcutting, item.name) then
		table.insert(useArray, chr..Icons.Icon({'Woodcutting', type='skill'}))
	end

	--Other odds and ends:

	--Mastery Tokens are tied to 'Mastery'
	if item.isToken and item.skill ~= nil then
		table.insert(useArray, chr..Icons.Icon({'Mastery'}))
	end

	--Skillcapes are tied to the appropriate skill
	--Except Maximum Skillcape, which is tied to all skills. (And so is the Signet Ring)
	--And combat skillcapes, since combat skills don't get special treatment

	local ignoreCapes = {'Ranged Skillcape', 'Attack Skillcape', 'Strength Skillcape', 'HP Skillcape', 'Defence Skillcape'}
	if Shared.contains({'Maximum Skillcape', 'Aorpheat&apos;s Signet Ring', 'Cape of Completion'}, item.name) then
		table.insert(useArray, chr..'All skills')
	elseif item.name == 'Magic Skillcape' then
		table.insert(useArray, chr..Icons.Icon({'Magic', type='skill'}))
		table.insert(useArray, chr..Icons.Icon({'Alt. Magic', type='skill'}))
	elseif Shared.contains(item.name, 'Skillcape') and not Shared.contains(ignoreCapes, item.name) then
		local skillName = Shared.splitString(item.name, ' ')[1]
		--Avoiding double-listing the same skill twice
		if not Shared.contains(itemUseArray[skillName], item.name) then
			table.insert(useArray, chr..Icons.Icon({skillName, type='skill'}))
		end
	end

	if Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion' then table.insert(categoryArray, '[[Category:Skillcapes]]') end

	--Special note for Charge Stone of Rhaelyx
	if item.name == 'Charge Stone of Rhaelyx' then
		table.insert(useArray, chr..'Powering '..Icons.Icon({'Crown of Rhaelyx', type='item'}))
	end

	--Some items are needed to make shop purchases
	local shopArray = Shop.getItemCostArray(item.id)
	if Shared.tableCount(shopArray) > 0 then
		table.insert(useArray, chr..Icons.Icon({'Shop'}))
	end

	if canUpgrade then
		if item.canUpgrade or (item.type == 'Armour' and item.canUpgrade == nil) then
			table.insert(categoryArray, '[[Category:Upgradeable Items]]')
		end
		table.insert(useArray, chr..'[[Upgrading Items]]')
	end

	local resultPart = {}
	table.insert(resultPart, asList and table.concat(useArray,'\r\n') or table.concat(useArray, '<br/>'))
	if addCategories then table.insert(resultPart, table.concat(categoryArray, '')) end
	return table.concat(resultPart)
end

function p.getItemUses(frame)
	local itemName = frame.args ~= nil and frame.args[1] or frame
	local item = Items.getItem(itemName)
	local addCategories = false
	local asList = true
	if frame.args ~= nil then
		addCategories = frame.args.addCategories ~= nil and frame.args.addCategories ~= '' and frame.args.addCategories ~= 'false'
		asList = frame.args.addCategories == nil or frame.args.addCategories == '' or frame.args.addCategories == 'true'
	end
	if item == nil then
		return "ERROR: No item named "..itemName.." exists in the data module"
	end

	return p._getItemUses(item, asList, addCategories)
end

function p._getItemUseTable(item)
	local useArray = {}
	local potTierMastery = {[0] = 0, [1] = 20, [2] = 50, [3] = 90}

	--First, loop through all items to find anything that can be made or upgraded into using our source
	for i, item2 in pairs(ItemData.Items) do
		if item2.itemsRequired ~= nil then
			for j, req in pairs(item2.itemsRequired) do
				if req[1] == item.id then
					local mat = item2.itemsRequired
					local xp = 'N/A'
					local rowReq = 'None'
					--Potions do have upgrade requirements though
					if item2.potionTier ~= nil then
						rowReq = Icons._MasteryReq(item2.name, potTierMastery[item2.potionTier])
					end
					table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Upgrade', req = rowReq, xp = xp, gp = item2.trimmedGPCost})
					break
				end
			end
		end
		if item2.craftReq ~= nil then
			for j, req in pairs(item2.craftReq) do
				if req.id == item.id then
					local mat = item2.craftReq
					local xp = item2.craftingXP
					local rowReq = item2.craftingLevel
					local qty = item2.craftQty
					table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Crafting', req = rowReq, xp = xp, gp = item2.craftGPCost})
					break
				end
			end
		end
		if item2.fletchReq ~= nil then
			for j, req in pairs(item2.fletchReq) do
				if req.id == item.id then
					local xp = item2.fletchingXP
					local rowReq = item2.fletchingLevel
					--Arrow Shafts are special and have to be treated specially
					local qty = item2.fletchQty
					local mat = item2.fletchReq
					if item2.name == 'Arrow Shafts' then
						mat = {{id = item.id, qty = 1}}
						qty =  qty + (qty * item.id)
					end
					table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Fletching', req = rowReq, xp = xp})
					break
				end
			end
		end
		if item2.smithReq ~= nil then
			for j, req in pairs(item2.smithReq) do
				if req.id == item.id then
					local mat = item2.smithReq
					local xp = item2.smithingXP
					local rowReq = item2.smithingLevel
					local qty = item2.smithingQty
					table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Smithing', req = rowReq, xp = xp})
					break
				end
			end
		end
		--Handling for new Cooking method
		if item2.recipeRequirements ~= nil then
			for j, reqSet in pairs(item2.recipeRequirements) do
				for k, req in pairs(reqSet) do
					if req.id == item.id then
						local mat = reqSet
						local xp = item2.cookingXP
						local rowReq = item2.cookingLevel
						local qty = item2.cookingQty
						table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})
						
						if item2.perfectItem ~= nil then
							local perfectItem = Items.getItemByID(item2.perfectItem)
							table.insert(useArray, {item = perfectItem, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})
						end
					end
				end
			end
		end
		if item2.runecraftReq ~= nil then
			for j, req in pairs(item2.runecraftReq) do
				if req.id == item.id then
					local mat = item2.runecraftReq
					local xp = item2.runecraftingXP
					local rowReq = item2.runecraftingLevel
					local qty = item2.runecraftQty
					table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Runecrafting', req = rowReq, xp = xp})
					break
				end
			end
		end
		if item2.herbloreReq ~= nil then
			for j, req in pairs(item2.herbloreReq) do
				if req.id == item.id then
					local potionData = SkillData.Herblore.ItemData[item2.masteryID[2] + 1]
					local mat = item2.herbloreReq
					local xp = potionData.herbloreXP
					--Potions do have upgrade requirements though
					local rowReq = Icons._SkillReq('Herblore', potionData.level)
					local masteryLvl = potTierMastery[item2.potionTier]
					if masteryLvl > 0 then
						rowReq = rowReq..'<br/>'..Icons._MasteryReq(item2.name, masteryLvl)
					end
					local reqVal = potionData.level + (masteryLvl * 0.01)
					table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Herblore', reqVal = reqVal, req = rowReq, xp = xp})
					break
				end
			end
		end

		if item2.summoningReq ~= nil then
			for j, reqSet in pairs(item2.summoningReq) do
				for k, req in pairs(reqSet) do
					if req.id == item.id then
						local mat = Shared.clone(reqSet)
						mat[k].qty = math.max(math.floor(1000 / math.max(item.sellsFor, 20)), 1)
						local xp = 5 + 2 * math.floor(item2.summoningLevel * 0.2)
						local rowReq = item2.summoningLevel
						table.insert(useArray, {item = item2, qty = 25, mats = mat, skill = 'Summoning', req = rowReq, xp = xp})
					end
				end
			end
		end
	end
	if item.grownItemID ~= nil then
		local item2 = Items.getItemByID(item.grownItemID)
		local mat = {{id = item.id, qty = item.seedsRequired}}
		local xp = item.farmingXP
		local rowReq = item.farmingLevel
		local qty = (item.tier ~= nil and item.tier == 'Tree' and 35 or 15)
		table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Farming', req = rowReq, xp = xp})
	end

	--Handle shop purchases using Module:Shop
	local shopUses = Shop.getItemCostArray(item.id)
	for i, purchase in Shared.skpairs(shopUses) do
		local rowReq = Shop.getRequirementString(purchase.unlockRequirements)
		local iconType = (purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0) and 'item' or 'upgrade'
		table.insert(useArray, {item = {name = purchase.name}, qty = 1, mats = purchase.cost.items, skill = 'Shop', req = rowReq, xp = 'N/A', gp = purchase.cost.gp, type = iconType})
	end

	--Finally build the table using what we've learned
	table.sort(useArray, function(a, b)
							           local aReqVal = a.reqVal ~= nil and a.reqVal or a.req
							           local bReqVal = b.reqVal ~= nil and b.reqVal or b.req
							           if a.skill ~= b.skill then
							             return a.skill < b.skill
							           elseif type(aReqVal) ~= type(bReqVal) then
							             return tostring(aReqVal) < tostring(bReqVal)
							           elseif aReqVal ~= bReqVal then
							             return aReqVal < bReqVal
							           else
							             return a.item.name < b.item.name
							           end end)

	local obstacles = Agility.getObstaclesForItem(item.id)

	local spellUseTable = p._getSpellUseTable(item)
	local resultPart = {}
	if Shared.tableCount(useArray) == 0 and Shared.tableCount(obstacles) == 0 then
		if string.len(spellUseTable) > 0 then
			return '==Uses==\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable
		else
			return ''
		end
	end
	table.insert(resultPart, '{| class="wikitable sortable"')
	table.insert(resultPart, '\r\n!colspan=2|Item Created!!Type!!Requirements!!XP!!Ingredients')
	for i, row in pairs(useArray) do
		local qty = row.qty ~= nil and row.qty or 1
		local iconType = row.type ~= nil and row.type or 'item'
		table.insert(resultPart, '\r\n|-\r\n|data-sort-value="'..row.item.name..'"|')
		table.insert(resultPart, Icons.Icon({row.item.name, type=iconType, notext=true, size=50})..'||')
		if qty > 1 then table.insert(resultPart, "'''"..qty.."x''' ") end
		table.insert(resultPart, Icons.Icon({row.item.name, type='item', noicon=true}))
		if row.skill == 'Upgrade' then
			table.insert(resultPart, '||data-sort-value="Upgrade"|[[Upgrading Items|Upgrade]]')
		elseif row.skill == 'Shop' then
			table.insert(resultPart, '||data-sort-value="Shop"|'..Icons.Icon({'Shop'}))
		else
			table.insert(resultPart, '||data-sort-value="'..row.skill..'"|'..Icons.Icon({row.skill, type='skill'}))
		end
		if type(row.req) == 'number' then
			table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.req..'"|'..Icons._SkillReq(row.skill, row.req))
		elseif row.reqVal ~= nil then
			table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.reqVal..'"|'..row.req)
		else
			table.insert(resultPart, '||'..row.req)
		end
		if type(row.xp) == 'string' then
			table.insert(resultPart, '||style="text-align:right" data-sort-value="0"|'..row.xp)
		else
			table.insert(resultPart, '||style="text-align:right" data-sort-value="'..row.xp..'"|'..row.xp..' '..Icons.Icon({row.skill, type='skill', notext=true})..' XP')
		end
		table.insert(resultPart, '||')
		for i, mat in Shared.skpairs(row.mats) do
			local matID = mat.id ~= nil and mat.id or mat[1]
			local matQty = mat.qty ~= nil and mat.qty or mat[2]
			local matText = ''

			if i > 1 then table.insert(resultPart, '<br/>') end
			if matID >= 0 then
				-- Item
				local matItem = Items.getItemByID(matID)
				if matItem == nil then
					matText = 'ERROR: Failed to find item with ID ' .. matID .. '[[Category:Pages with Script Errors]]'
				else
					matText = Icons.Icon({matItem.name, type='item', qty=matQty})
				end
			elseif matID == -4 then
				-- GP
				matText = Icons.GP(SkillData.Summoning.Settings.recipeGPCost)
			elseif matID == -5 then
				-- Slayer Coins
				matText = Icons.SC(SkillData.Summoning.Settings.recipeGPCost)
			else
				matText = 'ERROR: Unknown item ID: ' .. matID .. ' [[Category:Pages with Script Errors]]'
			end
			table.insert(resultPart, matText)
		end
		if row.gp ~= nil then table.insert(resultPart, '<br/>'..Icons.GP(row.gp)) end
	end

	--Agility obstacles are weird and get their own section
	for i, obst in Shared.skpairs(obstacles) do
		table.insert(resultPart, '\r\n|-\r\n|')
		table.insert(resultPart, Icons.Icon({"Agility", type="skill", size="50", notext=true}))
		table.insert(resultPart, '||[[Agility#Obstacles|'..obst.name..']]')
		table.insert(resultPart, '||'..Icons.Icon({"Agility", type="skill"}))

		--Adding the requirements for the Agility Obstacle
		local reqArray = {}
		if obst.category == nil then --nil category means this is a passive pillar
			table.insert(reqArray, Icons._SkillReq('Agility', 99))
		elseif obst.category > 0 then --Otherwise it's category * 10
			table.insert(reqArray, Icons._SkillReq('Agility', obst.category * 10))
		end
		--Then the other skill levels if any are added
		if obst.requirements ~= nil and obst.requirements.skillLevel ~= nil then
			for j, req in Shared.skpairs(obst.requirements.skillLevel) do
				table.insert(reqArray, Icons._SkillReq(Constants.getSkillName(req[1]), req[2]))
			end
		end
		table.insert(resultPart, '||style="text-align:right"|'..table.concat(reqArray, '<br/>'))

		--Just including 'N/A' for XP since it doesn't really apply for Agility Obstacles
		table.insert(resultPart, '||style="text-align:right"|N/A')

		--Finally the cost
		local cost = obst.cost
		local costArray = {}
		if cost.gp ~= nil and cost.gp > 0 then
			table.insert(costArray, Icons.GP(cost.gp))
		end
		if cost.slayerCoins ~= nil and cost.slayerCoins > 0 then
			table.insert(costArray, Icons.SC(cost.slayerCoins))
		end
		for j, mat in Shared.skpairs(cost.items) do
			local item = Items.getItemByID(mat[1])
			table.insert(costArray, Icons.Icon({item.name, type="item", qty=mat[2]}))
		end

		table.insert(resultPart, '||'..table.concat(costArray, '<br/>'))

	end

	table.insert(resultPart, '\r\n|}')
	if string.len(spellUseTable) > 0 then
		table.insert(resultPart, '\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable)
	end
	return '==Uses==\r\n'..table.concat(resultPart)
end

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

	return p._getItemUseTable(item)
end

function p._getSpellUseTable(item)
	local spellList = Magic.getSpellsForRune(item.id)
	--Bail immediately if no spells are found
	if Shared.tableCount(spellList) == 0 then
		return ''
	end

	local resultPart = {}
	table.insert(resultPart, '{|class="wikitable sortable"\r\n!colspan="2"|Spell')
	table.insert(resultPart, '!!Requirements')
	table.insert(resultPart, '!!Type!!style="width:275px"|Description')
	table.insert(resultPart, '!!Runes')
	for i, spell in pairs(spellList) do
		local rowPart = {}
		table.insert(rowPart, '\r\n|-\r\n|data-sort-value="'..spell.name..'"|')
		local iconType = (spell.type == 'Auroras' and 'aurora') or (spell.type == 'Curses' and 'curse') or 'spell'
		table.insert(rowPart, Icons.Icon({spell.name, type=iconType, notext=true, size=50}))
		table.insert(rowPart, '||'..Icons.Icon({spell.name, type=iconType, noicon=true}))
		table.insert(rowPart, '||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level))
		--Handle required items/dungeon clears
		if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
			local reqItem = Items.getItemByID(spell.requiredItem)
			table.insert(rowPart, '<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped')
		end
		if spell.requiredDungeonCompletion ~= nil then
			local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
			table.insert(rowPart, '<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears')
		end
		table.insert(rowPart, '||data-sort-value="'..Magic.getSpellTypeIndex(spell.type)..'"|')
		table.insert(rowPart, Magic.getSpellTypeLink(spell.type))
		table.insert(rowPart, '||'..Magic._getSpellStat(spell, 'description'))
		table.insert(rowPart, '||style="text-align:center"|')
		table.insert(rowPart, Magic._getSpellRunes(spell))
		table.insert(resultPart, table.concat(rowPart))
	end
	 --Add the table end and add the table to the result string
	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

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

	return p._getSpellUseTable(item)
end

return p