Module:Navboxes
From Melvor Idle
Documentation for this module may be created at Module:Navboxes/doc
-- New module to stop navbox generators cluttering other modules local p = {} local SkillData = mw.loadData('Module:Skills/data') local MagicData = mw.loadData('Module:Magic/data') local ItemData = mw.loadData('Module:Items/data') local Shared = require('Module:Shared') local Icons = require('Module:Icons') local Items = require('Module:Items') local Shop = require('Module:Shop') function p.getFarmingNavbox(frame) local resultPart = {} local seedsTable = {} local produceTable = {} for i, item in ipairs(ItemData.Items) do if item.farmingLevel ~= nil then local tier = item.tier if seedsTable[tier] == nil then -- Initialize tier tables seedsTable[tier] = {} produceTable[tier] = {} end if item.grownItemID ~= nil then local grownItem = Items.getItemByID(item.grownItemID) if grownItem ~= nil then table.insert(produceTable[tier], { ["name"] = grownItem.name, ["level"] = item.farmingLevel }) end end table.insert(seedsTable[tier], { ["name"] = item.name, ["level"] = item.farmingLevel }) end end -- Generate output table table.insert(resultPart, '{| class="wikitable mw-collapsible navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n!style="background-color:#275C87;color:#FFFFFF;padding-left:64px;" colspan="2"|' .. Icons.Icon({'Farming', type='skill'})) local getItemList = function(itemTable) local listPart = {} for i, item in ipairs(itemTable) do table.insert(listPart, Icons.Icon({item.name, type='item'})) end return table.concat(listPart, ' • ') 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 local tierList = {} for tier, seeds in pairs(seedsTable) do table.insert(tierList, tier) end table.sort(tierList, function(a, b) return a < b end) -- Generate table section for each tier for i, tier in pairs(tierList) do -- Sort tables by Farming level order table.sort(seedsTable[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!scope="row"| Seeds') 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|style="text-align:center;"| ' .. getItemList(produceTable[tier])) end table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getFoodNavbox(frame) local foundIDs, cookedFood, harvestedFood, otherFood = {}, {}, {}, {} -- Hide Lemon cake foundIDs[1029] = true foundIDs[1061] = true -- Cooked food for i, recipe in ipairs(SkillData.Cooking.Recipes) do if not foundIDs[recipe.itemID] then foundIDs[recipe.itemID] = true local cookedItem = Items.getItemByID(recipe.itemID) if cookedItem ~= nil then local catIdx = recipe.category + 1 -- Initialize category if it doesn't already exist if cookedFood[catIdx] == nil then cookedFood[catIdx] = {} end local perfectName = nil if recipe.perfectCookID ~= nil then local perfectItem = Items.getItemByID(recipe.perfectCookID) if perfectItem ~= nil then perfectName = perfectItem.name foundIDs[recipe.perfectCookID] = true end end table.insert(cookedFood[catIdx], { ["name"] = cookedItem.name, ["order"] = recipe.level, ["perfectName"] = perfectName }) end end end -- Harvested foods for i, item in ipairs(ItemData.Items) do if item.grownItemID ~= nil and not foundIDs[item.grownItemID] then -- Item is grown from farming and can be eaten local grownItem = Items.getItemByID(item.grownItemID) if grownItem ~= nil and grownItem.canEat then table.insert(harvestedFood, { ["name"] = grownItem.name, ["order"] = item.farmingLevel }) foundIDs[grownItem.id] = true end end end -- Other foods, must be checked after cooked & harvested foods have been identified for i, item in ipairs(ItemData.Items) do if item.canEat and not foundIDs[item.id] then -- Item can be eaten but isn't cooked nor harvested table.insert(otherFood, { ["name"] = item.name, ["order"] = item.id }) foundIDs[item.id] = true end end -- Sort food lists 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 table.sort(cookedFood[i], sortFunc) end table.sort(harvestedFood, sortFunc) table.sort(otherFood, sortFunc) -- Generate food lists for final output local cookingCatHeader = { Icons.Icon({'Normal Cooking Fire', 'Cooking Fire', type='upgrade', nolink=true}), Icons.Icon({'Basic Furnace', 'Furnace', type='upgrade', nolink=true}), Icons.Icon({'Basic Pot', 'Pot', type='upgrade', nolink=true}) } local getFoodList = function(foodTable) local listPart = {} for i, food in ipairs(foodTable) do local foodText = Icons.Icon({food.name, type='item'}) if food.perfectName ~= nil then foodText = Icons.Icon({food.perfectName, type='item', notext=true}) .. ' ' .. foodText end table.insert(listPart, foodText) end return table.concat(listPart, ' • ') end local resultPart = {} table.insert(resultPart, '{| class="wikitable mw-collapsible navigation-not-searchable" 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"| ') table.insert(resultPart, Icons.Icon({'Food', type='item', img='Crab'})) table.insert(resultPart, '\r\n|-\r\n!colspan="2"| Cooked') for catID, foodTable in ipairs(cookedFood) do table.insert(resultPart, '\r\n|-\r\n!scope="row"| ' .. cookingCatHeader[catID]) table.insert(resultPart, '\r\n|style="text-align:center;"| ' .. getFoodList(foodTable)) end 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"| Other') table.insert(resultPart, '\r\n|-\r\n|colspan="2" style="text-align:center;"| ' .. getFoodList(otherFood)) table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getPotionNavbox(frame) local catList = { { ["categoryID"] = 0, ["name"] = 'Combat' }, { ["categoryID"] = 1, ["name"] = 'Skill' } } table.sort(catList, function(a, b) return a.name < b.name end) -- Compile list of potions to be included local potList = {} for i, potData in ipairs(SkillData.Herblore.Potions) do if potList[potData.category] == nil then potList[potData.category] = {} end local potFirstItem = Items.getItemByID(potData.potionIDs[1]) local potName = string.gsub(potFirstItem.name, ' Potion [IV]+$', '') table.insert(potList[potData.category], { ["name"] = potName, ["order"] = potData.level, ["img"] = potFirstItem.name }) end local resultPart = {} -- Generate table header table.insert(resultPart, '{| class="wikitable navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n!colspan=2|' .. Icons.Icon({ 'Herblore', 'Potions', type='skill' })) -- Generate section for each category of potions for i, catData in ipairs(catList) do -- Compile list of potions 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) for j, potData in ipairs(potList[catData.categoryID]) do table.insert(potListText, Icons.Icon({ potData.name .. ' Potion', potData.name, img=potData.img, type='item' })) end table.insert(resultPart, '\r\n|-\r\n! ' .. catData.name .. ' Potions') table.insert(resultPart, '\r\n|class="center" style="vertical-align:middle;"| ' .. table.concat(potListText, ' • ')) end table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getPrayerNavbox(frame) local prayerList = {} for i, prayer in Shared.skpairs(SkillData.Prayer) do table.insert(prayerList, { ["name"] = prayer.name, ["order"] = prayer.prayerLevel }) end table.sort(prayerList, function(a, b) if a.order == b.order then return a.name < b.name else return a.order < b.order end end) local prayerListText = {} for i, prayer in ipairs(prayerList) do table.insert(prayerListText, Icons.Icon({ prayer.name, type='prayer' })) end local resultPart = {} table.insert(resultPart, '{| class="wikitable navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') 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|}') return table.concat(resultPart) end function p.getRuneNavbox(frame) -- Assumes all runes are from Runecrafting, which may need revising in future updates local catNames = { 'Standard', 'Combination' } local runeList = { {}, {} } for i, recipe in ipairs(SkillData.Runecrafting.Recipes) do local catIdx = recipe.category + 1 if catNames[catIdx] ~= nil then local item = Items.getItemByID(recipe.itemID) if item ~= nil then table.insert(runeList[catIdx], { ["name"] = item.name, ["order"] = recipe.level }) end end end local resultPart = {} table.insert(resultPart, '{| class="wikitable navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n!colspan="2"|' .. Icons.Icon({'Runes', type='item', img='Air Rune'})) for catIdx, catName in ipairs(catNames) do table.sort(runeList[catIdx], 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"|' .. catName .. ' Runes') local listPart = {} for j, rune in ipairs(runeList[catIdx]) do table.insert(listPart, Icons.Icon({rune.name, type='item'})) end table.insert(resultPart, '\r\n|style="text-align:center;"|'..table.concat(listPart, ' • ')) end table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getSkillcapeNavbox(frame) local capeList = Shop.getPurchases(function(cat, purch) return cat == 'Skillcapes' end) table.sort(capeList, function(a, b) if a.cost.gp == b.cost.gp then return a.name < b.name else return a.cost.gp < b.cost.gp end end) local capeText = {} for i, purch in ipairs(capeList) do if purch.contains ~= nil and purch.contains.items ~= nil then local item = Items.getItemByID(purch.contains.items[1][1]) if item ~= nil then table.insert(capeText, Icons.Icon({item.name, type='item'})) end end end local resultPart = {} table.insert(resultPart, '{| class="wikitable navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n!' .. Icons.Icon({'Skillcapes', type='item', img='Cape of Completion'})) table.insert(resultPart, '\r\n|-\r\n|style="text-align:center;"|'..table.concat(capeText, ' • ')) table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getSpellNavbox(frame) local spellTable = { ["standard"] = {}, ["curse"] = {}, ["aurora"] = {}, ["ancient"] = {}, ["alt"] = {} } local catData = { { ["name"] = 'standard', ["header"] = '[[Magic#Standard_Magic|Standard Spells]]', ["imgType"] = 'spell' }, { ["name"] = 'curse', ["header"] = '[[Magic#Curses|Curses]]', ["imgType"] = 'curse' }, { ["name"] = 'aurora', ["header"] = '[[Magic#Auroras|Auroras]]', ["imgType"] = 'aurora' }, { ["name"] = 'ancient', ["header"] = '[[Magic#Ancient_Magicks|Ancient Magicks]]', ["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 local resultPart = {} table.insert(resultPart, '{| class="wikitable navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n!colspan=2|' .. Icons.Icon({'Spells', type='skill', img='Magic'})) 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) end function p.getFamiliarNavbox(frame) local familiarList = {} for i, recipe in ipairs(SkillData.Summoning.Marks) do local item = Items.getItemByID(recipe.itemID) if item ~= nil then table.insert(familiarList, { ["name"] = item.name, ["order"] = recipe.level }) end end table.sort(familiarList, function(a, b) return a.order < b.order end) local resultPart = {} table.insert(resultPart, '{| class="wikitable navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n!colspan=2|' .. Icons.Icon({'Summoning', 'Summoning Familiars', type='skill'})) local iconArray = {} for i, fam in ipairs(familiarList) do table.insert(iconArray, Icons.Icon({fam.name, type='item'})) end table.insert(resultPart, '\r\n|-\r\n|style="text-align:center;"|'..table.concat(iconArray, ' • ')) table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getThievingNavbox() local returnPart = {} -- Create table header table.insert(returnPart, '{| class="wikitable navigation-not-searchable" style="text-align:center; clear:both; margin:auto; margin-bottom:1em;"') table.insert(returnPart, '|-\r\n!' .. Icons.Icon({'Thieving', 'Thieving Targets', type='skill'})) table.insert(returnPart, '|-\r\n|') local npcData = {} for i, npc in ipairs(SkillData.Thieving.NPCs) do table.insert(npcData, {["level"] = npc.level, ["name"] = npc.name}) end table.sort(npcData, function(a, b) return a.level < b.level end) local npcList = {} -- Create row for each NPC for i, npc in ipairs(npcData) do table.insert(npcList, Icons.Icon({npc.name, type='thieving'})) end table.insert(returnPart, table.concat(npcList, ' • ')) table.insert(returnPart, '|}') return table.concat(returnPart, '\r\n') end function p.getFishingNavbox() local categoryHeader = {} local categoryItems = {} local addCatData = function(cat, catLink, itemName, itemOrder) if categoryItems[cat] == nil then -- Initialize category table.insert(categoryHeader, { ["name"] = cat, ["link"] = catLink }) categoryItems[cat] = {} end table.insert(categoryItems[cat], { ["name"] = itemName, ["order"] = itemOrder }) end -- Fishing areas -- Iterate through all fishing areas, identifying fish within each for i, area in ipairs(SkillData.Fishing.Areas) do for j, recipe in ipairs(area.fish) do local fishItem = Items.getItemByID(recipe.itemID) if fishItem ~= nil then addCatData(area.name, 'Fishing#Fishing Areas', fishItem.name, recipe.level) end end end -- Junk items for i, itemID in ipairs(SkillData.Fishing.JunkItems) do local item = Items.getItemByID(itemID) if item ~= nil then addCatData('Junk', 'Fishing#Junk', item.name, 1) end end -- Special items for i, itemDef in ipairs(SkillData.Fishing.SpecialItems) do local item = Items.getItemByID(itemDef[1]) if item ~= nil then local weight = itemDef[2] or 1 addCatData('Special Items', 'Fishing#Special', item.name, 1 / weight) end end local resultPart = {} -- Generate navbox header table.insert(resultPart, '{| class="wikitable navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n|-\r\n!colspan="2" | ' .. Icons.Icon({'Fishing', type='skill'})) -- Generate section for each fishing area, junk, and special for i, cat in ipairs(categoryHeader) do local itemList = {} 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) for j, item in ipairs(categoryItems[cat.name]) do table.insert(itemList, Icons.Icon({item.name, type='item'})) 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| class="center" style="vertical-align:middle;" | ' .. table.concat(itemList, ' • ')) end table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getOreBarNavbox(frame) local categoryList = { 'Ores', 'Bars' } local categoryItems = { ["Ores"] = {}, ["Bars"] = {} } local barOreIDs = {} -- Compile list of bars -- Also compile a list of ores used to create these bars, used to filter out non-bar ores later for i, recipe in ipairs(SkillData.Smithing.Recipes) do if recipe.category == 0 then -- Category 0 = Bars local item = Items.getItemByID(recipe.itemID) if item ~= nil then local displayName = string.gsub(item.name, ' Bar$', '') table.insert(categoryItems['Bars'], { ["name"] = item.name, ["display"] = displayName, ["order"] = recipe.level }) end -- Add to barOreIDs list for j, costDef in ipairs(recipe.itemCosts) do if barOreIDs[costDef.id] == nil then barOreIDs[costDef.id] = true end end end end -- Compile list of ores for i, recipe in ipairs(SkillData.Mining.Rocks) do if barOreIDs[recipe.oreID] then local item = Items.getItemByID(recipe.oreID) if item ~= nil then table.insert(categoryItems['Ores'], { ["name"] = item.name, ["display"] = recipe.name, ["order"] = recipe.levelRequired }) end end end local resultPart = {} -- Generate navbox header table.insert(resultPart, '{| class="wikitable mw-collapsible navigation-not-searchable" style="margin:auto; clear:both; width: 100%"') table.insert(resultPart, '\r\n|-\r\n!style="background-color:#275C87;color:#FFFFFF;padding-left:64px;" colspan="2" | ' .. '<b>Ores & Bars</b>') -- Generate navbox content for i, cat in ipairs(categoryList) do table.sort(categoryItems[cat], function(a, b) return (a.order == b.order and a.display < b.display) or a.order < b.order end) local listPart = {} for j, listItem in ipairs(categoryItems[cat]) do table.insert(listPart, Icons.Icon({ listItem.name, listItem.display, type = 'item' })) end table.insert(resultPart, '\r\n|-\r\n! ' .. cat .. '\r\n|style="text-align:center;"| ' .. table.concat(listPart, ' • ')) end table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end return p