Difference between revisions of "Module:Skills/Agility"

From Melvor Idle
(Added grouping by agility slot)
(Attempted to add getCourseTable. Time to see if it works)
 
(16 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
local p = {}
 
local p = {}
  
local ItemData = mw.loadData('Module:Items/data')
 
 
local SkillData = mw.loadData('Module:Skills/data')
 
local SkillData = mw.loadData('Module:Skills/data')
  
Line 7: Line 6:
 
local Shared = require('Module:Shared')
 
local Shared = require('Module:Shared')
 
local Items = require('Module:Items')
 
local Items = require('Module:Items')
local ItemSourceTables = require('Module:Items/SourceTables')
 
 
local Icons = require('Module:Icons')
 
local Icons = require('Module:Icons')
 +
 +
function p.getObstacleByID(obstID)
 +
local result = Shared.clone(SkillData.Agility.Obstacles[obstID + 1])
 +
return result
 +
end
 +
 +
function p.getObstacle(name)
 +
for i, obst in ipairs(SkillData.Agility.Obstacles) do
 +
if obst.name == name then
 +
local result = Shared.clone(obst)
 +
result.id = i - 1
 +
return result
 +
end
 +
end
 +
return nil
 +
end
 +
 +
function p.getObstacles(checkFunc)
 +
local result = {}
 +
for i, obst in ipairs(SkillData.Agility.Obstacles) do
 +
if checkFunc(obst) then
 +
local newObst = Shared.clone(obst)
 +
newObst.id = i - 1
 +
table.insert(result, newObst)
 +
end
 +
end
 +
return result
 +
end
 +
 +
function p.getPillars(checkFunc)
 +
local result = {}
 +
for i, pillar in ipairs(SkillData.Agility.Pillars) do
 +
if checkFunc(pillar) then
 +
local newPillar = Shared.clone(pillar)
 +
newPillar.id = i - 1
 +
table.insert(result, newPillar)
 +
end
 +
end
 +
return result
 +
end
 +
 +
function p._getObstacleRequirements(obstacle)
 +
local resultPart = {}
 +
if obstacle.category == nil then
 +
-- Pillar
 +
table.insert(resultPart, Icons._SkillReq('Agility', 99))
 +
elseif obstacle.category > 0 then
 +
-- Obstacle
 +
table.insert(resultPart, Icons._SkillReq('Agility', obstacle.category * 10))
 +
end
 +
if type(obstacle.skillRequirements) == 'table' then
 +
for i, skillReq in ipairs(obstacle.skillRequirements) do
 +
local skillName = Constants.getSkillName(skillReq.skill)
 +
if skillName ~= nil then
 +
table.insert(resultPart, Icons._SkillReq(skillName, skillReq.level))
 +
end
 +
end
 +
end
 +
return table.concat(resultPart, '<br/>')
 +
end
  
 
function p.getObstacleCourseTable(frame)
 
function p.getObstacleCourseTable(frame)
  local result = ''
+
local result = ''
  
  result = '{| class="wikitable sortable stickyHeader"'
+
result = '{| class="wikitable sortable stickyHeader"'
  result = result..'\r\n|- class="headerRow-0"'
+
result = result..'\r\n|- class="headerRow-0"'
  result = result..'\r\n!Slot!!Name!!XP!!GP!!Time'--!!XP/s!!GP/s
+
result = result..'\r\n!Slot!!Name!!XP!!GP!!Time!!XP/s!!GP/s'--!!XP/s!!GP/s (left comment here for posterity)
  result = result..'!!Bonuses!!Requirements!!Cost'
+
result = result..'!!Bonuses!!Requirements!!Cost'
  
  local catLog = {}
+
local catLog = {}
 +
local Obstacles = Shared.clone(SkillData.Agility.Obstacles)
 +
table.sort(Obstacles, function(a, b) return (a.category == b.category and a.id < b.id) or a.category < b.category end)
  
  for i, obst in Shared.skpairs(SkillData.Agility.Obstacles) do
+
local catCounts = {}
    result = result..'\r\n|-'
+
for i, obst in ipairs(Obstacles) do
    result = result..'\r\n|'
+
if catCounts[obst.category] == nil then
    if catLog[obst.category] == nil then
+
catCounts[obst.category] = 1
      local rowspan = obst.category > 1 and 5 or 3
+
else
      result = result..'rowspan="'..rowspan..'"|'..(obst.category + 1)..'||'
+
catCounts[obst.category] = catCounts[obst.category] + 1
      catLog[obst.category] = true
+
end
    end
+
end
    result = result..obst.name
 
  
    --After the name & category, doing XP, GP, Time, and rates
+
for i, obst in ipairs(Obstacles) do
    local XP = obst.completionBonuses.xp
+
result = result..'\r\n|-'
    local GP = obst.completionBonuses.gp
+
result = result..'\r\n|'
    local Time = obst.interval / 1000
+
if catLog[obst.category] == nil then
    result = result..'||'..XP..'||data-sort-value="'..GP..'"|'..Icons.GP(GP)
+
local rowspan = catCounts[obst.category]
    result = result..'||data-sort-value="'..Time..'"|'..Shared.timeString(Time, true)
+
result = result..'rowspan="'..rowspan..'" style="border:1px solid black"|'..(obst.category + 1)..'||'
    --result = result..'||'..Shared.round(XP / Time, 2, 2)
+
catLog[obst.category] = true
    --result = result..'||data-sort-value="'..GP/Time..'"|'..Icons.GP(Shared.round(GP/Time, 2, 2))
+
end
 +
result = result..obst.name
  
    local bonuses = {}
+
--After the name & category, doing XP, GP, Time, and rates
    --After that, adding the bonuses
+
local XP = obst.completionBonuses.xp
    for bonusName, bonusValue in pairs(obst.modifiers) do
+
local GP = obst.completionBonuses.gp
      if type(bonusValue) == 'table' then
+
local Time = obst.interval / 1000
        for j, trueBonus in pairs(bonusValue) do
+
result = result..'||'..XP..'||data-sort-value="'..GP..'"|'..Icons.GP(GP)
          table.insert(bonuses, Constants.getModifierText(bonusName, trueBonus))
+
result = result..'||data-sort-value="'..Time..'"|'..Shared.timeString(Time, true)
        end
+
-- Readded XP/Time and GP/Time (previously commented out)
      else
+
result = result..'||'..Shared.round(XP / Time, 2, 2)
        table.insert(bonuses, Constants.getModifierText(bonusName, bonusValue))
+
result = result..'||data-sort-value="'..GP/Time..'"|'..Icons.GP(Shared.round(GP/Time, 2, 2))
      end
 
    end
 
    if Shared.tableCount(bonuses) == 0 then
 
      table.insert(bonuses, '<span style="color:red">None :(</span>')
 
    end
 
    result = result..'||'..table.concat(bonuses, '<br/>')
 
  
    --Grabbing requirements to create
+
local bonuses = {}
    result = result..'||'
+
--After that, adding the bonuses
    if obst.category > 0 then
+
for bonusName, bonusValue in pairs(obst.modifiers) do
      result = result..Icons._SkillReq('Agility', obst.category * 10)
+
table.insert(bonuses, Constants._getModifierText(bonusName, bonusValue))
    end
+
end
    if obst.requirements ~= nil and obst.requirements.skillLevel ~= nil then
+
if Shared.tableCount(bonuses) == 0 then
      for j, skillReq in Shared.skpairs(obst.requirements.skillLevel) do
+
table.insert(bonuses, '<span style="color:red">None :(</span>')
        result = result..'<br/>'..Icons._SkillReq(Constants.getSkillName(skillReq[1]), skillReq[2])
+
end
      end
+
result = result..'||'..table.concat(bonuses, '<br/>')
    end
 
  
    --Finally, the cost
+
--Grabbing requirements to create
    local costs = {}
+
result = result..'|| ' .. p._getObstacleRequirements(obst)
    if obst.cost.gp > 0 then table.insert(costs, Icons.GP(obst.cost.gp)) end
 
    if obst.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(obst.cost.slayerCoins)) end
 
    for j, itemCost in Shared.skpairs(obst.cost.items) do
 
      local item = Items.getItemByID(itemCost[1])
 
      table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
 
    end
 
    result = result..'|| data-sort-value="'..obst.cost.gp..'"|'..table.concat(costs, '<br/>')
 
  end
 
  
  result = result..'\r\n|}'
+
--Finally, the cost
 +
local costs = {}
 +
if obst.cost.gp > 0 then table.insert(costs, Icons.GP(obst.cost.gp)) end
 +
if obst.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(obst.cost.slayerCoins)) end
 +
for j, itemCost in ipairs(obst.cost.items) do
 +
local item = Items.getItemByID(itemCost[1])
 +
table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
 +
end
 +
result = result..'|| data-sort-value="'..obst.cost.gp..'"|'..table.concat(costs, '<br/>')
 +
end
  
  return result
+
result = result..'\r\n|}'
 +
 
 +
return result
 
end
 
end
  
 
function p.getPassivePillarTable(frame)
 
function p.getPassivePillarTable(frame)
  local result = ''
+
local result = ''
 +
 
 +
result = '{| class="wikitable sortable stickyHeader"'
 +
result = result..'\r\n|- class="headerRow-0"'
 +
result = result..'\r\n!Name!!Bonuses!!Cost'
 +
 
 +
for i, pill in ipairs(SkillData.Agility.Pillars) do
 +
result = result..'\r\n|-'
 +
result = result..'\r\n|'..pill.name
 +
 
 +
--After that, adding the bonuses
 +
local bonuses = {}
 +
for bonusName, bonusValue in pairs(pill.modifiers) do
 +
table.insert(bonuses, Constants._getModifierText(bonusName, bonusValue))
 +
end
 +
if Shared.tableCount(bonuses) == 0 then
 +
table.insert(bonuses, '<span style="color:red">None :(</span>')
 +
end
 +
result = result..'||'..table.concat(bonuses, '<br/>')
 +
 
 +
--Finally, the cost
 +
local costs = {}
 +
if pill.cost.gp > 0 then table.insert(costs, Icons.GP(pill.cost.gp)) end
 +
if pill.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(pill.cost.slayerCoins)) end
 +
for j, itemCost in ipairs(pill.cost.items) do
 +
local item = Items.getItemByID(itemCost[1])
 +
table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
 +
end
 +
result = result..'|| data-sort-value="'..pill.cost.gp..'"|'..table.concat(costs, '<br/>')
 +
end
 +
 
 +
result = result..'\r\n|}'
 +
 
 +
return result
 +
end
 +
 
 +
function p.getObstaclesForItem(itemID)
 +
local result = {}
 +
for i, obst in ipairs(SkillData.Agility.Obstacles) do
 +
for j, costLine in ipairs(obst.cost.items) do
 +
if costLine[1] == itemID then
 +
table.insert(result, obst)
 +
end
 +
end
 +
end
 +
 
 +
for i, obst in ipairs(SkillData.Agility.Pillars) do
 +
for j, costLine in ipairs(obst.cost.items) do
 +
if costLine[1] == itemID then
 +
table.insert(result, obst)
 +
end
 +
end
 +
end
 +
 
 +
return result
 +
end
 +
 
 +
function p._getCourseTable(obstacleNames)
 +
local result = ''
 +
local Obstacles = {}
 +
for i, name in pairs(obstacleNames) do
 +
local obst = p.getObstacle(Shared.trim(name))
 +
if obst == nil then
 +
result = result..'ERROR: Invalid Obstacle Name "'..name..'"[[Category:Pages with script errors]]<br/>'
 +
else
 +
table.insert(Obstacles, obst)
 +
end
 +
end
 +
 
 +
result = result..'{| class="wikitable sortable stickyHeader"'
 +
result = result..'\r\n|- class="headerRow-0"'
 +
result = result..'\r\n!Slot!!Name!!Bonuses!!Requirements!!Cost'
  
  result = '{| class="wikitable sortable stickyHeader"'
+
local catLog = {}
  result = result..'\r\n|- class="headerRow-0"'
+
  result = result..'\r\n!Name!!Bonuses!!Cost'
+
table.sort(Obstacles, function(a, b) return (a.category == b.category and a.id < b.id) or a.category < b.category end)
  
  for i, pill in Shared.skpairs(SkillData.Agility.Pillars) do
+
local catCounts = {}
    result = result..'\r\n|-'
+
for i, obst in ipairs(Obstacles) do
    result = result..'\r\n|'..pill.name
+
if catCounts[obst.category] == nil then
 +
catCounts[obst.category] = 1
 +
else
 +
catCounts[obst.category] = catCounts[obst.category] + 1
 +
end
 +
end
  
    --After that, adding the bonuses
+
for i, obst in ipairs(Obstacles) do
    local bonuses = {}
+
result = result..'\r\n|-'
    for bonusName, bonusValue in pairs(pill.modifiers) do
+
result = result..'\r\n|'
      if type(bonusValue) == 'table' then
+
if catLog[obst.category] == nil then
        for j, trueBonus in pairs(bonusValue) do
+
local rowspan = catCounts[obst.category]
          table.insert(bonuses, Constants.getModifierText(bonusName, trueBonus))
+
result = result..'rowspan="'..rowspan..'" style="border:1px solid black"|'..(obst.category + 1)..'||'
        end
+
catLog[obst.category] = true
      else
+
end
        table.insert(bonuses, Constants.getModifierText(bonusName, bonusValue))
+
result = result..obst.name
      end
 
    end
 
    if Shared.tableCount(bonuses) == 0 then
 
      table.insert(bonuses, '<span style="color:red">None :(</span>')
 
    end
 
    result = result..'||'..table.concat(bonuses, '<br/>')
 
  
    --Finally, the cost
+
local bonuses = {}
    local costs = {}
+
--After that, adding the bonuses
    if pill.cost.gp > 0 then table.insert(costs, Icons.GP(pill.cost.gp)) end
+
for bonusName, bonusValue in pairs(obst.modifiers) do
    if pill.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(pill.cost.slayerCoins)) end
+
table.insert(bonuses, Constants._getModifierText(bonusName, bonusValue))
    for j, itemCost in Shared.skpairs(pill.cost.items) do
+
end
      local item = Items.getItemByID(itemCost[1])
+
if Shared.tableCount(bonuses) == 0 then
      table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
+
table.insert(bonuses, '<span style="color:red">None :(</span>')
    end
+
end
    result = result..'|| data-sort-value="'..pill.cost.gp..'"|'..table.concat(costs, '<br/>')
+
result = result..'||'..table.concat(bonuses, '<br/>')
  end
 
  
  result = result..'\r\n|}'
+
--Grabbing requirements to create
 +
result = result..'|| ' .. p._getObstacleRequirements(obst)
 +
 
 +
--Finally, the cost
 +
local costs = {}
 +
if obst.cost.gp > 0 then table.insert(costs, Icons.GP(obst.cost.gp)) end
 +
if obst.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(obst.cost.slayerCoins)) end
 +
for j, itemCost in ipairs(obst.cost.items) do
 +
local item = Items.getItemByID(itemCost[1])
 +
table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
 +
end
 +
result = result..'|| data-sort-value="'..obst.cost.gp..'"|'..table.concat(costs, '<br/>')
 +
end
 +
 
 +
result = result..'\r\n|}'
 +
 
 +
return result
 +
end
  
  return result
+
function p.getCourseTable(frame)
 +
local obstNameStr = frame.args ~= nil and frame.args[1] or frame
 +
local obstacleNames = Shared.splitString(obstNameStr, ',')
 +
 +
return p._getCourseTable(obstacleNames)
 
end
 
end
  
 
return p
 
return p

Latest revision as of 02:01, 13 April 2022

Documentation for this module may be created at Module:Skills/Agility/doc

local p = {}

local SkillData = mw.loadData('Module:Skills/data')

local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Items = require('Module:Items')
local Icons = require('Module:Icons')

function p.getObstacleByID(obstID)
	local result = Shared.clone(SkillData.Agility.Obstacles[obstID + 1])
	return result
end

function p.getObstacle(name)
	for i, obst in ipairs(SkillData.Agility.Obstacles) do
		if obst.name == name then
			local result = Shared.clone(obst)
			result.id = i - 1
			return result
		end
	end
	return nil
end

function p.getObstacles(checkFunc)
	local result = {}
	for i, obst in ipairs(SkillData.Agility.Obstacles) do
		if checkFunc(obst) then
			local newObst = Shared.clone(obst)
			newObst.id = i - 1
			table.insert(result, newObst)
		end
	end
	return result
end

function p.getPillars(checkFunc)
	local result = {}
	for i, pillar in ipairs(SkillData.Agility.Pillars) do
		if checkFunc(pillar) then
			local newPillar = Shared.clone(pillar)
			newPillar.id = i - 1
			table.insert(result, newPillar)
		end
	end
	return result
end

function p._getObstacleRequirements(obstacle)
	local resultPart = {}
	if obstacle.category == nil then
		-- Pillar
		table.insert(resultPart, Icons._SkillReq('Agility', 99))
	elseif obstacle.category > 0 then
		-- Obstacle
		table.insert(resultPart, Icons._SkillReq('Agility', obstacle.category * 10))
	end
	if type(obstacle.skillRequirements) == 'table' then
		for i, skillReq in ipairs(obstacle.skillRequirements) do
			local skillName = Constants.getSkillName(skillReq.skill)
			if skillName ~= nil then
				table.insert(resultPart, Icons._SkillReq(skillName, skillReq.level))
			end
		end
	end
	return table.concat(resultPart, '<br/>')
end

function p.getObstacleCourseTable(frame)
	local result = ''

	result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!Slot!!Name!!XP!!GP!!Time!!XP/s!!GP/s'--!!XP/s!!GP/s (left comment here for posterity)
	result = result..'!!Bonuses!!Requirements!!Cost'

	local catLog = {}
	local Obstacles = Shared.clone(SkillData.Agility.Obstacles)
	table.sort(Obstacles, function(a, b) return (a.category == b.category and a.id < b.id) or a.category < b.category end)

	local catCounts = {}
	for i, obst in ipairs(Obstacles) do
		if catCounts[obst.category] == nil then
			catCounts[obst.category] = 1
		else
			catCounts[obst.category] = catCounts[obst.category] + 1
		end
	end

	for i, obst in ipairs(Obstacles) do
		result = result..'\r\n|-'
		result = result..'\r\n|'
		if catLog[obst.category] == nil then
			local rowspan = catCounts[obst.category]
			result = result..'rowspan="'..rowspan..'" style="border:1px solid black"|'..(obst.category + 1)..'||'
			catLog[obst.category] = true
		end
		result = result..obst.name

		--After the name & category, doing XP, GP, Time, and rates
		local XP = obst.completionBonuses.xp
		local GP = obst.completionBonuses.gp
		local Time = obst.interval / 1000
		result = result..'||'..XP..'||data-sort-value="'..GP..'"|'..Icons.GP(GP)
		result = result..'||data-sort-value="'..Time..'"|'..Shared.timeString(Time, true)
		-- Readded XP/Time and GP/Time (previously commented out)
		result = result..'||'..Shared.round(XP / Time, 2, 2)
		result = result..'||data-sort-value="'..GP/Time..'"|'..Icons.GP(Shared.round(GP/Time, 2, 2))

		local bonuses = {}
		--After that, adding the bonuses
		for bonusName, bonusValue in pairs(obst.modifiers) do
			table.insert(bonuses, Constants._getModifierText(bonusName, bonusValue))
		end
		if Shared.tableCount(bonuses) == 0 then
			table.insert(bonuses, '<span style="color:red">None :(</span>')
		end
		result = result..'||'..table.concat(bonuses, '<br/>')

		--Grabbing requirements to create
		result = result..'|| ' .. p._getObstacleRequirements(obst)

		--Finally, the cost
		local costs = {}
		if obst.cost.gp > 0 then table.insert(costs, Icons.GP(obst.cost.gp)) end
		if obst.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(obst.cost.slayerCoins)) end
		for j, itemCost in ipairs(obst.cost.items) do
			local item = Items.getItemByID(itemCost[1])
			table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
		end
		result = result..'|| data-sort-value="'..obst.cost.gp..'"|'..table.concat(costs, '<br/>')
	end

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

	return result
end

function p.getPassivePillarTable(frame)
	local result = ''

	result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!Name!!Bonuses!!Cost'

	for i, pill in ipairs(SkillData.Agility.Pillars) do
		result = result..'\r\n|-'
		result = result..'\r\n|'..pill.name

		--After that, adding the bonuses
		local bonuses = {}
		for bonusName, bonusValue in pairs(pill.modifiers) do
			table.insert(bonuses, Constants._getModifierText(bonusName, bonusValue))
		end
		if Shared.tableCount(bonuses) == 0 then
			table.insert(bonuses, '<span style="color:red">None :(</span>')
		end
		result = result..'||'..table.concat(bonuses, '<br/>')

		--Finally, the cost
		local costs = {}
		if pill.cost.gp > 0 then table.insert(costs, Icons.GP(pill.cost.gp)) end
		if pill.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(pill.cost.slayerCoins)) end
		for j, itemCost in ipairs(pill.cost.items) do
			local item = Items.getItemByID(itemCost[1])
			table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
		end
		result = result..'|| data-sort-value="'..pill.cost.gp..'"|'..table.concat(costs, '<br/>')
	end

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

	return result
end

function p.getObstaclesForItem(itemID)
	local result = {}
	for i, obst in ipairs(SkillData.Agility.Obstacles) do
		for j, costLine in ipairs(obst.cost.items) do
			if costLine[1] == itemID then
				table.insert(result, obst)
			end
		end
	end

	for i, obst in ipairs(SkillData.Agility.Pillars) do
		for j, costLine in ipairs(obst.cost.items) do
			if costLine[1] == itemID then
				table.insert(result, obst)
			end
		end
	end

	return result
end

function p._getCourseTable(obstacleNames)
	local result = ''
	local Obstacles = {}
	for i, name in pairs(obstacleNames) do
		local obst = p.getObstacle(Shared.trim(name))
		if obst == nil then
			result = result..'ERROR: Invalid Obstacle Name "'..name..'"[[Category:Pages with script errors]]<br/>'
		else
			table.insert(Obstacles, obst)
		end
	end

	result = result..'{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!Slot!!Name!!Bonuses!!Requirements!!Cost'

	local catLog = {}
	
	table.sort(Obstacles, function(a, b) return (a.category == b.category and a.id < b.id) or a.category < b.category end)

	local catCounts = {}
	for i, obst in ipairs(Obstacles) do
		if catCounts[obst.category] == nil then
			catCounts[obst.category] = 1
		else
			catCounts[obst.category] = catCounts[obst.category] + 1
		end
	end

	for i, obst in ipairs(Obstacles) do
		result = result..'\r\n|-'
		result = result..'\r\n|'
		if catLog[obst.category] == nil then
			local rowspan = catCounts[obst.category]
			result = result..'rowspan="'..rowspan..'" style="border:1px solid black"|'..(obst.category + 1)..'||'
			catLog[obst.category] = true
		end
		result = result..obst.name

		local bonuses = {}
		--After that, adding the bonuses
		for bonusName, bonusValue in pairs(obst.modifiers) do
			table.insert(bonuses, Constants._getModifierText(bonusName, bonusValue))
		end
		if Shared.tableCount(bonuses) == 0 then
			table.insert(bonuses, '<span style="color:red">None :(</span>')
		end
		result = result..'||'..table.concat(bonuses, '<br/>')

		--Grabbing requirements to create
		result = result..'|| ' .. p._getObstacleRequirements(obst)

		--Finally, the cost
		local costs = {}
		if obst.cost.gp > 0 then table.insert(costs, Icons.GP(obst.cost.gp)) end
		if obst.cost.slayerCoins > 0 then table.insert(costs, Icons.SC(obst.cost.slayerCoins)) end
		for j, itemCost in ipairs(obst.cost.items) do
			local item = Items.getItemByID(itemCost[1])
			table.insert(costs, Icons.Icon({item.name, type='item', qty = itemCost[2], notext=true}))
		end
		result = result..'|| data-sort-value="'..obst.cost.gp..'"|'..table.concat(costs, '<br/>')
	end

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

	return result
end

function p.getCourseTable(frame)
	local obstNameStr = frame.args ~= nil and frame.args[1] or frame
	local obstacleNames = Shared.splitString(obstNameStr, ',')
	
	return p._getCourseTable(obstacleNames)
end

return p