Module:SkillUnlocks

Revision as of 01:36, 23 April 2023 by Pksage (talk | contribs)

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

local p = {}

--This module polls various game data sources to produce a full list of skill
--level unlocks for each skill. The game has a hard-coded set of "milestones"
--for each skill that does the same thing, but it is not exhaustive and not
--permanently visible for most combat skills.

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

local WEARABLES = {'Armour', 'Ring', 'Amulet'}
local CHECK_ITEMS = {'Attack', 'Strength', 'Defence', 'Ranged', 'Magic'}

function p._getAllItemsWithSkillRequirement(skillReqLabel)
	local itemList = Items.getItems(function(item)
		-- Exclude Golbin Raid exclusives
		if item.golbinRaidExclusive ~= nil and item.golbinRaidExclusive then
			return false
		end
		
		return Items._getItemStat(item, skillReqLabel) ~= nil
	end)
	
	local itemsWithReqs = {}
	for i, item in ipairs(itemList) do
		local processedItem = {}
		processedItem.item = item
		processedItem.skillLevel = Items._getItemStat(item, skillReqLabel)
		table.insert(itemsWithReqs, processedItem)
	end
	
	return itemsWithReqs
end

function p._getSkillUnlockTable(skillName)
	local skillReqLabel = skillName:lower() .. 'LevelRequired'
	
	-- What do we need to check for this skill? (we avoid checking everything
	-- for every skill to save time)
	local itemList = {}
	if Shared.contains(CHECK_ITEMS, skillName) then
		itemList = p._getAllItemsWithSkillRequirement(skillReqLabel)
	end
	
	if Shared.tableIsEmpty(itemList) then
		-- TODO: Omit empty tables
		return nil
	end
	
	-- Sort the list of items by level requirement
	table.sort(itemList, function(a, b) 
		return a.skillLevel < b.skillLevel or (a.skillLevel == b.skillLevel and a.item.name < b.item.name)
	end)
	
	-- Header and columns
	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable"\r\n|-class="headerRow-0"')
	table.insert(resultPart, '\r\n!' .. Icons.Icon({skillName, type='skill', notext='true'}) .. ' Level')
	table.insert(resultPart, '\r\n!Unlocks')
	
	-- Time to iterate the list!
	local currentLevel = 0
	for i, item in ipairs(itemList) do
		local itemLevel = Items._getItemStat(item.item, skillName .. 'LevelRequired')
		
		-- Start a new row if the current item's level differs from the current
		-- row
		if itemLevel ~= currentLevel then
			currentLevel = itemLevel
			table.insert(resultPart, '\r\n|-')
			table.insert(resultPart, '\r\n|' .. itemLevel)
			table.insert(resultPart, '\r\n|')
		else
			table.insert(resultPart, '<br/>')
		end
		
		-- Append item to the column
		local verb = ''
		if item.item.type == 'Weapon' then
			verb = 'Wield '
		elseif Shared.contains(WEARABLES, item.item.type) then
			verb = 'Wear '
		end
		
		table.insert(resultPart, verb .. Icons.Icon({item.item.name, type='item'}))
	end
	
	table.insert(resultPart, '\r\n|}')

	return table.concat(resultPart)
end

function p.getSkillUnlockTable(frame)
	local skillName = frame.args ~= nil and frame.args[1]
	return p._getSkillUnlockTable(skillName)
end

return p