Module:Skills/Agility

From Melvor Idle
< Module:Skills
Revision as of 02:01, 13 April 2022 by Falterfire (talk | contribs) (Attempted to add getCourseTable. Time to see if it works)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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