Module:Navboxes: Difference between revisions

1,258 bytes removed ,  6 January 2022
Use tabs instead of spaces for indentation
(getPotionNavbox: Link to general potion pages rather than tier I potion specifically)
(Use tabs instead of spaces for indentation)
Line 13: Line 13:


function p.getFarmingNavbox(frame)
function p.getFarmingNavbox(frame)
  local resultPart = {}
local resultPart = {}
  local seedsTable = {}
local seedsTable = {}
  local produceTable = {}
local produceTable = {}


  for i, item in ipairs(ItemData.Items) do
for i, item in ipairs(ItemData.Items) do
    if item.farmingLevel ~= nil then
if item.farmingLevel ~= nil then
      local tier = item.tier
local tier = item.tier
      if seedsTable[tier] == nil then
if seedsTable[tier] == nil then
        -- Initialise tier tables
-- Initialise tier tables
        seedsTable[tier] = {}
seedsTable[tier] = {}
        produceTable[tier] = {}
produceTable[tier] = {}
      end
end


      if item.grownItemID ~= nil then
if item.grownItemID ~= nil then
        local grownItem = Items.getItemByID(item.grownItemID)
local grownItem = Items.getItemByID(item.grownItemID)
        if grownItem ~= nil then
if grownItem ~= nil then
          table.insert(produceTable[tier], { ["name"] = grownItem.name, ["level"] = item.farmingLevel })
table.insert(produceTable[tier], { ["name"] = grownItem.name, ["level"] = item.farmingLevel })
        end
end
      end
end
      table.insert(seedsTable[tier], { ["name"] = item.name, ["level"] = item.farmingLevel })
table.insert(seedsTable[tier], { ["name"] = item.name, ["level"] = item.farmingLevel })
    end
end
  end
end


  -- Generate output table
-- Generate output table
  table.insert(resultPart, '{| class="wikitable mw-collapsible" style="margin:auto; clear:both; width: 100%"')
table.insert(resultPart, '{| class="wikitable mw-collapsible" style="margin:auto; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n!colspan="2" style="padding-left:64px;"|' .. Icons.Icon({'Farming', type='skill'}))
table.insert(resultPart, '\r\n!colspan="2" style="padding-left:64px;"|' .. Icons.Icon({'Farming', type='skill'}))


  local getItemList = function(itemTable)
local getItemList = function(itemTable)
      local listPart = {}
local listPart = {}
      for i, item in ipairs(itemTable) do
for i, item in ipairs(itemTable) do
        table.insert(listPart, Icons.Icon({item.name, type='item'}))
table.insert(listPart, Icons.Icon({item.name, type='item'}))
      end
end
      return table.concat(listPart, ' • ')
return table.concat(listPart, ' • ')
    end
end
  local sortFunc = function(a, b) return (a.level == b.level and a.name < b.name) or a.level < b.level end
local sortFunc = function(a, b) return (a.level == b.level and a.name < b.name) or a.level < b.level end


  -- Determine tier list & order in which tiers will be listed in output
-- Determine tier list & order in which tiers will be listed in output
  local tierList = {}
local tierList = {}
  for tier, seeds in pairs(seedsTable) do
for tier, seeds in pairs(seedsTable) do
    table.insert(tierList, tier)
table.insert(tierList, tier)
  end
end
  table.sort(tierList, function(a, b) return a < b end)
table.sort(tierList, function(a, b) return a < b end)


  -- Generate table section for each tier
-- Generate table section for each tier
  for i, tier in pairs(tierList) do
for i, tier in pairs(tierList) do
    -- Sort tables by Farming level order
-- Sort tables by Farming level order
    table.sort(seedsTable[tier], sortFunc)
table.sort(seedsTable[tier], sortFunc)
    table.sort(produceTable[tier], sortFunc)
table.sort(produceTable[tier], sortFunc)


    table.insert(resultPart, '\r\n|-\r\n!colspan="2"| ' .. tier .. 's')
table.insert(resultPart, '\r\n|-\r\n!colspan="2"| ' .. tier .. 's')
    table.insert(resultPart, '\r\n|-\r\n!scope="row"| Seeds')
table.insert(resultPart, '\r\n|-\r\n!scope="row"| Seeds')
    table.insert(resultPart, '\r\n|style="text-align:center;"| ' .. getItemList(seedsTable[tier]))
table.insert(resultPart, '\r\n|style="text-align:center;"| ' .. getItemList(seedsTable[tier]))
    table.insert(resultPart, '\r\n|-\r\n!scope="row"| Produce')
table.insert(resultPart, '\r\n|-\r\n!scope="row"| Produce')
    table.insert(resultPart, '\r\n|style="text-align:center;"| ' .. getItemList(produceTable[tier]))
table.insert(resultPart, '\r\n|style="text-align:center;"| ' .. getItemList(produceTable[tier]))
  end
end
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


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


function p.getFoodNavbox(frame)
function p.getFoodNavbox(frame)
  local foundIDs, cookedFood, harvestedFood, otherFood = {}, {}, {}, {}
local foundIDs, cookedFood, harvestedFood, otherFood = {}, {}, {}, {}


  -- Hide Lemon cake
-- Hide Lemon cake
  foundIDs[1029] = true
foundIDs[1029] = true
  foundIDs[1061] = true
foundIDs[1061] = true


  -- Harvested food first
-- Harvested food first
  for i, item in ipairs(ItemData.Items) do
for i, item in ipairs(ItemData.Items) do
    if item.grownItemID ~= nil then
if item.grownItemID ~= nil then
      local grownItem = Items.getItemByID(item.grownItemID)
local grownItem = Items.getItemByID(item.grownItemID)
      if grownItem ~= nil and grownItem.canEat then
if grownItem ~= nil and grownItem.canEat then
        table.insert(harvestedFood, { ["name"] = grownItem.name, ["order"] = item.farmingLevel })
table.insert(harvestedFood, { ["name"] = grownItem.name, ["order"] = item.farmingLevel })
        foundIDs[grownItem.id] = true
foundIDs[grownItem.id] = true
      end
end
    end
end
  end
end


  -- Any cooked & other food
-- Any cooked & other food
  for i, item in ipairs(ItemData.Items) do
for i, item in ipairs(ItemData.Items) do
    -- If an item can be eaten then it must be food
-- If an item can be eaten then it must be food
    if foundIDs[i - 1] == nil and item.canEat then
if foundIDs[i - 1] == nil and item.canEat then
      if item.cookingCategory ~= nil then
if item.cookingCategory ~= nil then
        -- Item is cooked, such food items are split by category
-- Item is cooked, such food items are split by category
        if cookedFood[item.cookingCategory + 1] == nil then
if cookedFood[item.cookingCategory + 1] == nil then
          cookedFood[item.cookingCategory + 1] = {}
cookedFood[item.cookingCategory + 1] = {}
        end
end


        local perfectName = nil
local perfectName = nil
        if item.perfectItem ~= nil then
if item.perfectItem ~= nil then
          local perfectItem = Items.getItemByID(item.perfectItem)
local perfectItem = Items.getItemByID(item.perfectItem)
          if perfectItem ~= nil then
if perfectItem ~= nil then
            perfectName = perfectItem.name
perfectName = perfectItem.name
            foundIDs[item.perfectItem] = true
foundIDs[item.perfectItem] = true
          end
end
        end
end
        table.insert(cookedFood[item.cookingCategory + 1], { ["name"] = item.name, ["order"] = item.cookingLevel, ["perfectName"] = perfectName })
table.insert(cookedFood[item.cookingCategory + 1], { ["name"] = item.name, ["order"] = item.cookingLevel, ["perfectName"] = perfectName })
      else
else
        -- Item cannot be cooked or grown, but can be eaten
-- Item cannot be cooked or grown, but can be eaten
        table.insert(otherFood, { ["name"] = item.name, ["order"] = item.id })
table.insert(otherFood, { ["name"] = item.name, ["order"] = item.id })
      end
end
      foundIDs[i - 1] = true
foundIDs[i - 1] = true
    end
end
  end
end


  -- Sort food lists
-- Sort food lists
  local sortFunc = function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end
local sortFunc = function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end
  for i, items in pairs(cookedFood) do
for i, items in pairs(cookedFood) do
    table.sort(cookedFood[i], sortFunc)
table.sort(cookedFood[i], sortFunc)
  end
end
  table.sort(harvestedFood, sortFunc)
table.sort(harvestedFood, sortFunc)
  table.sort(otherFood, sortFunc)
table.sort(otherFood, sortFunc)


  -- Generate food lists for final output
-- Generate food lists for final output
  local cookingCatHeader = {
local cookingCatHeader = {
    Icons.Icon({'Normal Cooking Fire', 'Cooking Fire', type='upgrade', nolink=true}),
Icons.Icon({'Normal Cooking Fire', 'Cooking Fire', type='upgrade', nolink=true}),
    Icons.Icon({'Basic Furnace', 'Furnace', type='upgrade', nolink=true}),
Icons.Icon({'Basic Furnace', 'Furnace', type='upgrade', nolink=true}),
    Icons.Icon({'Basic Pot', 'Pot', type='upgrade', nolink=true})
Icons.Icon({'Basic Pot', 'Pot', type='upgrade', nolink=true})
  }
}
  local getFoodList = function(foodTable)
local getFoodList = function(foodTable)
      local listPart = {}
local listPart = {}
      for i, food in ipairs(foodTable) do
for i, food in ipairs(foodTable) do
        local foodText = Icons.Icon({food.name, type='item'})
local foodText = Icons.Icon({food.name, type='item'})
        if food.perfectName ~= nil then
if food.perfectName ~= nil then
          foodText = Icons.Icon({food.perfectName, type='item', notext=true}) .. ' ' .. foodText
foodText = Icons.Icon({food.perfectName, type='item', notext=true}) .. ' ' .. foodText
        end
end
        table.insert(listPart, foodText)
table.insert(listPart, foodText)
      end
end
      return table.concat(listPart, ' • ')
return table.concat(listPart, ' • ')
    end
end


  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{| class="wikitable mw-collapsible" style="margin:0 auto 10px; clear:both; width: 100%"')
table.insert(resultPart, '{| class="wikitable mw-collapsible" style="margin:0 auto 10px; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n|-\r\n!style="background-color:#275C87;color:#FFFFFF;padding-left:64px;" colspan="2"| [[File:Crab_(item).svg|25px|link=Food]] [[Food]]')
table.insert(resultPart, '\r\n|-\r\n!style="background-color:#275C87;color:#FFFFFF;padding-left:64px;" colspan="2"| [[File:Crab_(item).svg|25px|link=Food]] [[Food]]')
  table.insert(resultPart, '\r\n|-\r\n!colspan="2"| Cooked')
table.insert(resultPart, '\r\n|-\r\n!colspan="2"| Cooked')
  for catID, foodTable in ipairs(cookedFood) do
for catID, foodTable in ipairs(cookedFood) do
    table.insert(resultPart, '\r\n|-\r\n!scope="row"| ' .. cookingCatHeader[catID])
table.insert(resultPart, '\r\n|-\r\n!scope="row"| ' .. cookingCatHeader[catID])
    table.insert(resultPart, '\r\n|style="text-align:center;"| ' .. getFoodList(foodTable))
table.insert(resultPart, '\r\n|style="text-align:center;"| ' .. getFoodList(foodTable))
  end
end
  table.insert(resultPart, '\r\n|-\r\n!colspan="2"| Harvested')
table.insert(resultPart, '\r\n|-\r\n!colspan="2"| Harvested')
  table.insert(resultPart, '\r\n|-\r\n|colspan="2" style="text-align:center;"| ' .. getFoodList(harvestedFood))
table.insert(resultPart, '\r\n|-\r\n|colspan="2" style="text-align:center;"| ' .. getFoodList(harvestedFood))
  table.insert(resultPart, '\r\n|-\r\n!colspan="2"| Other')
table.insert(resultPart, '\r\n|-\r\n!colspan="2"| Other')
  table.insert(resultPart, '\r\n|-\r\n|colspan="2" style="text-align:center;"| ' .. getFoodList(otherFood))
table.insert(resultPart, '\r\n|-\r\n|colspan="2" style="text-align:center;"| ' .. getFoodList(otherFood))
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


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


function p.getPotionNavbox(frame)
function p.getPotionNavbox(frame)
  local catList = {
local catList = {
    { ["categoryID"] = 0, ["name"] = 'Combat' },
{ ["categoryID"] = 0, ["name"] = 'Combat' },
    { ["categoryID"] = 1, ["name"] = 'Skill' }
{ ["categoryID"] = 1, ["name"] = 'Skill' }
  }
}
  table.sort(catList, function(a, b) return a.name < b.name end)
table.sort(catList, function(a, b) return a.name < b.name end)


  -- Compile list of potions to be included
-- Compile list of potions to be included
  local potList = {}
local potList = {}
  for i, potData in ipairs(SkillData.Herblore.ItemData) do
for i, potData in ipairs(SkillData.Herblore.ItemData) do
    if potList[potData.category] == nil then
if potList[potData.category] == nil then
      potList[potData.category] = {}
potList[potData.category] = {}
    end
end
    local potFirstItem = Items.getItemByID(potData.itemID[1])
local potFirstItem = Items.getItemByID(potData.itemID[1])
    local potName = string.gsub(potFirstItem.name, ' Potion [IV]+$', '')
local potName = string.gsub(potFirstItem.name, ' Potion [IV]+$', '')
    table.insert(potList[potData.category], { ["name"] = potName, ["order"] = potData.level, ["img"] = potFirstItem.name })
table.insert(potList[potData.category], { ["name"] = potName, ["order"] = potData.level, ["img"] = potFirstItem.name })
  end
end


  local resultPart = {}
local resultPart = {}
  -- Generate table header
-- Generate table header
  table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n!colspan=2|' .. Icons.Icon({ 'Herblore', 'Potions', type='skill' }))
table.insert(resultPart, '\r\n!colspan=2|' .. Icons.Icon({ 'Herblore', 'Potions', type='skill' }))
  -- Generate section for each category of potions
-- Generate section for each category of potions
  for i, catData in ipairs(catList) do
for i, catData in ipairs(catList) do
    -- Compile list of potions
-- Compile list of potions
    local potListText = {}
local potListText = {}
    table.sort(potList[catData.categoryID], function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end)
table.sort(potList[catData.categoryID], function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end)
    for j, potData in ipairs(potList[catData.categoryID]) do
for j, potData in ipairs(potList[catData.categoryID]) do
      table.insert(potListText, Icons.Icon({ potData.name .. ' Potion', potData.name, img=potData.img, type='item' }))
table.insert(potListText, Icons.Icon({ potData.name .. ' Potion', potData.name, img=potData.img, type='item' }))
    end
end
    table.insert(resultPart, '\r\n|-\r\n! ' .. catData.name .. ' Potions')
table.insert(resultPart, '\r\n|-\r\n! ' .. catData.name .. ' Potions')
    table.insert(resultPart, '\r\n|class="center" style="vertical-align:middle;"| ' .. table.concat(potListText, ' • '))
table.insert(resultPart, '\r\n|class="center" style="vertical-align:middle;"| ' .. table.concat(potListText, ' • '))
  end
end
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


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


function p.getPrayerNavbox(frame)
function p.getPrayerNavbox(frame)
  local prayerList = {}
local prayerList = {}
  for i, prayer in Shared.skpairs(SkillData.Prayer) do
for i, prayer in Shared.skpairs(SkillData.Prayer) do
  table.insert(prayerList, { ["name"] = prayer.name, ["order"] = prayer.prayerLevel })
table.insert(prayerList, { ["name"] = prayer.name, ["order"] = prayer.prayerLevel })
  end
end
  table.sort(prayerList, function(a, b)
table.sort(prayerList, function(a, b)
                        if a.order == b.order then
if a.order == b.order then
                        return a.name < b.name
return a.name < b.name
                        else
else
                        return a.order < b.order
return a.order < b.order
                        end
end
                      end)
end)


  local prayerListText = {}
local prayerListText = {}
  for i, prayer in ipairs(prayerList) do
for i, prayer in ipairs(prayerList) do
  table.insert(prayerListText, Icons.Icon({ prayer.name, type='prayer' }))
table.insert(prayerListText, Icons.Icon({ prayer.name, type='prayer' }))
  end
end
 
 
  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n!'..Icons.Icon({'Prayer', 'Prayers', type='skill'}))
table.insert(resultPart, '\r\n!'..Icons.Icon({'Prayer', 'Prayers', type='skill'}))
  table.insert(resultPart, '\r\n|-\r\n|style="text-align:center;"| ' .. table.concat(prayerListText, ' • '))
table.insert(resultPart, '\r\n|-\r\n|style="text-align:center;"| ' .. table.concat(prayerListText, ' • '))
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')
  return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.getRuneNavbox(frame)
function p.getRuneNavbox(frame)
  -- Assumes all runes are from Runecrafting, which may need revising in future updates
-- Assumes all runes are from Runecrafting, which may need revising in future updates
  local runeList = { ["Standard"] = {}, ["Combination"] = {} }
local runeList = { ["Standard"] = {}, ["Combination"] = {} }
  for i, item in ipairs(ItemData.Items) do
for i, item in ipairs(ItemData.Items) do
    if item.category == 'Runecrafting' and item.type ~= nil and item.type == 'Rune' and item.runecraftingLevel ~= nil then
if item.category == 'Runecrafting' and item.type ~= nil and item.type == 'Rune' and item.runecraftingLevel ~= nil then
      local runeType = (type(item.providesRune) == 'table' and Shared.tableCount(item.providesRune) > 1 and 'Combination') or 'Standard'
local runeType = (type(item.providesRune) == 'table' and Shared.tableCount(item.providesRune) > 1 and 'Combination') or 'Standard'
      table.insert(runeList[runeType], { ["name"] = item.name, ["order"] = item.runecraftingLevel })
table.insert(runeList[runeType], { ["name"] = item.name, ["order"] = item.runecraftingLevel })
    end
end
  end
end


  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n!colspan="2"|[[File:Air_Rune_(item).svg|25px|link=Runes]] [[Runes]]')
table.insert(resultPart, '\r\n!colspan="2"|[[File:Air_Rune_(item).svg|25px|link=Runes]] [[Runes]]')
  for i, cat in ipairs({'Standard', 'Combination'}) do
for i, cat in ipairs({'Standard', 'Combination'}) do
    table.sort(runeList[cat], function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end)
table.sort(runeList[cat], function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end)
    table.insert(resultPart, '\r\n|-\r\n!scope="row"|' .. cat .. ' Runes')
table.insert(resultPart, '\r\n|-\r\n!scope="row"|' .. cat .. ' Runes')


    local listPart = {}
local listPart = {}
    for j, rune in ipairs(runeList[cat]) do
for j, rune in ipairs(runeList[cat]) do
      table.insert(listPart, Icons.Icon({rune.name, type='item'}))
table.insert(listPart, Icons.Icon({rune.name, type='item'}))
    end
end
    table.insert(resultPart, '\r\n|style="text-align:center;"|'..table.concat(listPart, ' • '))
table.insert(resultPart, '\r\n|style="text-align:center;"|'..table.concat(listPart, ' • '))
  end
end
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


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


function p.getSkillcapeNavbox(frame)
function p.getSkillcapeNavbox(frame)
  local capeList = Shop.getPurchases(function(cat, purch) return cat == 'Skillcapes' end)
local capeList = Shop.getPurchases(function(cat, purch) return cat == 'Skillcapes' end)
  table.sort(capeList, function(a, b)
table.sort(capeList, function(a, b)
                        if a.cost.gp == b.cost.gp then
if a.cost.gp == b.cost.gp then
                          return a.name < b.name
return a.name < b.name
                        else
else
                          return a.cost.gp < b.cost.gp
return a.cost.gp < b.cost.gp
                        end
end
                      end)
end)


  local capeText = {}
local capeText = {}
  for i, purch in ipairs(capeList) do
for i, purch in ipairs(capeList) do
    if purch.contains ~= nil and purch.contains.items ~= nil then
if purch.contains ~= nil and purch.contains.items ~= nil then
      local item = Items.getItemByID(purch.contains.items[1][1])
local item = Items.getItemByID(purch.contains.items[1][1])
      if item ~= nil then
if item ~= nil then
        table.insert(capeText, Icons.Icon({item.name, type='item'}))
table.insert(capeText, Icons.Icon({item.name, type='item'}))
      end
end
    end
end
  end
end


  local resultPart = {}
local resultPart = {}
  table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n![[File:Cape_of_Completion_(item).svg|25px|link=Skillcapes]] [[Skillcapes]]')
table.insert(resultPart, '\r\n![[File:Cape_of_Completion_(item).svg|25px|link=Skillcapes]] [[Skillcapes]]')
  table.insert(resultPart, '\r\n|-\r\n|style="text-align:center;"|'..table.concat(capeText, ' • '))
table.insert(resultPart, '\r\n|-\r\n|style="text-align:center;"|'..table.concat(capeText, ' • '))
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


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


function p.getSpellNavbox(frame)
function p.getSpellNavbox(frame)
  local spellTable = { ["standard"] = {}, ["curse"] = {}, ["aurora"] = {}, ["ancient"] = {}, ["alt"] = {} }
local spellTable = { ["standard"] = {}, ["curse"] = {}, ["aurora"] = {}, ["ancient"] = {}, ["alt"] = {} }
  local catData = {
local catData = {
  { ["name"] = 'standard', ["header"] = '[[Magic#Standard_Magic|Standard Spells]]', ["imgType"] = 'spell' },
{ ["name"] = 'standard', ["header"] = '[[Magic#Standard_Magic|Standard Spells]]', ["imgType"] = 'spell' },
  { ["name"] = 'curse', ["header"] = '[[Magic#Curses|Curses]]', ["imgType"] = 'curse' },
{ ["name"] = 'curse', ["header"] = '[[Magic#Curses|Curses]]', ["imgType"] = 'curse' },
  { ["name"] = 'aurora', ["header"] = '[[Magic#Auroras|Auroras]]', ["imgType"] = 'aurora' },
{ ["name"] = 'aurora', ["header"] = '[[Magic#Auroras|Auroras]]', ["imgType"] = 'aurora' },
  { ["name"] = 'ancient', ["header"] = '[[Magic#Ancient_Magicks|Ancient Magicks]]', ["imgType"] = 'spell' },
{ ["name"] = 'ancient', ["header"] = '[[Magic#Ancient_Magicks|Ancient Magicks]]', ["imgType"] = 'spell' },
  { ["name"] = 'alt', ["header"] = '[[Alternative_Magic|Alt Magic]]', ["imgType"] = 'spell' },
{ ["name"] = 'alt', ["header"] = '[[Alternative_Magic|Alt Magic]]', ["imgType"] = 'spell' },
  }
}
 
for i, spell in ipairs(MagicData.Spells) do
table.insert(spellTable['standard'], { ["name"] = spell.name, ["order"] = spell.level })
end
for i, spell in ipairs(MagicData.Curses) do
table.insert(spellTable['curse'], { ["name"] = spell.name, ["order"] = spell.level })
end
for i, spell in ipairs(MagicData.Auroras) do
table.insert(spellTable['aurora'], { ["name"] = spell.name, ["order"] = spell.level })
end
for i, spell in ipairs(MagicData.Ancient) do
table.insert(spellTable['ancient'], { ["name"] = spell.name, ["order"] = spell.level })
end
for i, spell in ipairs(MagicData.AltMagic) do
table.insert(spellTable['alt'], { ["name"] = spell.name, ["order"] = spell.level })
end
 
local getSpellList = function(spellTable, imgType)
local listPart = {}
for i, obj in ipairs(spellTable) do
table.insert(listPart, Icons.Icon({obj.name, type=imgType}))
end
return table.concat(listPart, ' • ')
end


  for i, spell in ipairs(MagicData.Spells) do
local resultPart = {}
  table.insert(spellTable['standard'], { ["name"] = spell.name, ["order"] = spell.level })
table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
  end
table.insert(resultPart, '\r\n!colspan=2|[[File:Magic_(skill).svg|25px|link=Spells]] [[Spells]]')
  for i, spell in ipairs(MagicData.Curses) do
for i, catDefn in ipairs(catData) do
  table.insert(spellTable['curse'], { ["name"] = spell.name, ["order"] = spell.level })
table.sort(spellTable[catDefn.name], function(a, b)
  end
if a.order == b.order then
  for i, spell in ipairs(MagicData.Auroras) do
return a.name < b.name
  table.insert(spellTable['aurora'], { ["name"] = spell.name, ["order"] = spell.level })
else
  end
return a.order < b.order
  for i, spell in ipairs(MagicData.Ancient) do
end
  table.insert(spellTable['ancient'], { ["name"] = spell.name, ["order"] = spell.level })
end)
  end
table.insert(resultPart, '\r\n|-\r\n!scope="row"| ' .. catDefn.header)
  for i, spell in ipairs(MagicData.AltMagic) do
table.insert(resultPart, '\r\n|style="text-align:center;| ' .. getSpellList(spellTable[catDefn.name], catDefn.imgType))
  table.insert(spellTable['alt'], { ["name"] = spell.name, ["order"] = spell.level })
end
  end
table.insert(resultPart, '\r\n|}')
 
  local getSpellList = function(spellTable, imgType)
      local listPart = {}
      for i, obj in ipairs(spellTable) do
        table.insert(listPart, Icons.Icon({obj.name, type=imgType}))
      end
      return table.concat(listPart, ' • ')
    end
 
  local resultPart = {}
  table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n!colspan=2|[[File:Magic_(skill).svg|25px|link=Spells]] [[Spells]]')
  for i, catDefn in ipairs(catData) do
  table.sort(spellTable[catDefn.name], function(a, b)
                                if a.order == b.order then
                                return a.name < b.name
                                else
                                return a.order < b.order
                                end
                              end)
  table.insert(resultPart, '\r\n|-\r\n!scope="row"| ' .. catDefn.header)
  table.insert(resultPart, '\r\n|style="text-align:center;| ' .. getSpellList(spellTable[catDefn.name], catDefn.imgType))
  end
  table.insert(resultPart, '\r\n|}')


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


function p.getFamiliarNavbox(frame)
function p.getFamiliarNavbox(frame)
  local familiars = Items.getItems(function(item) return item.type == 'Familiar' end)
local familiars = Items.getItems(function(item) return item.type == 'Familiar' end)
  table.sort(familiars, function(a, b) return a.summoningLevel < b.summoningLevel end)
table.sort(familiars, function(a, b) return a.summoningLevel < b.summoningLevel end)


  local result = '{| class="wikitable" style="margin:auto; clear:both; width: 100%"'
local result = '{| class="wikitable" style="margin:auto; clear:both; width: 100%"'
  result = result..'\r\n!colspan=2|[[File:Summoning_(skill).svg|25px|link=Summoning]] [[Summoning|Summoning Familiars]]'
result = result..'\r\n!colspan=2|[[File:Summoning_(skill).svg|25px|link=Summoning]] [[Summoning|Summoning Familiars]]'
  local iconArray = {}
local iconArray = {}
  for i, fam in Shared.skpairs(familiars) do
for i, fam in Shared.skpairs(familiars) do
    table.insert(iconArray, Icons.Icon({fam.name, type='item'}))
table.insert(iconArray, Icons.Icon({fam.name, type='item'}))
  end
end
  result = result..'\r\n|-\r\n|style="text-align:center;"|'..table.concat(iconArray, ' • ')
result = result..'\r\n|-\r\n|style="text-align:center;"|'..table.concat(iconArray, ' • ')
  result = result..'\r\n|}'
result = result..'\r\n|}'
  return result
return result
end
end


function p.getThievingNavbox()
function p.getThievingNavbox()
  local returnPart = {}
local returnPart = {}


  -- Create table header
-- Create table header
  table.insert(returnPart, '{| class="wikitable" style="text-align:center; clear:both; margin:auto; margin-bottom:1em;"')
table.insert(returnPart, '{| class="wikitable" style="text-align:center; clear:both; margin:auto; margin-bottom:1em;"')
  table.insert(returnPart, '|-\r\n!' .. Icons.Icon({'Thieving', type='skill', notext=true}) .. '[[Thieving|Thieving Targets]]')
table.insert(returnPart, '|-\r\n!' .. Icons.Icon({'Thieving', type='skill', notext=true}) .. '[[Thieving|Thieving Targets]]')
  table.insert(returnPart, '|-\r\n|')
table.insert(returnPart, '|-\r\n|')


  local npcData = {}
local npcData = {}
  for i, npc in ipairs(SkillData.Thieving.NPCs) do
for i, npc in ipairs(SkillData.Thieving.NPCs) do
    table.insert(npcData, {["level"] = npc.level, ["name"] = npc.name})
table.insert(npcData, {["level"] = npc.level, ["name"] = npc.name})
  end
end
  table.sort(npcData, function(a, b) return a.level < b.level end)
table.sort(npcData, function(a, b) return a.level < b.level end)


  local npcList = {}
local npcList = {}
  -- Create row for each NPC
-- Create row for each NPC
  for i, npc in ipairs(npcData) do
for i, npc in ipairs(npcData) do
    table.insert(npcList, Icons.Icon({npc.name, type='thieving'}))
table.insert(npcList, Icons.Icon({npc.name, type='thieving'}))
  end
end
  table.insert(returnPart, table.concat(npcList, ' • '))
table.insert(returnPart, table.concat(npcList, ' • '))
  table.insert(returnPart, '|}')
table.insert(returnPart, '|}')


  return table.concat(returnPart, '\r\n')
return table.concat(returnPart, '\r\n')
end
end


function p.getFishingNavbox()
function p.getFishingNavbox()
  local categoryHeader = {}
local categoryHeader = {}
  local categoryItems = {}
local categoryItems = {}
  local addCatData = function(cat, catLink, itemName, itemOrder)
local addCatData = function(cat, catLink, itemName, itemOrder)
                      if categoryItems[cat] == nil then
if categoryItems[cat] == nil then
                        -- Initialise category
-- Initialise category
                        table.insert(categoryHeader, { ["name"] = cat, ["link"] = catLink })
table.insert(categoryHeader, { ["name"] = cat, ["link"] = catLink })
                        categoryItems[cat] = {}
categoryItems[cat] = {}
                      end
end
                      table.insert(categoryItems[cat], { ["name"] = itemName, ["order"] = itemOrder })
table.insert(categoryItems[cat], { ["name"] = itemName, ["order"] = itemOrder })
                    end
end


  -- Identify fishing catchable items
-- Identify fishing catchable items
  local fishingToItemID = {}
local fishingToItemID = {}
  local junkItems = {}
local junkItems = {}
  local specialItems = {}
local specialItems = {}
  for i, item in ipairs(ItemData.Items) do
for i, item in ipairs(ItemData.Items) do
    if item.fishingID ~= nil then
if item.fishingID ~= nil then
      -- Create FishingID to item map
-- Create FishingID to item map
      fishingToItemID[item.fishingID] = item
fishingToItemID[item.fishingID] = item
    elseif item.category == 'Fishing' and item.type == 'Junk' then
elseif item.category == 'Fishing' and item.type == 'Junk' then
      table.insert(junkItems, item)
table.insert(junkItems, item)
    elseif item.fishingCatchWeight ~= nil then
elseif item.fishingCatchWeight ~= nil then
      table.insert(specialItems, item)
table.insert(specialItems, item)
    end
end
  end
end
  -- Fishing areas
-- Fishing areas
  -- Iterate through all fishing areas, identifying fish within each
-- Iterate through all fishing areas, identifying fish within each
  for i, area in ipairs(SkillData.Fishing.Areas) do
for i, area in ipairs(SkillData.Fishing.Areas) do
    for j, fishID in ipairs(area.fish) do
for j, fishID in ipairs(area.fish) do
      local fishItem = fishingToItemID[fishID]
local fishItem = fishingToItemID[fishID]
      if fishItem ~= nil then
if fishItem ~= nil then
        addCatData(area.name, 'Fishing#Fishing Areas', fishItem.name, fishItem.fishingLevel)
addCatData(area.name, 'Fishing#Fishing Areas', fishItem.name, fishItem.fishingLevel)
      end
end
    end
end
  end
end
  -- Junk items
-- Junk items
  for i, item in ipairs(junkItems) do
for i, item in ipairs(junkItems) do
    addCatData('Junk', 'Fishing#Junk', item.name, 1)
addCatData('Junk', 'Fishing#Junk', item.name, 1)
  end
end
  -- Special items
-- Special items
  for i, item in ipairs(specialItems) do
for i, item in ipairs(specialItems) do
    addCatData('Special Items', 'Fishing#Special', item.name, 1 / (item.fishingCatchWeight or 1))
addCatData('Special Items', 'Fishing#Special', item.name, 1 / (item.fishingCatchWeight or 1))
  end
end


  local resultPart = {}
local resultPart = {}
  -- Generate navbox header
-- Generate navbox header
  table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
table.insert(resultPart, '{| class="wikitable" style="margin:auto; clear:both; width: 100%"')
  table.insert(resultPart, '\r\n|-\r\n!colspan="2" | ' .. Icons.Icon({'Fishing', type='skill'}))
table.insert(resultPart, '\r\n|-\r\n!colspan="2" | ' .. Icons.Icon({'Fishing', type='skill'}))
  -- Generate section for each fishing area, junk, and special
-- Generate section for each fishing area, junk, and special
  for i, cat in ipairs(categoryHeader) do
for i, cat in ipairs(categoryHeader) do
    local itemList = {}
local itemList = {}
    if categoryItems[cat.name] ~= nil then
if categoryItems[cat.name] ~= nil then
      table.sort(categoryItems[cat.name], function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end)
table.sort(categoryItems[cat.name], function(a, b) return (a.order == b.order and a.name < b.name) or a.order < b.order end)
      for j, item in ipairs(categoryItems[cat.name]) do
for j, item in ipairs(categoryItems[cat.name]) do
        table.insert(itemList, Icons.Icon({item.name, type='item'}))
table.insert(itemList, Icons.Icon({item.name, type='item'}))
      end
end
    end
end


    table.insert(resultPart, '\r\n|-\r\n!class="center" style="min-width:140px" | [[' .. (cat.link or cat.name) .. '|' .. cat.name .. ']]')
table.insert(resultPart, '\r\n|-\r\n!class="center" style="min-width:140px" | [[' .. (cat.link or cat.name) .. '|' .. cat.name .. ']]')
    table.insert(resultPart, '\r\n| class="center" style="vertical-align:middle;" | ' .. table.concat(itemList, ' • '))
table.insert(resultPart, '\r\n| class="center" style="vertical-align:middle;" | ' .. table.concat(itemList, ' • '))
  end
end
  table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


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


return p
return p