Module:CombatAreas/AreaTables: Difference between revisions

From Melvor Idle
m (Correct case)
(getDungeonTable: Add Requirements column; getSlayerAreaTable: Additional formatting for Requirements & area effects columns)
 
(12 intermediate revisions by 3 users not shown)
Line 2: Line 2:


local p = {}
local p = {}
local AreaData = mw.loadData('Module:CombatAreas/data')


local Constants = require('Module:Constants')
local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Shared = require('Module:Shared')
local GameData = require('Module:GameData')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')
local Items = require('Module:Items')
local Items = require('Module:Items')
local Monsters = require('Module:Monsters')
local Monsters = require('Module:Monsters')
local CombatAreas = require('Module:CombatAreas')
local Pets = require('Module:Pets')
local Pets = require('Module:Pets')
local Areas = require('Module:CombatAreas')


function p.getLowHighLevels(idList)
function p.getLowHighLevels(idList)
local lowLevel = 1000000
local lowLevel = 1000000
local highLevel = 0
local highLevel = 0
for i, monID in Shared.skpairs(idList) do
for i, monID in ipairs(idList) do
local monster = Monsters.getMonsterByID(monID)
local monster = Monsters.getMonsterByID(monID)
local cmbLevel = Monsters._getMonsterCombatLevel(monster)
local cmbLevel = Monsters._getMonsterCombatLevel(monster)
Line 28: Line 27:
local result = '{| class="wikitable sortable stickyHeader"'
local result = '{| class="wikitable sortable stickyHeader"'
result = result..'\r\n|- class="headerRow-0"'
result = result..'\r\n|- class="headerRow-0"'
result = result..'\r\n!colspan="2"|Zone!!Difficulty!!Lowest Monster Level!!Highest Monster Level'
result = result..'\r\n!colspan="2"|Zone!!Difficulty!!Lowest Monster Level!!Highest Monster Level!!Requirements'


for i, areaIdx in ipairs(AreaData.displayOrder.combatAreas) do
local areas = GameData.sortByOrderTable(GameData.rawData.combatAreas, GameData.rawData.combatAreaDisplayOrder)
local area = CombatAreas.getAreaByID('combat', areaIdx)
for i, area in ipairs(areas) do
result = result..'\r\n|-'
result = result..'\r\n|-'
result = result..'\r\n|'..Icons.Icon({area.name, type='combat', size='50', notext=true})
result = result..'\r\n|class="table-img" data-sort-value="' .. area.name .. '"| '..Icons.Icon({area.name, type='combatArea', size='50', notext=true})
result = result..'||'..Icons.Icon({area.name, type='combat', noicon=true})
result = result..'||' .. Icons.getExpansionIcon(area.id) .. Icons.Icon({area.name, type='combatArea', noicon=true})
local diff1 = Constants.getDifficultyString(area.difficulty[1])
result = result..'||data-sort-value="'..area.difficulty[1]..'"|'..Areas._getAreaStat(area, 'difficulty')
local diff2 = Constants.getDifficultyString(area.difficulty[2])
local lowLvl, highLvl = p.getLowHighLevels(area.monsterIDs)
result = result..'||data-sort-value="'..area.difficulty[1]..'"|'..diff1
result = result .. '||data-sort-value="' .. lowLvl .. '"| ' .. Shared.formatnum(lowLvl)
if diff1 ~= diff2 and diff2 ~= nil then result = result..' - '..diff2 end
result = result .. '||data-sort-value="' .. highLvl .. '"| ' .. Shared.formatnum(highLvl)
local lowLvl, highLvl = p.getLowHighLevels(area.monsters)
local reqText = Areas._getAreaRequirements(area)
result = result..'||'..lowLvl..'||'..highLvl
if reqText == nil or reqText == '' then
result = result .. '||class="table-na"| None'
else
result = result .. '||' .. reqText
end
end
end
result = result..'\r\n|}'
result = result..'\r\n|}'
Line 52: Line 55:
result = result..'\r\n!colspan="2"|Zone!!Difficulty!!Highest Monster Level!!Requirements!!Area Effect'
result = result..'\r\n!colspan="2"|Zone!!Difficulty!!Highest Monster Level!!Requirements!!Area Effect'


for i, areaIdx in ipairs(AreaData.displayOrder.slayerAreas) do
local areas = GameData.sortByOrderTable(GameData.rawData.slayerAreas, GameData.rawData.slayerAreaDisplayOrder)
local area = CombatAreas.getAreaByID('slayer', areaIdx)
for i, area in ipairs(areas) do
result = result..'\r\n|-'
result = result..'\r\n|-'
result = result..'\r\n|'..Icons.Icon({area.name, type='slayer', size='50', notext=true})
result = result..'\r\n|class="table-img" data-sort-value="' .. area.name .. '"| '..Icons.Icon({area.name, type='slayer', size='50', notext=true})
result = result..'||'..Icons.Icon({area.name, type='slayer', noicon=true})
result = result..'||' .. Icons.getExpansionIcon(area.id) .. Icons.Icon({area.name, type='slayer', noicon=true})
local diff1 = Constants.getDifficultyString(area.difficulty[1])
result = result..'||data-sort-value="'..area.difficulty[1]..'"|'..Areas._getAreaStat(area, 'difficulty')
local diff2 = Constants.getDifficultyString(area.difficulty[2])
local lowLvl, highLvl = p.getLowHighLevels(area.monsterIDs)
result = result..'||data-sort-value="'..area.difficulty[1]..'"|'..diff1
result = result..'||data-sort-value="' .. highLvl .. '"| ' .. Shared.formatnum(highLvl)
if diff1 ~= diff2 and diff2 ~= nil then result = result..' - '..diff2 end
local reqText = Areas._getAreaRequirements(area)
local lowLvl, highLvl = p.getLowHighLevels(area.monsters)
if reqText == nil or reqText == '' then
result = result..'||'..highLvl
result = result .. '||class="table-na"| None'
result = result..'||'..CombatAreas._getAreaRequirements(area)
else
result = result..'|| '..CombatAreas._getAreaStat(area, 'areaEffectDesc')
result = result .. '||' .. reqText
end
local effectText = Areas._getAreaStat(area, 'areaEffectDesc')
local classText = ((effectText == nil or effectText == 'None') and 'class="table-na"|') or ''
result = result..'||' .. classText .. ' ' .. effectText
end
end


Line 76: Line 83:
asList = true
asList = true
elseif type(asList) == 'string' then
elseif type(asList) == 'string' then
asList = asList.upper ~= 'FALSE'
asList = string.upper(asList) ~= 'FALSE'
end
end


Line 83: Line 90:
-- GP reward
-- GP reward
if area.isEvent == nil or not area.isEvent then
if area.eventID == nil then
local bossMonster = Monsters.getMonsterByID(area.monsters[Shared.tableCount(area.monsters)])
local bossMonster = Monsters.getMonsterByID(area.monsterIDs[Shared.tableCount(area.monsterIDs)])
local gpMin = bossMonster.dropCoins[1]
local gp = bossMonster.gpDrops
local gpMax = bossMonster.dropCoins[2]
if gp.min > 0 and gp.max > 0 then
if gpMin > 0 and gpMax > 0 then
if gp.min == gp.max then
if gpMin == gpMax then
table.insert(rewardList, chr .. Icons.GP(gp.min))
table.insert(rewardList, chr .. Icons.GP(gpMin))
else
else
table.insert(rewardList, chr .. Icons.GP(gpMin, gpMax))
table.insert(rewardList, chr .. Icons.GP(gp.min, gp.max))
end
end
end
end
Line 97: Line 103:
-- Item rewards
-- Item rewards
if type(area.rewards) == 'table' then
local itemLists = {}
for i, rewardID in ipairs(area.rewards) do
if type(area.rewardItemIDs) == 'table' then
table.insert(itemLists, area.rewardItemIDs)
end
if area.eventID ~= nil then
local event = GameData.getEntityByID('combatEvents', area.eventID)
if event ~= nil and type(event.itemRewardIDs) == 'table' then
table.insert(itemLists, event.itemRewardIDs)
end
end
for i, itemList in ipairs(itemLists) do
for j, rewardID in ipairs(itemList) do
local rewardItem = Items.getItemByID(rewardID)
local rewardItem = Items.getItemByID(rewardID)
if rewardItem == nil then
if rewardItem == nil then
table.insert(rewardList, chr .. 'Unknown item (ID ' .. tostring(rewardID) .. ')[[Category:Pages with script errors]]')
table.insert(rewardList, chr .. 'Unknown item (ID ' .. rewardID .. ')[[Category:Pages with script errors]]')
else
else
table.insert(rewardList, chr .. Icons.Icon({rewardItem.name, type='item', qty=1}))
table.insert(rewardList, chr .. Icons.Icon({rewardItem.name, type='item', qty=1}))
end
end
end
end
-- Event (Impending Darkness) rewards
if area.isEvent ~= nil and area.isEvent then
for i, rewardID in ipairs(AreaData.event.rewards) do
local rewardItem = Items.getItemByID(rewardID)
table.insert(rewardList, chr .. Icons.Icon({rewardItem.name, type='item', qty=1}))
end
end
end
end
Line 126: Line 134:
local areaName = frame.args ~= nil and frame.args[1] or frame
local areaName = frame.args ~= nil and frame.args[1] or frame
local asList = frame.args ~= nil and frame.args[2] or true
local asList = frame.args ~= nil and frame.args[2] or true
local area = CombatAreas.getArea(areaName)
local area = Areas.getArea(areaName)
if area == nil then
if area == nil then
return "ERROR: Could not find an area named "..areaName..'[[Category:Pages with script errors]]'
return Shared.printError('Could not find an area named "' .. areaName .. '"')
end
end


Line 134: Line 142:
return p._getDungeonRewards(area, asList)
return p._getDungeonRewards(area, asList)
else
else
return "ERROR: "..areaName.." is not a dungeon[[Category:Pages with script errors]]"
return Shared.printError('"' .. areaName .. '" is not a dungeon')
end
end
end
end
Line 141: Line 149:
local result = '{| class="wikitable sortable stickyHeader"'
local result = '{| class="wikitable sortable stickyHeader"'
result = result..'\r\n|-class="headerRow-0"'
result = result..'\r\n|-class="headerRow-0"'
result = result..'\r\n!colspan="2"|Dungeon!!Difficulty!!Monsters!!Boss Level!!Reward(s)!!Boss Pet'
result = result..'\r\n!colspan="2"|Dungeon!!Difficulty!!Monsters!!Boss Level!!Requirements!!Rewards!!Boss Pet'
 
local areas = GameData.sortByOrderTable(GameData.rawData.dungeons, GameData.rawData.dungeonDisplayOrder)
for i, dung in ipairs(areas) do
local monsterCount = Shared.tableCount(dung.monsterIDs)
local boss = Monsters.getMonsterByID(dung.monsterIDs[monsterCount])


for i, dungIdx in ipairs(AreaData.displayOrder.dungeons) do
local dung = CombatAreas.getAreaByID('dungeon', dungIdx)
result = result..'\r\n|-'
result = result..'\r\n|-'
result = result..'\r\n|data-sort-value="'..dung.name..'"|'..Icons.Icon({dung.name, type='dungeon', size='50', notext=true})
result = result..'\r\n|class="table-img" data-sort-value="'..dung.name..'"|'..Icons.Icon({dung.name, type='dungeon', size='50', notext=true})
result = result..'||'..Icons.Icon({dung.name, type='dungeon', noicon=true})
result = result..'||' .. Icons.getExpansionIcon(dung.id) .. Icons.Icon({dung.name, type='dungeon', noicon=true})
result = result..'||data-sort-value="'..dung.difficulty[1]..'"|'..CombatAreas._getAreaStat(dung, 'difficulty')
result = result..'||data-sort-value="'..dung.difficulty[1]..'"|'..Areas._getAreaStat(dung, 'difficulty')
result = result..'||'..Shared.tableCount(dung.monsters)
result = result..'||'..monsterCount
 
local boss = Monsters.getMonsterByID(dung.monsters[Shared.tableCount(dung.monsters)])
result = result..'||'..Shared.formatnum(Monsters._getMonsterCombatLevel(boss))
result = result..'||'..Shared.formatnum(Monsters._getMonsterCombatLevel(boss))
 
local reqText = Areas._getAreaRequirements(dung)
if reqText == nil or reqText == '' then
result = result .. '||class="table-na"| None'
else
result = result .. '||' .. reqText
end
result = result..'||'..p._getDungeonRewards(dung, false)
result = result..'||'..p._getDungeonRewards(dung, false)
if dung.petID ~= nil then
local petAdded = false
local pet = Pets.getPetByID(dung.petID)
if dung.pet ~= nil then
result = result..'||data-sort-value="'..pet.name..'"|'..Icons.Icon({pet.name, type='pet'})
local pet = GameData.getEntityByID('pets', dung.pet.petID)
else
if pet ~= nil then
result = result..'|| '
result = result..'||data-sort-value="'..pet.name..'"|'..Icons.Icon({pet.name, type='pet'})
local petDrop = Pets._getPetChance(pet)
if petDrop ~= nil then
result = result..'<br/>'..petDrop
end
petAdded = true
end
end
if not petAdded then
result = result..'||class="table-na"| None'
end
end
end
end
Line 167: Line 190:
end
end


function p._getDungeonDRTable(dung, mode, doStuns)
function p.buildCombatNavText(frame)
local AutoEatVals = {T1 = 0.2, T2 = 0.3, T3 = 0.4, T3W = 0.45}
--This isn't actually called on any pages but instead exists to save me time on updating Template:CombatNav for the new expansion
--NOTE: Due to Agility Obstacles, this value is a tad arbitrary
local areas = GameData.sortByOrderTable(GameData.rawData.slayerAreas, GameData.rawData.slayerAreaDisplayOrder)
local MaxViableHP = 1120
local outArray = {}
--This is the highest DR to list as possible. Value might be slightly off right now, currently just setting up value for testing
for i, area in ipairs(areas) do
local MaxViableDR = 81
local id = area.id
--This is the highest DR row shown. This should be higher than MaxViableDR
if Shared.startsWith(id, 'melvorTotH') then
local MaxVisibleDR = 85
table.insert(outArray, '|-')
 
table.insert(outArray, '| {{TotH}} {{ZoneIcon|'..area.name..'}}')
if doStuns == nil then
local monsterArray = {}
doStuns = true
for j, monsterID in ipairs(area.monsterIDs) do
elseif type(doStuns) == 'string' then
local monster = Monsters.getMonsterByID(monsterID)
doStuns = string.upper(doStuns) == 'TRUE'
table.insert(monsterArray, '{{MonsterIcon|'..monster.name..'}}')
end
end
 
table.insert(outArray, '| class="center" style="vertical-align:middle;" | '..table.concat(monsterArray, ' {{*}} '))
--First, figure out what our max hit for each style is
local MaxHits = { Melee = 0, Ranged = 0, Magic = 0 }
for i, monsterID in Shared.skpairs(dung.monsters) do
local monster = Monsters.getMonsterByID(monsterID)
local styleName = Constants.getCombatStyleName(monster.attackType)
local maxHit = Monsters._getMonsterMaxHit(monster, doStuns)
if maxHit > MaxHits[styleName] then
MaxHits[styleName] = maxHit
end
end
end
end
 
--Then, figure out the DR row to start with
areas = GameData.sortByOrderTable(GameData.rawData.dungeons, GameData.rawData.dungeonDisplayOrder)
--This is the DR that is one lower than the lowest possible DR for the best style
for i, area in ipairs(areas) do
local StyleArray = {"Melee", "Ranged", "Magic"}
local id = area.id
local EatThreshold = math.floor(MaxViableHP * AutoEatVals.T3W)
if Shared.startsWith(id, 'melvorTotH') then
local minDR = 100
table.insert(outArray, '|-')
for i, playerStyle in Shared.skpairs(StyleArray) do
table.insert(outArray, '| {{TotH}} {{ZoneIcon|'..area.name..'}}')
local maxStyleDR = 0
local monsterArray = {}
for enemyStyle, styleHit in Shared.skpairs(MaxHits) do
local mCheck = {}
if styleHit > 0 and styleHit > EatThreshold then
for j, monsterID in ipairs(area.monsterIDs) do
local styleDR = math.ceil((1 - (EatThreshold / styleHit)) * 100)
local monster = Monsters.getMonsterByID(monsterID)
styleDR = math.ceil(styleDR / Constants.getTriangleDRModifier(playerStyle, enemyStyle, mode))
if mCheck[monster.name] == nil then
maxStyleDR = math.max(maxStyleDR, styleDR)
table.insert(monsterArray, '{{MonsterIcon|'..monster.name..'}}')
end
mCheck[monster.name] = 1
end
end
table.insert(outArray, '| class="center" style="vertical-align:middle;" | '..table.concat(monsterArray, ' {{*}} '))
end
end
minDR = math.min(minDR, maxStyleDR)
end
end
 
minDR = minDR - 1
return table.concat(outArray, '\r\n')
 
--Finally, build the table using those starting points
local StyleHeader = "Melee!!Ranged!!Magic"
StyleHeader = StyleHeader..'!!'..StyleHeader..'!!'..StyleHeader..'!!'..StyleHeader
 
local result = '{| class="wikitable stickyHeader"'
result = result..'\r\n|-class="headerRow-0"'
result = result..'\r\n!Pre-Triangle DR!!colspan=3|AE T3 + Wasteful!!colspan=3|Auto Eat Tier 3!!colspan=3|Auto Eat Tier 2!!colspan=3|Auto Eat Tier 1'
result = result..'\r\n|-class="headerRow-0"'
result = result..'\r\n!DR %!!'..StyleHeader
 
local getHpForStyle = function(playerStyle, autoEat, playerDR)
return nil
end
 
for dr = minDR, MaxVisibleDR, 1 do
end
 
result = result..'\r\n|}'
 
return result
end
 
function p.getDungeonDRTable(frame)
local dungName = frame.args ~= nil and frame.args[1] or frame[1]
local mode = frame.args ~= nil and frame.args[2] or frame[2]
local doStuns = frame.args ~= nil and frame.args[3] or frame[3]
local dung = CombatAreas.getArea(dungName)
 
if dung == nil then
return 'ERROR: Invalid dungeon name'
end
 
return p._getDungeonDRTable(dung, mode, doStuns)
end
end


return p
return p

Latest revision as of 21:53, 6 October 2023

Documentation for this module may be created at Module:CombatAreas/AreaTables/doc

--Splitting this out so I can make Module:Monsters calls (Monsters calls CombatAreas, so this prevents a loop)

local p = {}

local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local GameData = require('Module:GameData')
local Icons = require('Module:Icons')
local Items = require('Module:Items')
local Monsters = require('Module:Monsters')
local Pets = require('Module:Pets')
local Areas = require('Module:CombatAreas')

function p.getLowHighLevels(idList)
	local lowLevel = 1000000
	local highLevel = 0
	for i, monID in ipairs(idList) do
		local monster = Monsters.getMonsterByID(monID)
		local cmbLevel = Monsters._getMonsterCombatLevel(monster)
		if cmbLevel < lowLevel then lowLevel = cmbLevel end
		if cmbLevel > highLevel then highLevel = cmbLevel end
	end
	return lowLevel, highLevel
end

function p.getCombatAreaTable()
	local result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!colspan="2"|Zone!!Difficulty!!Lowest Monster Level!!Highest Monster Level!!Requirements'

	local areas = GameData.sortByOrderTable(GameData.rawData.combatAreas, GameData.rawData.combatAreaDisplayOrder)
	for i, area in ipairs(areas) do
		result = result..'\r\n|-'
		result = result..'\r\n|class="table-img" data-sort-value="' .. area.name .. '"| '..Icons.Icon({area.name, type='combatArea', size='50', notext=true})
		result = result..'||' .. Icons.getExpansionIcon(area.id) .. Icons.Icon({area.name, type='combatArea', noicon=true})
		result = result..'||data-sort-value="'..area.difficulty[1]..'"|'..Areas._getAreaStat(area, 'difficulty')
		local lowLvl, highLvl = p.getLowHighLevels(area.monsterIDs)
		result = result .. '||data-sort-value="' .. lowLvl .. '"| ' .. Shared.formatnum(lowLvl)
		result = result .. '||data-sort-value="' .. highLvl .. '"| ' .. Shared.formatnum(highLvl)
		local reqText = Areas._getAreaRequirements(area)
		if reqText == nil or reqText == '' then
			result = result .. '||class="table-na"| None'
		else
			result = result .. '||' .. reqText
		end
	end
	result = result..'\r\n|}'

	return result
end

function p.getSlayerAreaTable()
	local result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!colspan="2"|Zone!!Difficulty!!Highest Monster Level!!Requirements!!Area Effect'

	local areas = GameData.sortByOrderTable(GameData.rawData.slayerAreas, GameData.rawData.slayerAreaDisplayOrder)
	for i, area in ipairs(areas) do
		result = result..'\r\n|-'
		result = result..'\r\n|class="table-img" data-sort-value="' .. area.name .. '"| '..Icons.Icon({area.name, type='slayer', size='50', notext=true})
		result = result..'||' .. Icons.getExpansionIcon(area.id) .. Icons.Icon({area.name, type='slayer', noicon=true})
		result = result..'||data-sort-value="'..area.difficulty[1]..'"|'..Areas._getAreaStat(area, 'difficulty')
		local lowLvl, highLvl = p.getLowHighLevels(area.monsterIDs)
		result = result..'||data-sort-value="' .. highLvl .. '"| ' .. Shared.formatnum(highLvl)
		local reqText = Areas._getAreaRequirements(area)
		if reqText == nil or reqText == '' then
			result = result .. '||class="table-na"| None'
		else
			result = result .. '||' .. reqText
		end
		local effectText = Areas._getAreaStat(area, 'areaEffectDesc')
		local classText = ((effectText == nil or effectText == 'None') and 'class="table-na"|') or ''
		result = result..'||' .. classText .. ' ' .. effectText
	end

	result = result..'\r\n|}'

	return result
end

function p._getDungeonRewards(area, asList)
	if asList == nil then
		asList = true
	elseif type(asList) == 'string' then
		asList = string.upper(asList) ~= 'FALSE'
	end

	local chr = asList and '* ' or ''
	local rewardList = {}
	
	-- GP reward
	if area.eventID == nil then
		local bossMonster = Monsters.getMonsterByID(area.monsterIDs[Shared.tableCount(area.monsterIDs)])
		local gp = bossMonster.gpDrops
		if gp.min > 0 and gp.max > 0 then
			if gp.min == gp.max then
				table.insert(rewardList, chr .. Icons.GP(gp.min))
			else
				table.insert(rewardList, chr .. Icons.GP(gp.min, gp.max))
			end
		end
	end
	
	-- Item rewards
	local itemLists = {}
	if type(area.rewardItemIDs) == 'table' then
		table.insert(itemLists, area.rewardItemIDs)
	end
	if area.eventID ~= nil then
		local event = GameData.getEntityByID('combatEvents', area.eventID)
		if event ~= nil and type(event.itemRewardIDs) == 'table' then
			table.insert(itemLists, event.itemRewardIDs)
		end
	end
	for i, itemList in ipairs(itemLists) do
		for j, rewardID in ipairs(itemList) do
			local rewardItem = Items.getItemByID(rewardID)
			if rewardItem == nil then
				table.insert(rewardList, chr .. 'Unknown item (ID ' .. rewardID .. ')[[Category:Pages with script errors]]')
			else
				table.insert(rewardList, chr .. Icons.Icon({rewardItem.name, type='item', qty=1}))
			end
		end
	end

	if asList then
		return table.concat(rewardList, '\r\n')
	else
		return table.concat(rewardList, '<br/>')
	end
end

function p.getDungeonRewards(frame)
	local areaName = frame.args ~= nil and frame.args[1] or frame
	local asList = frame.args ~= nil and frame.args[2] or true
	local area = Areas.getArea(areaName)
	if area == nil then
		return Shared.printError('Could not find an area named "' .. areaName .. '"')
	end

	if area.type == 'dungeon' then
		return p._getDungeonRewards(area, asList)
	else
		return Shared.printError('"' .. areaName .. '" is not a dungeon')
	end
end

function p.getDungeonTable(frame)
	local result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|-class="headerRow-0"'
	result = result..'\r\n!colspan="2"|Dungeon!!Difficulty!!Monsters!!Boss Level!!Requirements!!Rewards!!Boss Pet'

	local areas = GameData.sortByOrderTable(GameData.rawData.dungeons, GameData.rawData.dungeonDisplayOrder)
	for i, dung in ipairs(areas) do
		local monsterCount = Shared.tableCount(dung.monsterIDs)
		local boss = Monsters.getMonsterByID(dung.monsterIDs[monsterCount])

		result = result..'\r\n|-'
		result = result..'\r\n|class="table-img" data-sort-value="'..dung.name..'"|'..Icons.Icon({dung.name, type='dungeon', size='50', notext=true})
		result = result..'||' .. Icons.getExpansionIcon(dung.id) .. Icons.Icon({dung.name, type='dungeon', noicon=true})
		result = result..'||data-sort-value="'..dung.difficulty[1]..'"|'..Areas._getAreaStat(dung, 'difficulty')
		result = result..'||'..monsterCount
		result = result..'||'..Shared.formatnum(Monsters._getMonsterCombatLevel(boss))
		local reqText = Areas._getAreaRequirements(dung)
		if reqText == nil or reqText == '' then
			result = result .. '||class="table-na"| None'
		else
			result = result .. '||' .. reqText
		end
		result = result..'||'..p._getDungeonRewards(dung, false)
		local petAdded = false
		if dung.pet ~= nil then
			local pet = GameData.getEntityByID('pets', dung.pet.petID)
			if pet ~= nil then
				result = result..'||data-sort-value="'..pet.name..'"|'..Icons.Icon({pet.name, type='pet'})
				local petDrop = Pets._getPetChance(pet)
				if petDrop ~= nil then
					result = result..'<br/>'..petDrop
				end
				petAdded = true
			end
		end
		if not petAdded then
			result = result..'||class="table-na"| None'
		end
	end

	result = result..'\r\n|}'
	return result
end

function p.buildCombatNavText(frame)
	--This isn't actually called on any pages but instead exists to save me time on updating Template:CombatNav for the new expansion
	local areas = GameData.sortByOrderTable(GameData.rawData.slayerAreas, GameData.rawData.slayerAreaDisplayOrder)
	local outArray = {}
	for i, area in ipairs(areas) do
		local id = area.id
		if Shared.startsWith(id, 'melvorTotH') then
			table.insert(outArray, '|-')
			table.insert(outArray, '| {{TotH}} {{ZoneIcon|'..area.name..'}}')
			local monsterArray = {}
			for j, monsterID in ipairs(area.monsterIDs) do
				local monster = Monsters.getMonsterByID(monsterID)
				table.insert(monsterArray, '{{MonsterIcon|'..monster.name..'}}')
			end
			table.insert(outArray, '| class="center" style="vertical-align:middle;" | '..table.concat(monsterArray, ' {{*}} '))
		end
	end
	
	areas = GameData.sortByOrderTable(GameData.rawData.dungeons, GameData.rawData.dungeonDisplayOrder)
	for i, area in ipairs(areas) do
		local id = area.id
		if Shared.startsWith(id, 'melvorTotH') then
			table.insert(outArray, '|-')
			table.insert(outArray, '| {{TotH}} {{ZoneIcon|'..area.name..'}}')
			local monsterArray = {}
			local mCheck = {}
			for j, monsterID in ipairs(area.monsterIDs) do
				local monster = Monsters.getMonsterByID(monsterID)
				if mCheck[monster.name] == nil then
					table.insert(monsterArray, '{{MonsterIcon|'..monster.name..'}}')
					mCheck[monster.name] = 1
				end
					end
			table.insert(outArray, '| class="center" style="vertical-align:middle;" | '..table.concat(monsterArray, ' {{*}} '))
		end
	end
	
	return table.concat(outArray, '\r\n')
end

return p