Module:Items/SourceTables: Difference between revisions

Updated indenting
m (Fix logic error)
(Updated indenting)
Line 18: Line 18:
-- Currently only overrides for dungeon sources are implemented here
-- Currently only overrides for dungeon sources are implemented here
local sourceOverrides = {
local sourceOverrides = {
  ['Dungeon'] = {
['Dungeon'] = {
  [361] = 'Volcanic Cave', -- Fire Cape
[361] = 'Volcanic Cave', -- Fire Cape
  [941] = 'Infernal Stronghold', -- Infernal Cape
[941] = 'Infernal Stronghold', -- Infernal Cape
    [950] = 'Volcanic Cave', -- A Tale of the Past, a future's prophecy
[950] = 'Volcanic Cave', -- A Tale of the Past, a future's prophecy
    [951] = 'Fire God Dungeon', -- The First Hero and an Unknown Evil
[951] = 'Fire God Dungeon', -- The First Hero and an Unknown Evil
    [1116] = 'Into the Mist' -- Beginning of the End
[1116] = 'Into the Mist' -- Beginning of the End
  }
}
}
}


function p._getCreationTable(item)
function p._getCreationTable(item)
  local skill = ''
local skill = ''
  local specialReq = nil
local specialReq = nil
  local time = 0
local time = 0
  local maxTime = nil
local maxTime = nil
  local lvl = 0
local lvl = 0
  local xp = 0
local xp = 0
  local qty = nil
local qty = nil
  local req = nil
local req = nil


  local tables = {}
local tables = {}
  --First figure out what skill is used to make this...
--First figure out what skill is used to make this...
  if item.smithingLevel ~= nil then
if item.smithingLevel ~= nil then
    skill = 'Smithing'
skill = 'Smithing'
    lvl = item.smithingLevel
lvl = item.smithingLevel
    xp = item.smithingXP
xp = item.smithingXP
    req = item.smithReq
req = item.smithReq
    qty = item.smithingQty
qty = item.smithingQty
    time = 2
time = 2
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
  end
end
  if item.craftingLevel ~= nil then
if item.craftingLevel ~= nil then
    skill = 'Crafting'
skill = 'Crafting'
    lvl = item.craftingLevel
lvl = item.craftingLevel
    xp = item.craftingXP
xp = item.craftingXP
    req = item.craftReq
req = item.craftReq
    qty = item.craftQty
qty = item.craftQty
    time = 3
time = 3
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, nil, nil, item.craftGPCost))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, nil, nil, item.craftGPCost))
  end
end
  if item.runecraftingLevel ~= nil then
if item.runecraftingLevel ~= nil then
    skill = 'Runecrafting'
skill = 'Runecrafting'
    lvl = item.runecraftingLevel
lvl = item.runecraftingLevel
    xp = item.runecraftingXP
xp = item.runecraftingXP
    req = item.runecraftReq
req = item.runecraftReq
    qty = item.runecraftQty
qty = item.runecraftQty
    time = 2
time = 2
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
  end
end
  if item.fletchingLevel ~= nil then
if item.fletchingLevel ~= nil then
    skill = 'Fletching'
skill = 'Fletching'
    lvl = item.fletchingLevel
lvl = item.fletchingLevel
    xp = item.fletchingXP
xp = item.fletchingXP
    req = item.fletchReq
req = item.fletchReq
    qty = item.fletchQty
qty = item.fletchQty
    time = 2
time = 2
    if item.name == 'Arrow Shafts' then
if item.name == 'Arrow Shafts' then
      --Arrow Shafts get special (weird) treatment
--Arrow Shafts get special (weird) treatment
      req = '1 of any [[Log]]'
req = '1 of any [[Log]]'
      qty = '15 - 135'
qty = '15 - 135'
    end
end
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
  end
end
  if item.cookingLevel ~= nil and item.recipeRequirements ~= nil then
if item.cookingLevel ~= nil and item.recipeRequirements ~= nil then
  for i, reqSet in pairs(item.recipeRequirements) do
for i, reqSet in pairs(item.recipeRequirements) do
    skill = 'Cooking'
skill = 'Cooking'
    lvl = item.cookingLevel
lvl = item.cookingLevel
    xp = item.cookingXP
xp = item.cookingXP
    req = reqSet
req = reqSet
    qty = item.cookingQty
qty = item.cookingQty
    time = item.cookingInterval / 1000
time = item.cookingInterval / 1000
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
  end
end
  end
end
  if item.herbloreReq ~= nil then
if item.herbloreReq ~= nil then
    skill = 'Herblore'
skill = 'Herblore'
    req = item.herbloreReq
req = item.herbloreReq
    --Currently using 'masteryID' as shorthand to find details, could be a better method
--Currently using 'masteryID' as shorthand to find details, could be a better method
    local potionID = item.masteryID[2]
local potionID = item.masteryID[2]
    local potionData = SkillData.Herblore.ItemData[potionID + 1]
local potionData = SkillData.Herblore.ItemData[potionID + 1]
    lvl = potionData.level
lvl = potionData.level
    xp = potionData.herbloreXP
xp = potionData.herbloreXP
    time = 2
time = 2
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
  end
end
  if item.masteryID ~= nil and item.masteryID[1] == 4 then
if item.masteryID ~= nil and item.masteryID[1] == 4 then
    skill = 'Mining'
skill = 'Mining'
    lvl = SkillData.Mining.Rocks[item.masteryID[2] + 1].levelRequired
lvl = SkillData.Mining.Rocks[item.masteryID[2] + 1].levelRequired
    time = 3
time = 3
    xp = item.miningXP
xp = item.miningXP
    --Rune Essence has double quantity, but that's a hard-coded thing in the game so it's hard-coded here
--Rune Essence has double quantity, but that's a hard-coded thing in the game so it's hard-coded here
    if item.name == 'Rune Essence' then qty = 2 else qty = 1 end
if item.name == 'Rune Essence' then qty = 2 else qty = 1 end


    if item.name == 'Dragonite Ore' then
if item.name == 'Dragonite Ore' then
      specialReq = Icons.Icon({"Mastery", notext='true'})..' 271 total [[Mining]] [[Mastery]]'
specialReq = Icons.Icon({"Mastery", notext='true'})..' 271 total [[Mining]] [[Mastery]]'
    end
end
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, nil, specialReq))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, nil, specialReq))
  end
end
  if item.type == "Logs" then
if item.type == "Logs" then
    --Well this feels like cheating, but for as long as logs are the first items by ID it works
--Well this feels like cheating, but for as long as logs are the first items by ID it works
    local treeData = SkillData.Woodcutting.Trees[item.id + 1]
local treeData = SkillData.Woodcutting.Trees[item.id + 1]
    skill = 'Woodcutting'
skill = 'Woodcutting'
    lvl = treeData.level
lvl = treeData.level
    time = treeData.interval / 1000
time = treeData.interval / 1000
    xp = treeData.xp
xp = treeData.xp
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
  end
end
  if item.fishingLevel ~= nil then
if item.fishingLevel ~= nil then
    skill = 'Fishing'
skill = 'Fishing'
    lvl = item.fishingLevel
lvl = item.fishingLevel
    xp = item.fishingXP
xp = item.fishingXP
    time = item.minFishingInterval/1000
time = item.minFishingInterval/1000
    maxTime = item.maxFishingInterval/1000
maxTime = item.maxFishingInterval/1000
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime))
  end
end
  --had to add cooking to the list of valid categories here to account for cherries/apples
--had to add cooking to the list of valid categories here to account for cherries/apples
  if item.category == 'Cooking' or item.type == "Harvest" or item.type == "Herb" or item.type == "Logs" or Shared.contains(item.name, '(Perfect)') then
if item.category == 'Cooking' or item.type == "Harvest" or item.type == "Herb" or item.type == "Logs" or Shared.contains(item.name, '(Perfect)') then
    --Harvest/Herb means farming
--Harvest/Herb means farming
    --Logs might mean farming or might not. Depends on the logs
--Logs might mean farming or might not. Depends on the logs
    for i, item2 in pairs(ItemData.Items) do
for i, item2 in pairs(ItemData.Items) do
      if item2.grownItemID == item.id then
if item2.grownItemID == item.id then
        skill = 'Farming'
skill = 'Farming'
        lvl = item2.farmingLevel
lvl = item2.farmingLevel
        xp = item2.farmingXP
xp = item2.farmingXP
        time = item2.timeToGrow
time = item2.timeToGrow
        if item.type == 'Logs' then
if item.type == 'Logs' then
          qty = 35
qty = 35
        else
else
          qty = 15
qty = 15
        end
end
        req = {{id = i - 1, qty = (item2.seedsRequired ~= nil and item2.seedsRequired or 1)}}
req = {{id = i - 1, qty = (item2.seedsRequired ~= nil and item2.seedsRequired or 1)}}
        table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
        break
break
      end
end


      --If this is a perfect item, need to find the original
--If this is a perfect item, need to find the original
      if item2.perfectItem == item.id and item2.recipeRequirements ~= nil then
if item2.perfectItem == item.id and item2.recipeRequirements ~= nil then
  for j, reqSet in pairs(item2.recipeRequirements) do
for j, reqSet in pairs(item2.recipeRequirements) do
      skill = 'Cooking'
skill = 'Cooking'
    lvl = item2.cookingLevel
lvl = item2.cookingLevel
    xp = item2.cookingXP
xp = item2.cookingXP
    req = reqSet
req = reqSet
    qty = item2.cookingQty
qty = item2.cookingQty
    time = item2.cookingInterval / 1000
time = item2.cookingInterval / 1000
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
end
end
end
end
if item.summoningLevel ~= nil then
skill = 'Summoning'
lvl = item.summoningLevel
--Summoning uses a formula to calculate XP for creation instead of referring to the item's XP data directly
xp = (5 + 2 * math.floor(item.summoningLevel / 5))
local ShardCostArray = {}
for j, cost in Shared.skpairs(item.summoningReq[1]) do
if cost.id >= 0 then
local item = Items.getItemByID(cost.id)
if item.type == 'Shard' then
table.insert(ShardCostArray, Icons.Icon({item.name,  type='item', notext=true, qty=cost.qty}))
end
end
end
req = table.concat(ShardCostArray, ', ')
req = req..'<br/>\r\nand one of the following<br/>\r\n'
local OtherCostArray = {}
local recipeGPCost = SkillData.Summoning.Settings.recipeGPCost
for j, altCost in Shared.skpairs(item.summoningReq) do
local nonShardArray = {}
for k, cost in Shared.skpairs(altCost) do
if cost.id >= 0 then
local item = Items.getItemByID(cost.id)
if item.type ~= 'Shard' then
  local sellPrice = math.max(item.sellsFor, 20)
  table.insert(nonShardArray, Icons.Icon({item.name, type='item', notext=true, qty=math.max(1, math.floor(recipeGPCost / sellPrice))}))
end
else
if cost.id == -4 then
  table.insert(nonShardArray, Icons.GP(recipeGPCost))
elseif cost.id == -5 then
  table.insert(nonShardArray, Icons.SC(recipeGPCost))
end
end
end
table.insert(OtherCostArray, table.concat(nonShardArray, ', '))
end
end
  end
req = req..table.concat(OtherCostArray, "<br/>'''OR''' ")
    end
qty = item.summoningQty
  end
time = 5
  if item.summoningLevel ~= nil then
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
    skill = 'Summoning'
end
    lvl = item.summoningLevel
--A couple special exceptions for Alt Magic
    --Summoning uses a formula to calculate XP for creation instead of referring to the item's XP data directly
--Not Gems or Bars though since those have their own separate thing
    xp = (5 + 2 * math.floor(item.summoningLevel / 5))
if item.name == 'Rune Essence' then
    local ShardCostArray = {}
table.insert(tables, p.buildAltMagicTable('Just Learning'))
    for j, cost in Shared.skpairs(item.summoningReq[1]) do
elseif item.name == 'Bones' then
      if cost.id >= 0 then
table.insert(tables, p.buildAltMagicTable('Bone Offering'))
        local item = Items.getItemByID(cost.id)
elseif item.name == 'Holy Dust' then
        if item.type == 'Shard' then
table.insert(tables, p.buildAltMagicTable('Blessed Offering'))
          table.insert(ShardCostArray, Icons.Icon({item.name,  type='item', notext=true, qty=cost.qty}))
end
        end
      end
    end
    req = table.concat(ShardCostArray, ', ')
    req = req..'<br/>\r\nand one of the following<br/>\r\n'
    local OtherCostArray = {}
    local recipeGPCost = SkillData.Summoning.Settings.recipeGPCost
    for j, altCost in Shared.skpairs(item.summoningReq) do
      local nonShardArray = {}
      for k, cost in Shared.skpairs(altCost) do
        if cost.id >= 0 then
          local item = Items.getItemByID(cost.id)
          if item.type ~= 'Shard' then
            local sellPrice = math.max(item.sellsFor, 20)
            table.insert(nonShardArray, Icons.Icon({item.name, type='item', notext=true, qty=math.max(1, math.floor(recipeGPCost / sellPrice))}))
          end
        else
          if cost.id == -4 then
            table.insert(nonShardArray, Icons.GP(recipeGPCost))
          elseif cost.id == -5 then
            table.insert(nonShardArray, Icons.SC(recipeGPCost))
          end
        end
      end
      table.insert(OtherCostArray, table.concat(nonShardArray, ', '))
    end
    req = req..table.concat(OtherCostArray, "<br/>'''OR''' ")
    qty = item.summoningQty
    time = 5
    table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
  end
  --A couple special exceptions for Alt Magic
  --Not Gems or Bars though since those have their own separate thing
  if item.name == 'Rune Essence' then
    table.insert(tables, p.buildAltMagicTable('Just Learning'))
  elseif item.name == 'Bones' then
    table.insert(tables, p.buildAltMagicTable('Bone Offering'))
  elseif item.name == 'Holy Dust' then
    table.insert(tables, p.buildAltMagicTable('Blessed Offering'))
  end


  if Shared.tableCount(tables) == 0 then
if Shared.tableCount(tables) == 0 then
    return ""
return ""
  else
else
    return table.concat(tables, '\r\n')
return table.concat(tables, '\r\n')
  end
end
end
end


function p.buildAltMagicTable(spellName)
function p.buildAltMagicTable(spellName)
  local spell = Magic.getSpell(spellName, 'AltMagic')
local spell = Magic.getSpell(spellName, 'AltMagic')
  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{|class="wikitable"\r\n|-')
table.insert(resultPart, '{|class="wikitable"\r\n|-')
  table.insert(resultPart, '\r\n!colspan="2"|'..Icons.Icon({spell.name, type='spell'}))
table.insert(resultPart, '\r\n!colspan="2"|'..Icons.Icon({spell.name, type='spell'}))
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Requirements')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Requirements')
  table.insert(resultPart, '\r\n|'..Icons._SkillReq('Magic', spell.level))
table.insert(resultPart, '\r\n|'..Icons._SkillReq('Magic', spell.level))
  -- 1 means select any item. 0 would mean Superheat, but that's handled elsewhere
-- 1 means select any item. 0 would mean Superheat, but that's handled elsewhere
  -- -1 means no item is needed, so hide this section
-- -1 means no item is needed, so hide this section
  if spell.selectItem == 1 then
if spell.selectItem == 1 then
    table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Materials')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Materials')
    table.insert(resultPart, '\r\n|1 of any item')
table.insert(resultPart, '\r\n|1 of any item')
  end
end
  --Add runes
--Add runes
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Runes\r\n|')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Runes\r\n|')
  for i, req in pairs(spell.runesRequired) do
for i, req in pairs(spell.runesRequired) do
    local rune = Items.getItemByID(req.id)
local rune = Items.getItemByID(req.id)
    if i > 1 then table.insert(resultPart, ', ') end
if i > 1 then table.insert(resultPart, ', ') end
    table.insert(resultPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
table.insert(resultPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
  end
end
  if spell.runesRequiredAlt ~= nil and Shared.tableCount(spell.runesRequired) ~= Shared.tableCount(spell.runesRequiredAlt) then
if spell.runesRequiredAlt ~= nil and Shared.tableCount(spell.runesRequired) ~= Shared.tableCount(spell.runesRequiredAlt) then
    table.insert(resultPart, "<br/>'''OR'''<br/>")
table.insert(resultPart, "<br/>'''OR'''<br/>")
    for i, req in pairs(spell.runesRequiredAlt) do
for i, req in pairs(spell.runesRequiredAlt) do
      local rune = Items.getItemByID(req.id)
local rune = Items.getItemByID(req.id)
      if i > 1 then table.insert(resultPart, ', ') end
if i > 1 then table.insert(resultPart, ', ') end
      table.insert(resultPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
table.insert(resultPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
    end
end
  end
end


  --Now just need the output quantity, xp, and casting time (which is always 2)
--Now just need the output quantity, xp, and casting time (which is always 2)
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Quantity\r\n|'..spell.convertToQty)
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Quantity\r\n|'..spell.convertToQty)
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base XP\r\n|'..spell.magicXP)
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base XP\r\n|'..spell.magicXP)
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Cast Time\r\n|2s')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Cast Time\r\n|2s')
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')
  return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime, specialReq, gpCost)
function p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime, specialReq, gpCost)
  if qty == nil then qty = 1 end
if qty == nil then qty = 1 end
  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{|class="wikitable"')
table.insert(resultPart, '{|class="wikitable"')
  if req ~= nil then
if req ~= nil then
    table.insert(resultPart, '\r\n!colspan="2"|Item Creation')
table.insert(resultPart, '\r\n!colspan="2"|Item Creation')
  else
else
    table.insert(resultPart, '\r\n!colspan="2"|Item Production')
table.insert(resultPart, '\r\n!colspan="2"|Item Production')
  end
end
  table.insert(resultPart, '\r\n|-\r\n!style="text-align: right;"|Requirements')
table.insert(resultPart, '\r\n|-\r\n!style="text-align: right;"|Requirements')
  table.insert(resultPart, '\r\n|'..Icons._SkillReq(skill, lvl))
table.insert(resultPart, '\r\n|'..Icons._SkillReq(skill, lvl))
  if specialReq ~= nil then table.insert(resultPart, '<br/>'..specialReq) end
if specialReq ~= nil then table.insert(resultPart, '<br/>'..specialReq) end


  if req ~= nil then
if req ~= nil then
    table.insert(resultPart, '\r\n|-\r\n!style="text-align: right;"|Materials\r\n|')
table.insert(resultPart, '\r\n|-\r\n!style="text-align: right;"|Materials\r\n|')
    if type(req) == 'table' then
if type(req) == 'table' then
      for i, mat in pairs(req) do
for i, mat in pairs(req) do
        if i > 1 then table.insert(resultPart, '<br/>') end
if i > 1 then table.insert(resultPart, '<br/>') end
        local matItem = Items.getItemByID(mat.id)
local matItem = Items.getItemByID(mat.id)
        if matItem == nil then
if matItem == nil then
          table.insert(resultPart, mat.qty..'x ?????')
table.insert(resultPart, mat.qty..'x ?????')
        else
else
          table.insert(resultPart, Icons.Icon({matItem.name, type='item', qty=mat.qty}))
table.insert(resultPart, Icons.Icon({matItem.name, type='item', qty=mat.qty}))
        end
end
      end
end
      if gpCost ~= nil and gpCost > 0 then
if gpCost ~= nil and gpCost > 0 then
    table.insert(resultPart, '<br/>')
table.insert(resultPart, '<br/>')
    table.insert(resultPart, Icons.GP(gpCost))
table.insert(resultPart, Icons.GP(gpCost))
      end
end
    else
else
    table.insert(resultPart, req)
table.insert(resultPart, req)
    end
end
  end
end
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Quantity')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Quantity')
  table.insert(resultPart, '\r\n|'..qty)
table.insert(resultPart, '\r\n|'..qty)
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Experience')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Experience')
  table.insert(resultPart, '\r\n|'..Shared.formatnum(xp)..' XP')
table.insert(resultPart, '\r\n|'..Shared.formatnum(xp)..' XP')
  table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Creation Time')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Creation Time')
  table.insert(resultPart, '\r\n|'..Shared.formatnum(Shared.round(time, 2, 0))..'s')
table.insert(resultPart, '\r\n|'..Shared.formatnum(Shared.round(time, 2, 0))..'s')
  if maxTime ~= nil then table.insert(resultPart, ' - '..Shared.formatnum(Shared.round(maxTime, 2, 0))..'s') end
if maxTime ~= nil then table.insert(resultPart, ' - '..Shared.formatnum(Shared.round(maxTime, 2, 0))..'s') end
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


  return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.getCreationTable(frame)
function p.getCreationTable(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[[Category:Pages with script errors]]"
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
end


  return p._getCreationTable(item)
return p._getCreationTable(item)
end
end


function p._getItemSources(item, asList, addCategories)
function p._getItemSources(item, asList, addCategories)
  local lineArray = {}
local lineArray = {}
  local categoryArray = {}
local categoryArray = {}


  --Alright, time to go through all the ways you can get an item...
--Alright, time to go through all the ways you can get an item...
  --First up: Can we kill somebody and take theirs?
--First up: Can we kill somebody and take theirs?
  local killStrPart = {}
local killStrPart = {}
  local dungeonStrPart = {}
local dungeonStrPart = {}
  for i, monster in ipairs(MonsterData.Monsters) do
for i, monster in ipairs(MonsterData.Monsters) do
  local isDrop, isBones = false, false
local isDrop, isBones = false, false
  if monster.bones == item.id and Monsters.getMonsterBones(monster) ~= nil then
if monster.bones == item.id and Monsters.getMonsterBones(monster) ~= nil then
  -- Item is a bone, and is either a shard from God dungeons or dropped by a non-boss monster with a loot table
-- Item is a bone, and is either a shard from God dungeons or dropped by a non-boss monster with a loot table
  isDrop = true
isDrop = true
  isBones = true
isBones = true
      elseif monster.lootTable ~= nil then
elseif monster.lootTable ~= nil then
      -- If the monster has a loot table, check if the item we are looking for is in there
-- If the monster has a loot table, check if the item we are looking for is in there
          for j, loot in ipairs(monster.lootTable) do
for j, loot in ipairs(monster.lootTable) do
              if loot[1] == item.id then
    if loot[1] == item.id then
            isDrop = true
  isDrop = true
            break
  break
            end
        end
      end
  if isDrop then
  if not isBones and Monsters._isDungeonOnlyMonster(monster) then
  -- For dungeon exclusive monsters, loot is only rolled when they are the last
  -- monster within that dungeon (unless it is a shard)
  if monster.isBoss then
  local areaList = Areas.getMonsterAreas(monster.id)
  for k, area in ipairs(areaList) do
  if area.type == 'dungeon' and area.monsters[#area.monsters] == monster.id then
  table.insert(dungeonStrPart, Icons.Icon({area.name, type='dungeon', notext=true}))
  end
  end
  end
end
  end
end
  else
if isDrop then
  -- Item is not an end of dungeon reward, and drops when the monster is killed
if not isBones and Monsters._isDungeonOnlyMonster(monster) then
  table.insert(killStrPart, Icons.Icon({monster.name, type='monster', notext=true}))
-- For dungeon exclusive monsters, loot is only rolled when they are the last
  end
-- monster within that dungeon (unless it is a shard)
  end
if monster.isBoss then
  end
local areaList = Areas.getMonsterAreas(monster.id)
  -- Is the item dropped from a cycle of the Impending Darkness event?
for k, area in ipairs(areaList) do
  for i, eventItemID in ipairs(Areas.eventData.rewards) do
if area.type == 'dungeon' and area.monsters[#area.monsters] == monster.id then
      if item.id == eventItemID then
table.insert(dungeonStrPart, Icons.Icon({area.name, type='dungeon', notext=true}))
  local dungPrefix = (i == Shared.tableCount(Areas.eventData.rewards) and '' or i .. ' ' .. (i == 1 and 'cycle' or 'cycles') .. ' of ')
end
          table.insert(dungeonStrPart, dungPrefix .. Icons.Icon({'Impending Darkness Event', type='dungeon', notext=true}))
end
  break
end
  end
else
  end
-- Item is not an end of dungeon reward, and drops when the monster is killed
  -- Special exceptions for Fire/Infernal Cape and first two lore books
table.insert(killStrPart, Icons.Icon({monster.name, type='monster', notext=true}))
  if sourceOverrides['Dungeon'][item.id] ~= nil then
end
    table.insert(dungeonStrPart, Icons.Icon({sourceOverrides['Dungeon'][item.id], type='dungeon', notext=true}))
end
  end
end
-- Is the item dropped from a cycle of the Impending Darkness event?
for i, eventItemID in ipairs(Areas.eventData.rewards) do
if item.id == eventItemID then
local dungPrefix = (i == Shared.tableCount(Areas.eventData.rewards) and '' or i .. ' ' .. (i == 1 and 'cycle' or 'cycles') .. ' of ')
table.insert(dungeonStrPart, dungPrefix .. Icons.Icon({'Impending Darkness Event', type='dungeon', notext=true}))
break
end
end
-- Special exceptions for Fire/Infernal Cape and first two lore books
if sourceOverrides['Dungeon'][item.id] ~= nil then
table.insert(dungeonStrPart, Icons.Icon({sourceOverrides['Dungeon'][item.id], type='dungeon', notext=true}))
end


  if Shared.tableCount(dungeonStrPart) > 0 then
if Shared.tableCount(dungeonStrPart) > 0 then
  table.insert(lineArray, 'Completing: ' .. table.concat(dungeonStrPart, ','))
table.insert(lineArray, 'Completing: ' .. table.concat(dungeonStrPart, ','))
  end
end
  if Shared.tableCount(killStrPart) > 0 then
if Shared.tableCount(killStrPart) > 0 then
  table.insert(lineArray, 'Killing: ' .. table.concat(killStrPart, ','))
table.insert(lineArray, 'Killing: ' .. table.concat(killStrPart, ','))
  end
end


  --Next: Can we find it in a box?
--Next: Can we find it in a box?
  --While we're here, check for upgrades, originals (for perfect items), and growing
--While we're here, check for upgrades, originals (for perfect items), and growing
  local lootStr = ''
local lootStr = ''
  local upgradeStr = ''
local upgradeStr = ''
  local cookStr = ''
local cookStr = ''
  local growStr = ''
local growStr = ''
  local count1 = 0
local count1 = 0
  local count2 = 0
local count2 = 0
  for i, item2 in pairs(ItemData.Items) do
for i, item2 in pairs(ItemData.Items) do
    if item2.dropTable ~= nil then
if item2.dropTable ~= nil then
      for j, loot in pairs(item2.dropTable) do
for j, loot in pairs(item2.dropTable) do
        if loot[1] == item.id then
if loot[1] == item.id then
          count1 = count1 + 1
count1 = count1 + 1
          if string.len(lootStr) > 0 then
if string.len(lootStr) > 0 then
            lootStr = lootStr..','
  lootStr = lootStr..','
            --if count1 % 3 == 1 and count1 > 1 then lootStr = lootStr..'<br/>' end
  --if count1 % 3 == 1 and count1 > 1 then lootStr = lootStr..'<br/>' end
            lootStr = lootStr..Icons.Icon({item2.name, type="item", notext="true"})
  lootStr = lootStr..Icons.Icon({item2.name, type="item", notext="true"})
          else
else
            lootStr = lootStr..'Opening: '..Icons.Icon({item2.name, type="item", notext="true"})
  lootStr = lootStr..'Opening: '..Icons.Icon({item2.name, type="item", notext="true"})
          end
end
        end
end
      end
end
    end
end
    if item2.trimmedItemID == item.id then
if item2.trimmedItemID == item.id then
          count2 = count2 + 1
count2 = count2 + 1
        if string.len(upgradeStr) > 0 then
if string.len(upgradeStr) > 0 then
          upgradeStr = upgradeStr..','
upgradeStr = upgradeStr..','
          --if count2 % 3 == 1 and count2 > 1 then upgradeStr = upgradeStr..'<br/>' end
--if count2 % 3 == 1 and count2 > 1 then upgradeStr = upgradeStr..'<br/>' end
          upgradeStr = upgradeStr..Icons.Icon({item2.name, type="item", notext="true"})
upgradeStr = upgradeStr..Icons.Icon({item2.name, type="item", notext="true"})
        else
else
          table.insert(categoryArray, '[[Category:Upgraded Items]]')
table.insert(categoryArray, '[[Category:Upgraded Items]]')
          upgradeStr = upgradeStr..'Upgrading: '..Icons.Icon({item2.name, type="item", notext="true"})
upgradeStr = upgradeStr..'Upgrading: '..Icons.Icon({item2.name, type="item", notext="true"})
        end
end
    end
end
    if item2.grownItemID == item.id then
if item2.grownItemID == item.id then
        if string.len(growStr) > 0 then
if string.len(growStr) > 0 then
          growStr = growStr..','..Icons.Icon({item2.name, type="item", notext="true"})
growStr = growStr..','..Icons.Icon({item2.name, type="item", notext="true"})
        else
else
          table.insert(categoryArray, '[[Category:Harvestable Items]]')
table.insert(categoryArray, '[[Category:Harvestable Items]]')
          growStr = growStr..'Growing: '..Icons.Icon({item2.name, type="item", notext="true"})
growStr = growStr..'Growing: '..Icons.Icon({item2.name, type="item", notext="true"})
        end
end
    end
end
    if item2.perfectItem == item.id and item2.cookingLevel ~= nil then
if item2.perfectItem == item.id and item2.cookingLevel ~= nil then
    table.insert(lineArray, Icons._SkillReq('Cooking', item2.cookingLevel))
table.insert(lineArray, Icons._SkillReq('Cooking', item2.cookingLevel))
    end
end
  end
end
  if string.len(lootStr) > 0 then table.insert(lineArray, lootStr) end
if string.len(lootStr) > 0 then table.insert(lineArray, lootStr) end
  if string.len(upgradeStr) > 0 then table.insert(lineArray, upgradeStr) end
if string.len(upgradeStr) > 0 then table.insert(lineArray, upgradeStr) end
  if string.len(cookStr) > 0 then table.insert(lineArray, cookStr) end
if string.len(cookStr) > 0 then table.insert(lineArray, cookStr) end
  if string.len(growStr) > 0 then table.insert(lineArray, growStr) end
if string.len(growStr) > 0 then table.insert(lineArray, growStr) end


  --Next: Can we take it from somebody else -without- killing them?
--Next: Can we take it from somebody else -without- killing them?
  local thiefItems = GatheringSkills.getThievingSourcesForItem(item.id)
local thiefItems = GatheringSkills.getThievingSourcesForItem(item.id)
  local thiefStr = ''
local thiefStr = ''
  if Shared.tableCount(thiefItems) > 0 then
if Shared.tableCount(thiefItems) > 0 then
  thiefStr = 'Pickpocketing: '
thiefStr = 'Pickpocketing: '
  for i, thiefRow in pairs(thiefItems) do
for i, thiefRow in pairs(thiefItems) do
  if thiefRow.npc == 'all' then
if thiefRow.npc == 'all' then
  --if 'any' is the npc, this is a rare item so just say 'Thieving level 1'
--if 'any' is the npc, this is a rare item so just say 'Thieving level 1'
  thiefStr = Icons._SkillReq('Thieving', 1)
thiefStr = Icons._SkillReq('Thieving', 1)
  else
else
  if i > 1 then thiefStr = thiefStr..', ' end
if i > 1 then thiefStr = thiefStr..', ' end
  thiefStr = thiefStr..Icons.Icon({thiefRow.npc, type='thieving', notext='true'})
thiefStr = thiefStr..Icons.Icon({thiefRow.npc, type='thieving', notext='true'})
  end
end
  end
end
  end
end
  if string.len(thiefStr) > 0 then table.insert(lineArray, thiefStr) end
if string.len(thiefStr) > 0 then table.insert(lineArray, thiefStr) end


  --If all else fails, I guess we should check if we can make it ourselves
--If all else fails, I guess we should check if we can make it ourselves
  --AstrologyCheck
--AstrologyCheck
  --(Just a brute force for now because only two items and I'm lazy)
--(Just a brute force for now because only two items and I'm lazy)
  if item.name == 'Stardust' or item.name == 'Golden Stardust' then
if item.name == 'Stardust' or item.name == 'Golden Stardust' then
  table.insert(lineArray, Icons.Icon({"Astrology", type="skill"}))
table.insert(lineArray, Icons.Icon({"Astrology", type="skill"}))
  end
end


  --SmithCheck:
--SmithCheck:
  if item.smithingLevel ~= nil then
if item.smithingLevel ~= nil then
    table.insert(lineArray, Icons._SkillReq("Smithing", item.smithingLevel))
table.insert(lineArray, Icons._SkillReq("Smithing", item.smithingLevel))
  end
end


  --CraftCheck:
--CraftCheck:
  if item.craftingLevel ~= nil then
if item.craftingLevel ~= nil then
    table.insert(lineArray, Icons._SkillReq("Crafting", item.craftingLevel))
table.insert(lineArray, Icons._SkillReq("Crafting", item.craftingLevel))
  end
end


  --FletchCheck:
--FletchCheck:
  if item.fletchingLevel ~= nil then
if item.fletchingLevel ~= nil then
    table.insert(lineArray, Icons._SkillReq("Fletching", item.fletchingLevel))
table.insert(lineArray, Icons._SkillReq("Fletching", item.fletchingLevel))
  end
end


  --RunecraftCheck:
--RunecraftCheck:
  if item.runecraftingLevel ~= nil then
if item.runecraftingLevel ~= nil then
    table.insert(lineArray, Icons._SkillReq("Runecrafting", item.runecraftingLevel))
table.insert(lineArray, Icons._SkillReq("Runecrafting", item.runecraftingLevel))
  end
end


  --CookCheck
--CookCheck
  if item.cookingLevel ~= nil and item.recipeRequirements ~= nil then
if item.cookingLevel ~= nil and item.recipeRequirements ~= nil then
  table.insert(lineArray, Icons._SkillReq('Cooking', item.cookingLevel))
table.insert(lineArray, Icons._SkillReq('Cooking', item.cookingLevel))
  end
end


  --MineCheck:
--MineCheck:
  if item.masteryID ~= nil and item.masteryID[1] == 4 then
if item.masteryID ~= nil and item.masteryID[1] == 4 then
    table.insert(lineArray, Icons._SkillReq("Mining", SkillData.Mining.Rocks[item.masteryID[2] + 1].levelRequired))
table.insert(lineArray, Icons._SkillReq("Mining", SkillData.Mining.Rocks[item.masteryID[2] + 1].levelRequired))
  end
end


  --FishCheck:
--FishCheck:
  if (item.category == "Fishing" and (item.type == "Junk" or item.type == "Special")) then
if (item.category == "Fishing" and (item.type == "Junk" or item.type == "Special")) then
    table.insert(lineArray, Icons.Icon({"Fishing", type='skill', notext=true})..' [[Fishing#'..item.type..'|'..item.type..']]')
table.insert(lineArray, Icons.Icon({"Fishing", type='skill', notext=true})..' [[Fishing#'..item.type..'|'..item.type..']]')
  elseif item.fishingLevel ~= nil then
elseif item.fishingLevel ~= nil then
    table.insert(lineArray, Icons._SkillReq("Fishing", item.fishingLevel))
table.insert(lineArray, Icons._SkillReq("Fishing", item.fishingLevel))
  end
end


  --HerbCheck:
--HerbCheck:
  if item.masteryID ~= nil and item.masteryID[1] == 19 then
if item.masteryID ~= nil and item.masteryID[1] == 19 then
    local potionData = SkillData.Herblore.ItemData[item.masteryID[2] + 1].level
local potionData = SkillData.Herblore.ItemData[item.masteryID[2] + 1].level
    table.insert(lineArray, Icons._SkillReq("Herblore", potionData))
table.insert(lineArray, Icons._SkillReq("Herblore", potionData))
  end
end


  --WoodcuttingCheck:
--WoodcuttingCheck:
  if item.type == 'Logs' then
if item.type == 'Logs' then
    local treeData = SkillData.Woodcutting.Trees[item.id + 1]
local treeData = SkillData.Woodcutting.Trees[item.id + 1]
    local lvl = treeData.level
local lvl = treeData.level
    table.insert(lineArray, Icons._SkillReq("Woodcutting", lvl))
table.insert(lineArray, Icons._SkillReq("Woodcutting", lvl))
  end
end


  --SummoningCheck:
--SummoningCheck:
  if item.summoningLevel ~= nil then
if item.summoningLevel ~= nil then
    table.insert(lineArray, Icons._SkillReq("Summoning", item.summoningLevel))
table.insert(lineArray, Icons._SkillReq("Summoning", item.summoningLevel))
  end
end


  --Finally there are some weird exceptions:
--Finally there are some weird exceptions:
  --Coal can be acquired via firemaking
--Coal can be acquired via firemaking
  if item.name == "Coal Ore" then
if item.name == "Coal Ore" then
    table.insert(lineArray, Icons._SkillReq("Firemaking", 1))
table.insert(lineArray, Icons._SkillReq("Firemaking", 1))
  end
end


  --Gems can be acquired from mining, fishing, and alt. magic
--Gems can be acquired from mining, fishing, and alt. magic
  if item.type == 'Gem' and item.name ~= 'Jadestone' then
if item.type == 'Gem' and item.name ~= 'Jadestone' then
    table.insert(lineArray, Icons.Icon({"Fishing", type='skill', notext=true})..' [[Fishing#Special|Special]]')
table.insert(lineArray, Icons.Icon({"Fishing", type='skill', notext=true})..' [[Fishing#Special|Special]]')
    table.insert(lineArray, Icons.Icon({"Mining", type='skill', notext=true})..' [[Mining#Gems|Gem]]')
table.insert(lineArray, Icons.Icon({"Mining", type='skill', notext=true})..' [[Mining#Gems|Gem]]')
    table.insert(lineArray, Icons.Icon({"Alt. Magic", type='skill'}))
table.insert(lineArray, Icons.Icon({"Alt. Magic", type='skill'}))
  end
end


  --Bars and some other stuff can also be acquired via Alt. Magic
--Bars and some other stuff can also be acquired via Alt. Magic
  if item.type == 'Bar' or Shared.contains(Items.AltMagicProducts, item.name) then
if item.type == 'Bar' or Shared.contains(Items.AltMagicProducts, item.name) then
    table.insert(lineArray, Icons.Icon({"Alt. Magic", type='skill'}))
table.insert(lineArray, Icons.Icon({"Alt. Magic", type='skill'}))
  end
end


  --Rhaelyx pieces are also special
--Rhaelyx pieces are also special
  if Shared.contains({'Circlet of Rhaelyx', 'Jewel of Rhaelyx', 'Mysterious Stone'}, item.name) then
if Shared.contains({'Circlet of Rhaelyx', 'Jewel of Rhaelyx', 'Mysterious Stone'}, item.name) then
    local rhaSkills = {
local rhaSkills = {
      Circlet = {'Woodcutting', 'Fishing', 'Mining', 'Thieving', 'Farming', 'Agility', 'Astrology'},
Circlet = {'Woodcutting', 'Fishing', 'Mining', 'Thieving', 'Farming', 'Agility', 'Astrology'},
      Jewel = {'Firemaking', 'Cooking', 'Smithing', 'Fletching', 'Crafting', 'Runecrafting', 'Herblore', 'Summoning'}
Jewel = {'Firemaking', 'Cooking', 'Smithing', 'Fletching', 'Crafting', 'Runecrafting', 'Herblore', 'Summoning'}
    }
}
    local rhaSkList = {}
local rhaSkList = {}
    if item.name == 'Circlet of Rhaelyx' then
if item.name == 'Circlet of Rhaelyx' then
      rhaSkList = rhaSkills.Circlet
rhaSkList = rhaSkills.Circlet
    elseif item.name == 'Jewel of Rhaelyx' then
elseif item.name == 'Jewel of Rhaelyx' then
      rhaSkList = rhaSkills.Jewel
rhaSkList = rhaSkills.Jewel
    elseif item.name == 'Mysterious Stone' then
elseif item.name == 'Mysterious Stone' then
      rhaSkList = rhaSkills.Jewel
rhaSkList = rhaSkills.Jewel
      for i, v in ipairs(rhaSkills.Circlet) do
for i, v in ipairs(rhaSkills.Circlet) do
        table.insert(rhaSkList, v)
table.insert(rhaSkList, v)
      end
end
    end
end


    local rhaStrPart = {}
local rhaStrPart = {}
    for i, skillName in ipairs(rhaSkList) do
for i, skillName in ipairs(rhaSkList) do
      table.insert(rhaStrPart, Icons.Icon({skillName, type='skill', notext=true}))
table.insert(rhaStrPart, Icons.Icon({skillName, type='skill', notext=true}))
    end
end
    local rhaStr = 'Any action in: ' .. table.concat(rhaStrPart, ', ')
local rhaStr = 'Any action in: ' .. table.concat(rhaStrPart, ', ')
    if item.name == 'Mysterious Stone' then rhaStr = rhaStr .. '<br/>after finding ' .. Icons.Icon({'Crown of Rhaelyx', type='item'}) end
if item.name == 'Mysterious Stone' then rhaStr = rhaStr .. '<br/>after finding ' .. Icons.Icon({'Crown of Rhaelyx', type='item'}) end
    table.insert(lineArray, rhaStr)
table.insert(lineArray, rhaStr)
  end
end


  --Tokens are from the appropriate skill
--Tokens are from the appropriate skill
  if item.isToken and item.skill ~= nil then
if item.isToken and item.skill ~= nil then
    table.insert(lineArray, Icons._SkillReq(Constants.getSkillName(item.skill), 1))
table.insert(lineArray, Icons._SkillReq(Constants.getSkillName(item.skill), 1))
  end
end


  --Shop items (including special items like gloves that aren't otherwise listed)
--Shop items (including special items like gloves that aren't otherwise listed)
  local shopSources = Shop.getItemSourceArray(item.id)
local shopSources = Shop.getItemSourceArray(item.id)
  if Shared.tableCount(shopSources) > 0 then
if Shared.tableCount(shopSources) > 0 then
    table.insert(lineArray, Icons.Icon({'Shop'}))
table.insert(lineArray, Icons.Icon({'Shop'}))
  end
end


  --Easter Eggs (manual list 'cause don't have a better way to do that)
--Easter Eggs (manual list 'cause don't have a better way to do that)
  if Shared.contains(Items.EasterEggs, item.name) then
if Shared.contains(Items.EasterEggs, item.name) then
    table.insert(lineArray, '[[Easter Eggs]]')
table.insert(lineArray, '[[Easter Eggs]]')
  end
end
  -- Event exclusive items (also a manual list)
-- Event exclusive items (also a manual list)
  if Shared.contains(Items.EventItems, item.name) then
if Shared.contains(Items.EventItems, item.name) then
  table.insert(lineArray, '[[Events]]')
table.insert(lineArray, '[[Events]]')
  end
end
 
  --Gold Topaz Ring drops from any action (when not wearing a Gold Topaz Ring)
--Gold Topaz Ring drops from any action (when not wearing a Gold Topaz Ring)
  --Also handling Signet Ring things here
--Also handling Signet Ring things here
  if item.name == 'Gold Topaz Ring' then
if item.name == 'Gold Topaz Ring' then
table.insert(lineArray, 'Any non-combat action if not worn (Instead of '..Icons.Icon({"Signet Ring Half (a)", type="item"})..')')
table.insert(lineArray, 'Any non-combat action if not worn (Instead of '..Icons.Icon({"Signet Ring Half (a)", type="item"})..')')
table.insert(lineArray, 'Killing any monster if not worn (Instead of '..Icons.Icon({"Signet Ring Half (b)", type="item"})..')')
table.insert(lineArray, 'Killing any monster if not worn (Instead of '..Icons.Icon({"Signet Ring Half (b)", type="item"})..')')
  elseif item.name == 'Signet Ring Half (a)' then
elseif item.name == 'Signet Ring Half (a)' then
table.insert(lineArray, 'Any non-combat action while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
table.insert(lineArray, 'Any non-combat action while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
  elseif item.name == 'Signet Ring Half (b)' then
elseif item.name == 'Signet Ring Half (b)' then
    table.insert(lineArray, 'Killing any monster while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
table.insert(lineArray, 'Killing any monster while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
  end
end


  local resultPart = {}
local resultPart = {}
  if asList then
if asList then
    table.insert(resultPart, '* '..table.concat(lineArray, "\r\n* "))
table.insert(resultPart, '* '..table.concat(lineArray, "\r\n* "))
  else
else
    table.insert(resultPart, '<div style="max-width:180px;text-align:right">' .. table.concat(lineArray, "<br/>") .. '</div>')
table.insert(resultPart, '<div style="max-width:180px;text-align:right">' .. table.concat(lineArray, "<br/>") .. '</div>')
  end
end
  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.getItemSources(frame)
function p.getItemSources(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 asList = false
local asList = false
  local addCategories = false
local addCategories = 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'
    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'
  end
end
  if item == nil then
if item == nil then
    return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
end


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


function p._getItemLootSourceTable(item)
function p._getItemLootSourceTable(item)
  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
  table.insert(resultPart, '\r\n|- class="headerRow-0"')
table.insert(resultPart, '\r\n|- class="headerRow-0"')
  table.insert(resultPart, '\r\n!Source!!Source Type!!Quantity!!colspan="2"|Chance')
table.insert(resultPart, '\r\n!Source!!Source Type!!Quantity!!colspan="2"|Chance')


  --Set up function for adding rows
--Set up function for adding rows
  local buildRow = function(source, type, minqty, qty, weight, totalWeight)
local buildRow = function(source, type, minqty, qty, weight, totalWeight)
    if minqty == nil then minqty = 1 end
if minqty == nil then minqty = 1 end
    local rowPart = {}
local rowPart = {}
    table.insert(rowPart, '\r\n|-')
table.insert(rowPart, '\r\n|-')
    table.insert(rowPart, '\r\n|style="text-align: left;"|'..source)
table.insert(rowPart, '\r\n|style="text-align: left;"|'..source)
    table.insert(rowPart, '\r\n|style="text-align: left;"|'..type)
table.insert(rowPart, '\r\n|style="text-align: left;"|'..type)


    table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="'..qty..'"|'..minqty)
table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="'..qty..'"|'..minqty)
    if qty ~= minqty then table.insert(rowPart, ' - '..qty) end
if qty ~= minqty then table.insert(rowPart, ' - '..qty) end
    local chance = Shared.round(weight / totalWeight * 100, 2, 2)
local chance = Shared.round(weight / totalWeight * 100, 2, 2)
    if weight >= totalWeight then
if weight >= totalWeight then
      -- Fraction would be 1/1, so only show the percentage
-- Fraction would be 1/1, so only show the percentage
      chance = 100
chance = 100
      table.insert(rowPart, '\r\n|colspan="2" ')
table.insert(rowPart, '\r\n|colspan="2" ')
    else
else
local fraction = Shared.fraction(weight, totalWeight)
local fraction = Shared.fraction(weight, totalWeight)
if Shared.contains(fraction, '%.') then
if Shared.contains(fraction, '%.') then
Line 638: Line 638:
table.insert(rowPart, '\r\n|colspan="2" ')
table.insert(rowPart, '\r\n|colspan="2" ')
else
else
    table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="' .. chance .. '"| ' .. Shared.fraction(weight, totalWeight) .. '\r\n|')
table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="' .. chance .. '"| ' .. Shared.fraction(weight, totalWeight) .. '\r\n|')
    end
end
    end
end
    if weight == -1 then
if weight == -1 then
    --Weight of -1 means this is a weird row that has a variable percentage
--Weight of -1 means this is a weird row that has a variable percentage
    table.insert(rowPart, 'style="text-align: right;" data-sort-value="0"|Varies (see Thieving page)')
table.insert(rowPart, 'style="text-align: right;" data-sort-value="0"|Varies (see Thieving page)')
    else
else
    table.insert(rowPart, 'style="text-align: right;" data-sort-value="'.. chance .. '"|'..chance..'%')
table.insert(rowPart, 'style="text-align: right;" data-sort-value="'.. chance .. '"|'..chance..'%')
    end
end
    return table.concat(rowPart)
return table.concat(rowPart)
  end
end
  local dropRows = {}
local dropRows = {}


  --Alright, time to go through a few ways to get the item
--Alright, time to go through a few ways to get the item
  --First up: Can we kill somebody and take theirs?
--First up: Can we kill somebody and take theirs?
  for i, monster in ipairs(MonsterData.Monsters) do
for i, monster in ipairs(MonsterData.Monsters) do
    local minqty = 1
local minqty = 1
    local qty = 1
local qty = 1
    local wt = 0
local wt = 0
    local totalWt = 0
local totalWt = 0
    --Only add bones if this monster has loot (ie appears outside a dungeon) and isn't a boss
--Only add bones if this monster has loot (ie appears outside a dungeon) and isn't a boss
    --... unless we're looking for Shards of course, at which point we'll take any monster with the right bones
--... unless we're looking for Shards of course, at which point we'll take any monster with the right bones
    if monster.bones == item.id and Monsters.getMonsterBones(monster) ~= nil then
if monster.bones == item.id and Monsters.getMonsterBones(monster) ~= nil then
      qty = monster.boneQty ~= nil and monster.boneQty or 1
qty = monster.boneQty ~= nil and monster.boneQty or 1
      minqty = qty
minqty = qty
      wt = 1
wt = 1
      totalWt = 1
totalWt = 1
    elseif monster.lootTable ~= nil then
elseif monster.lootTable ~= nil then
  -- If the monster has a loot table, check if the item we are looking for is in there
-- If the monster has a loot table, check if the item we are looking for is in there
      for j, loot in ipairs(monster.lootTable) do
for j, loot in ipairs(monster.lootTable) do
        totalWt = totalWt + loot[2]
totalWt = totalWt + loot[2]
        if loot[1] == item.id then
if loot[1] == item.id then
          wt = loot[2]
wt = loot[2]
          qty = loot[3]
qty = loot[3]
        end
end
      end
end
    end
end
    local lootChance = monster.lootChance ~= nil and monster.bones ~= item.id and monster.lootChance or 100
local lootChance = monster.lootChance ~= nil and monster.bones ~= item.id and monster.lootChance or 100


if wt > 0 and lootChance > 0 then
if wt > 0 and lootChance > 0 then
  if not Shared.contains(item.name, 'Shard') and Monsters._isDungeonOnlyMonster(monster) then
if not Shared.contains(item.name, 'Shard') and Monsters._isDungeonOnlyMonster(monster) then
-- For dungeon exclusive monsters, loot is only rolled when they are the last
-- For dungeon exclusive monsters, loot is only rolled when they are the last
  -- monster within that dungeon (unless it is a shard)
-- monster within that dungeon (unless it is a shard)
if monster.isBoss then
if monster.isBoss then
  local areaList = Areas.getMonsterAreas(monster.id)
local areaList = Areas.getMonsterAreas(monster.id)
  for k, area in ipairs(areaList) do
for k, area in ipairs(areaList) do
            if area.type == 'dungeon' and area.monsters[#area.monsters] == monster.id then
  if area.type == 'dungeon' and area.monsters[#area.monsters] == monster.id then
  table.insert(dropRows, {source = Icons.Icon({area.name, type='dungeon'}), type = '[[Dungeon]]', minqty = minqty, qty = qty, weight = wt * lootChance, totalWeight = totalWt * 100})
table.insert(dropRows, {source = Icons.Icon({area.name, type='dungeon'}), type = '[[Dungeon]]', minqty = minqty, qty = qty, weight = wt * lootChance, totalWeight = totalWt * 100})
    end
end
  end
end
    end
end
  else
else
        -- Item is not an end of dungeon reward, and drops when the monster is killed
-- Item is not an end of dungeon reward, and drops when the monster is killed
table.insert(dropRows, {source = Icons.Icon({monster.name, type='monster'}), type = '[[Monster]]', minqty = minqty, qty = qty, weight = wt * lootChance, totalWeight = totalWt * 100})
table.insert(dropRows, {source = Icons.Icon({monster.name, type='monster'}), type = '[[Monster]]', minqty = minqty, qty = qty, weight = wt * lootChance, totalWeight = totalWt * 100})
  end
end
end
end
-- Is the item dropped from a cycle of the Impending Darkness event?
for i, eventItemID in ipairs(Areas.eventData.rewards) do
if item.id == eventItemID then
sourceTxt = Icons.Icon({'Impending Darkness Event', type='dungeon'}) .. (i == Shared.tableCount(Areas.eventData.rewards) and '' or ', Cycle ' .. i)
table.insert(dropRows, {source = sourceTxt, type = '[[Dungeon]]', minqty = 1, qty = 1, weight = 1, totalWeight = 1})
break
end
end
--Special exception for the Fire/Infernal Cape and first two lore books as bonus dungeon drops
if sourceOverrides['Dungeon'][item.id] ~= nil then
local sourceTxt = Icons.Icon({sourceOverrides['Dungeon'][item.id], type='dungeon'})
table.insert(dropRows, {source = sourceTxt, type = '[[Dungeon]]', minqty = 1, qty = 1, weight = 1, totalWeight = 1})
end
end
  end
  -- Is the item dropped from a cycle of the Impending Darkness event?
  for i, eventItemID in ipairs(Areas.eventData.rewards) do
  if item.id == eventItemID then
    sourceTxt = Icons.Icon({'Impending Darkness Event', type='dungeon'}) .. (i == Shared.tableCount(Areas.eventData.rewards) and '' or ', Cycle ' .. i)
    table.insert(dropRows, {source = sourceTxt, type = '[[Dungeon]]', minqty = 1, qty = 1, weight = 1, totalWeight = 1})
    break
  end
  end
  --Special exception for the Fire/Infernal Cape and first two lore books as bonus dungeon drops
  if sourceOverrides['Dungeon'][item.id] ~= nil then
    local sourceTxt = Icons.Icon({sourceOverrides['Dungeon'][item.id], type='dungeon'})
    table.insert(dropRows, {source = sourceTxt, type = '[[Dungeon]]', minqty = 1, qty = 1, weight = 1, totalWeight = 1})
  end


  --Next: Can we find it by rummaging around in another item?
--Next: Can we find it by rummaging around in another item?
  for i, item2 in pairs(ItemData.Items) do
for i, item2 in pairs(ItemData.Items) do
    if item2.dropTable ~= nil then
if item2.dropTable ~= nil then
      local qty = 1
local qty = 1
      local wt = 0
local wt = 0
      local totalWt = 0
local totalWt = 0
      for j, loot in pairs(item2.dropTable) do
for j, loot in pairs(item2.dropTable) do
        totalWt = totalWt + loot[2]
totalWt = totalWt + loot[2]
        if loot[1] == item.id then
if loot[1] == item.id then
          wt = loot[2]
wt = loot[2]
          if item2.dropQty ~= nil then qty = item2.dropQty[j] end
if item2.dropQty ~= nil then qty = item2.dropQty[j] end
        end
end
      end
end


      if wt > 0 then
if wt > 0 then
        local sourceTxt = Icons.Icon({item2.name, type='item'})
local sourceTxt = Icons.Icon({item2.name, type='item'})
        table.insert(dropRows, {source = sourceTxt, type = '[[Chest]]', minqty = 1, qty = qty, weight = wt, totalWeight = totalWt})
table.insert(dropRows, {source = sourceTxt, type = '[[Chest]]', minqty = 1, qty = qty, weight = wt, totalWeight = totalWt})
      end
end
    end
end
  end
end


  --Finally, let's try just stealing it
--Finally, let's try just stealing it
  local thiefType = Icons.Icon({"Thieving", type='skill'})
local thiefType = Icons.Icon({"Thieving", type='skill'})
  local thiefItems = GatheringSkills.getThievingSourcesForItem(item.id)
local thiefItems = GatheringSkills.getThievingSourcesForItem(item.id)
  for i, thiefRow in pairs(thiefItems) do
for i, thiefRow in pairs(thiefItems) do
  local sourceTxt = ''
local sourceTxt = ''
    if thiefRow.npc == 'all' then
if thiefRow.npc == 'all' then
    sourceTxt = "Thieving Rare Drop"
sourceTxt = "Thieving Rare Drop"
    else
else
    sourceTxt = Icons.Icon({thiefRow.npc, type='thieving'})
sourceTxt = Icons.Icon({thiefRow.npc, type='thieving'})
end
table.insert(dropRows, {source = sourceTxt, type = thiefType, minqty = thiefRow.minQty, qty = thiefRow.maxQty, weight = thiefRow.wt, totalWeight = thiefRow.totalWt})
end
end
    table.insert(dropRows, {source = sourceTxt, type = thiefType, minqty = thiefRow.minQty, qty = thiefRow.maxQty, weight = thiefRow.wt, totalWeight = thiefRow.totalWt})
  end


  --Bonus overtime: Special Fishing table & mining gem table. Also Rags to Riches
--Bonus overtime: Special Fishing table & mining gem table. Also Rags to Riches
  --Jadestone is special and doesn't count
--Jadestone is special and doesn't count
  if item.type == 'Gem' and item.name ~= 'Jadestone' then
if item.type == 'Gem' and item.name ~= 'Jadestone' then
    local mineType = Icons.Icon({'Mining', type='skill'})
local mineType = Icons.Icon({'Mining', type='skill'})
    local thisGemChance = Items.GemTable[item.name].chance
local thisGemChance = Items.GemTable[item.name].chance
    local totalGemChance = 0
local totalGemChance = 0
    for i, gem in pairs(Items.GemTable) do
for i, gem in pairs(Items.GemTable) do
      totalGemChance = totalGemChance + gem.chance
totalGemChance = totalGemChance + gem.chance
    end
end
    table.insert(dropRows, {source = '[[Mining#Gems|Gem]]', type = mineType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
table.insert(dropRows, {source = '[[Mining#Gems|Gem]]', type = mineType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
    local magicType = Icons.Icon({'Magic', type = 'skill'})
local magicType = Icons.Icon({'Magic', type = 'skill'})
    table.insert(dropRows, {source = Icons.Icon({"Rags to Riches I", type="spell"}), type = magicType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
table.insert(dropRows, {source = Icons.Icon({"Rags to Riches I", type="spell"}), type = magicType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
    table.insert(dropRows, {source = Icons.Icon({"Rags to Riches II", type="spell"}), type = magicType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
table.insert(dropRows, {source = Icons.Icon({"Rags to Riches II", type="spell"}), type = magicType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
  end
end


  if item.fishingCatchWeight ~= nil then
if item.fishingCatchWeight ~= nil then
    local fishSource = '[[Fishing#Special|Special]]'
local fishSource = '[[Fishing#Special|Special]]'
    local fishType = Icons.Icon({'Fishing', type='skill'})
local fishType = Icons.Icon({'Fishing', type='skill'})
    table.insert(dropRows, {source = fishSource, type = fishType, minqty = 1, qty = 1, weight = item.fishingCatchWeight, totalWeight = Items.specialFishWt})
table.insert(dropRows, {source = fishSource, type = fishType, minqty = 1, qty = 1, weight = item.fishingCatchWeight, totalWeight = Items.specialFishWt})
  end
end


  if item.type == 'Junk' then
if item.type == 'Junk' then
    local fishSource = '[[Fishing#Junk|Junk]]'
local fishSource = '[[Fishing#Junk|Junk]]'
    local fishType = Icons.Icon({'Fishing', type='skill'})
local fishType = Icons.Icon({'Fishing', type='skill'})
    table.insert(dropRows, {source = fishSource, type = fishType, minqty = 1, qty = 1, weight = 1, totalWeight = Items.junkCount})
table.insert(dropRows, {source = fishSource, type = fishType, minqty = 1, qty = 1, weight = 1, totalWeight = Items.junkCount})
  end
end


  --Make sure to return nothing if there are no drop sources
--Make sure to return nothing if there are no drop sources
  if Shared.tableCount(dropRows) == 0 then return '' end
if Shared.tableCount(dropRows) == 0 then return '' end


  table.sort(dropRows, function(a, b)
table.sort(dropRows, function(a, b)
                        if a.weight / a.totalWeight == b.weight / b.totalWeight then
              if a.weight / a.totalWeight == b.weight / b.totalWeight then
                          return a.minqty + a.qty > b.minqty + b.qty
                return a.minqty + a.qty > b.minqty + b.qty
                        else
              else
                          return a.weight / a.totalWeight > b.weight / b.totalWeight
                return a.weight / a.totalWeight > b.weight / b.totalWeight
                        end
              end
                      end)
            end)
  for i, data in pairs(dropRows) do
for i, data in pairs(dropRows) do
    table.insert(resultPart, buildRow(data.source, data.type, data.minqty, data.qty, data.weight, data.totalWeight))
table.insert(resultPart, buildRow(data.source, data.type, data.minqty, data.qty, data.weight, data.totalWeight))
  end
end


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


function p.getItemLootSourceTable(frame)
function p.getItemLootSourceTable(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[[Category:Pages with script errors]]"
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
end


  return p._getItemLootSourceTable(item)
return p._getItemLootSourceTable(item)
end
end


function p._getItemUpgradeTable(item)
function p._getItemUpgradeTable(item)
  local resultPart = {}
local resultPart = {}
  if item.itemsRequired ~= nil then
if item.itemsRequired ~= nil then
    --First, get details on all the required materials
--First, get details on all the required materials
    local upgradeFrom = {}
local upgradeFrom = {}
    local materials = {}
local materials = {}
    for i, row in pairs(item.itemsRequired) do
for i, row in pairs(item.itemsRequired) do
      local mat = Items.getItemByID(row[1])
local mat = Items.getItemByID(row[1])
      --Check to see if the source item can trigger the upgrade
--Check to see if the source item can trigger the upgrade
      if mat.canUpgrade or (mat.type == 'Armour' and mat.canUpgrade == nil) then
if mat.canUpgrade or (mat.type == 'Armour' and mat.canUpgrade == nil) then
        table.insert(upgradeFrom, Icons.Icon({mat.name, type='item'}))
table.insert(upgradeFrom, Icons.Icon({mat.name, type='item'}))
      end
end
      table.insert(materials, Icons.Icon({mat.name, type='item', qty=row[2]}))
table.insert(materials, Icons.Icon({mat.name, type='item', qty=row[2]}))
    end
end
    if item.trimmedGPCost ~= nil then
if item.trimmedGPCost ~= nil then
      table.insert(materials, Icons.GP(item.trimmedGPCost))
table.insert(materials, Icons.GP(item.trimmedGPCost))
    end
end
    table.insert(resultPart, '{| class="wikitable"\r\n|-\r\n!colspan="2"|[[Upgrading Items|Item Upgrade]]')
table.insert(resultPart, '{| class="wikitable"\r\n|-\r\n!colspan="2"|[[Upgrading Items|Item Upgrade]]')
    --[[result = result..'\r\n|-\r\n!style="text-align:right;"|Upgrades From\r\n|'
--[[result = result..'\r\n|-\r\n!style="text-align:right;"|Upgrades From\r\n|'
    result = result..table.concat(upgradeFrom, '<br/>')--]]
result = result..table.concat(upgradeFrom, '<br/>')--]]
    table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Materials\r\n|')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Materials\r\n|')
    table.insert(resultPart, table.concat(materials, '<br/>'))
table.insert(resultPart, table.concat(materials, '<br/>'))
    table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')
  end
end
  return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.getItemUpgradeTable(frame)
function p.getItemUpgradeTable(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[[Category:Pages with script errors]]"
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
end


  return p._getItemUpgradeTable(item)
return p._getItemUpgradeTable(item)
end
end


function p._getItemSuperheatTable(item)
function p._getItemSuperheatTable(item)
  --Manually build the Superheat Item table
--Manually build the Superheat Item table
  local oreString = ''
local oreString = ''
  local coalString = ''
local coalString = ''
  for i, mat in pairs(item.smithReq) do
for i, mat in pairs(item.smithReq) do
    local thisMat = Items.getItemByID(mat.id)
local thisMat = Items.getItemByID(mat.id)
    if thisMat.name == 'Coal Ore' then
if thisMat.name == 'Coal Ore' then
      coalString = ', '..Icons.Icon({thisMat.name, type='item', notext='true', qty=mat.qty})
coalString = ', '..Icons.Icon({thisMat.name, type='item', notext='true', qty=mat.qty})
    else
else
      if string.len(oreString) > 0 then oreString = oreString..', ' end
if string.len(oreString) > 0 then oreString = oreString..', ' end
      oreString =  oreString..Icons.Icon({thisMat.name, type='item', notext='true', qty=mat.qty})
oreString =  oreString..Icons.Icon({thisMat.name, type='item', notext='true', qty=mat.qty})
    end
end
  end
end
  --Set up the header
--Set up the header
  local superheatTable = {}
local superheatTable = {}
  table.insert(superheatTable, '{|class="wikitable"\r\n!colspan="2"|Spell')
table.insert(superheatTable, '{|class="wikitable"\r\n!colspan="2"|Spell')
  table.insert(superheatTable, '!!'..Icons.Icon({'Smithing', type='skill', notext='true'})..' Level')
table.insert(superheatTable, '!!'..Icons.Icon({'Smithing', type='skill', notext='true'})..' Level')
  table.insert(superheatTable, '!!'..Icons.Icon({'Magic', type='skill', notext='true'})..' Level')
table.insert(superheatTable, '!!'..Icons.Icon({'Magic', type='skill', notext='true'})..' Level')
  table.insert(superheatTable, '!!'..Icons.Icon({'Magic', type='skill', notext='true'})..' XP')
table.insert(superheatTable, '!!'..Icons.Icon({'Magic', type='skill', notext='true'})..' XP')
  table.insert(superheatTable, '!!'..Icons.Icon({item.name, type='item', notext='true'})..' Bars')
table.insert(superheatTable, '!!'..Icons.Icon({item.name, type='item', notext='true'})..' Bars')
  table.insert(superheatTable, '!!Ore!!Runes')
table.insert(superheatTable, '!!Ore!!Runes')
  --Loop through all the variants
--Loop through all the variants
  local spellNames = {'Superheat I', 'Superheat II', 'Superheat III', 'Superheat IV'}
local spellNames = {'Superheat I', 'Superheat II', 'Superheat III', 'Superheat IV'}
  for i, sName in pairs(spellNames) do
for i, sName in pairs(spellNames) do
    local spell = Magic.getSpell(sName, 'AltMagic')
local spell = Magic.getSpell(sName, 'AltMagic')
    local rowPart = {}
local rowPart = {}
    table.insert(rowPart, '\r\n|-\r\n|'..Icons.Icon({spell.name, type='spell', notext=true, size=50}))
table.insert(rowPart, '\r\n|-\r\n|'..Icons.Icon({spell.name, type='spell', notext=true, size=50}))
    table.insert(rowPart, '||'..Icons.Icon({spell.name, type='spell', noicon=true})..'||style="text-align:right;"|'..item.smithingLevel)
table.insert(rowPart, '||'..Icons.Icon({spell.name, type='spell', noicon=true})..'||style="text-align:right;"|'..item.smithingLevel)
    table.insert(rowPart, '||style="text-align:right;"|'..spell.level..'||style="text-align:right;"|'..spell.magicXP..'||style="text-align:right;"|'..spell.convertToQty)
table.insert(rowPart, '||style="text-align:right;"|'..spell.level..'||style="text-align:right;"|'..spell.magicXP..'||style="text-align:right;"|'..spell.convertToQty)
    table.insert(rowPart, '||'..oreString)
table.insert(rowPart, '||'..oreString)
    if spell.ignoreCoal ~= nil and not spell.ignoreCoal then table.insert(rowPart, coalString) end
if spell.ignoreCoal ~= nil and not spell.ignoreCoal then table.insert(rowPart, coalString) end
    table.insert(rowPart, '||style="text-align:center"|')
table.insert(rowPart, '||style="text-align:center"|')
    for i, req in pairs(spell.runesRequired) do
for i, req in pairs(spell.runesRequired) do
      local rune = Items.getItemByID(req.id)
local rune = Items.getItemByID(req.id)
      if i > 1 then table.insert(rowPart, ', ') end
if i > 1 then table.insert(rowPart, ', ') end
      table.insert(rowPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
table.insert(rowPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
    end
end
    table.insert(rowPart, "<br/>'''OR'''<br/>")
table.insert(rowPart, "<br/>'''OR'''<br/>")
    for i, req in pairs(spell.runesRequiredAlt) do
for i, req in pairs(spell.runesRequiredAlt) do
      local rune = Items.getItemByID(req.id)
local rune = Items.getItemByID(req.id)
      if i > 1 then table.insert(rowPart, ', ') end
if i > 1 then table.insert(rowPart, ', ') end
      table.insert(rowPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
table.insert(rowPart, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
    end
end
    table.insert(superheatTable, table.concat(rowPart))
table.insert(superheatTable, 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(superheatTable, '\r\n|}')
table.insert(superheatTable, '\r\n|}')
  return table.concat(superheatTable)
return table.concat(superheatTable)
end
end


function p.getItemSuperheatTable(frame)
function p.getItemSuperheatTable(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[[Category:Pages with script errors]]"
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
end


  return p._getItemSuperheatTable(item)
return p._getItemSuperheatTable(item)
end
end


function p._getItemSourceTables(item)
function p._getItemSourceTables(item)
  local resultPart = {}
local resultPart = {}
  local shopTable = Shop._getItemShopTable(item)
local shopTable = Shop._getItemShopTable(item)
  if string.len(shopTable) > 0 then
if string.len(shopTable) > 0 then
    table.insert(resultPart, '===Shop===\r\n'..shopTable)
table.insert(resultPart, '===Shop===\r\n'..shopTable)
  end
end


  local creationTable = p._getCreationTable(item)
local creationTable = p._getCreationTable(item)
  if string.len(creationTable) > 0 then
if string.len(creationTable) > 0 then
    if #resultPart > 0 then table.insert(resultPart, '\r\n') end
if #resultPart > 0 then table.insert(resultPart, '\r\n') end
    table.insert(resultPart, '===Creation===\r\n'..creationTable)
table.insert(resultPart, '===Creation===\r\n'..creationTable)
  end
end


  local upgradeTable = p._getItemUpgradeTable(item)
local upgradeTable = p._getItemUpgradeTable(item)
  if string.len(upgradeTable) > 0 then
if string.len(upgradeTable) > 0 then
    if #resultPart > 0 then table.insert(resultPart, '\r\n') end
if #resultPart > 0 then table.insert(resultPart, '\r\n') end
    if string.len(creationTable) == 0 then table.insert(resultPart, '===Creation===\r\n') end
if string.len(creationTable) == 0 then table.insert(resultPart, '===Creation===\r\n') end
    table.insert(resultPart, upgradeTable)
table.insert(resultPart, upgradeTable)
  end
end


  if item.type == 'Bar' then
if item.type == 'Bar' then
    table.insert(resultPart, '\r\n==='..Icons.Icon({'Alt Magic', type='skill'})..'===\r\n'..p._getItemSuperheatTable(item))
table.insert(resultPart, '\r\n==='..Icons.Icon({'Alt Magic', type='skill'})..'===\r\n'..p._getItemSuperheatTable(item))
  end
end


  local lootTable = p._getItemLootSourceTable(item)
local lootTable = p._getItemLootSourceTable(item)
  if string.len(lootTable) > 0 then
if string.len(lootTable) > 0 then
    if #resultPart > 0 then table.insert(resultPart, '\r\n') end
if #resultPart > 0 then table.insert(resultPart, '\r\n') end
    table.insert(resultPart, '===Loot===\r\n'..lootTable)
table.insert(resultPart, '===Loot===\r\n'..lootTable)
  end
end
  return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.getItemSourceTables(frame)
function p.getItemSourceTables(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[[Category:Pages with script errors]]"
return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
end


  return p._getItemSourceTables(item)
return p._getItemSourceTables(item)
end
end


function p.getCombatPassiveSlotItems(frame)
function p.getCombatPassiveSlotItems(frame)
  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{| class="wikitable"\r\n')
table.insert(resultPart, '{| class="wikitable"\r\n')
  table.insert(resultPart, '|-\r\n')
table.insert(resultPart, '|-\r\n')
  table.insert(resultPart, '!colspan="2"|Item\r\n! Passive\r\n')
table.insert(resultPart, '!colspan="2"|Item\r\n! Passive\r\n')


  local itemArray = Items.getItems(function(item) return item.validSlots ~= nil and Shared.contains(item.validSlots, 'Passive') end)
local itemArray = Items.getItems(function(item) return item.validSlots ~= nil and Shared.contains(item.validSlots, 'Passive') end)


  table.sort(itemArray, function(a, b) return a.id < b.id end)
table.sort(itemArray, function(a, b) return a.id < b.id end)


  for i, item in ipairs(itemArray) do
for i, item in ipairs(itemArray) do
    table.insert(resultPart, '|-\r\n')
table.insert(resultPart, '|-\r\n')
    table.insert(resultPart, '! '..Icons.Icon({item.name, type='item', notext='true'})..'\r\n! '..Icons.Icon({item.name, type='item', noicon=true})..'\r\n')
table.insert(resultPart, '! '..Icons.Icon({item.name, type='item', notext='true'})..'\r\n! '..Icons.Icon({item.name, type='item', noicon=true})..'\r\n')
    table.insert(resultPart, '| '..item.description..'\r\n')
table.insert(resultPart, '| '..item.description..'\r\n')
  end
end


  table.insert(resultPart, '|}')
table.insert(resultPart, '|}')


  return table.concat(resultPart)
return table.concat(resultPart)
end
end


return p
return p