Module:Skills: Difference between revisions

getMasteryTokenTable: Correct values for change in game logic & extend to display both base game and TotH values
(Undo revision 60644 by Auron956 (talk) - Reinstate changes)
Tag: Undo
(getMasteryTokenTable: Correct values for change in game logic & extend to display both base game and TotH values)
Line 22: Line 22:
local Items = require('Module:Items')
local Items = require('Module:Items')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')
-- Given a skill ID, returns the key for that skill's recipe data.
-- If the skill has no recipes (e.g. is a combat skill) then the
-- return value is nil
function p.getSkillRecipeKey(skillID)
-- Convert skillID to local ID if not already
local ns, localSkillID = GameData.getLocalID(skillID)
local recipeIDs = {
["Woodcutting"] = 'trees',
["Fishing"] = 'fish',
["Firemaking"] = 'logs',
["Mining"] = 'rockData',
["Thieving"] = 'npcs',
["Agility"] = 'obstacles',
["Cooking"] = 'recipes',
["Smithing"] = 'recipes',
["Farming"] = 'recipes',
["Summoning"] = 'recipes',
["Fletching"] = 'recipes',
["Crafting"] = 'recipes',
["Runecrafting"] = 'recipes',
["Herblore"] = 'recipes',
["Astrology"] = 'recipes'
}
return recipeIDs[localSkillID]
end
-- Given a skill ID & recipe, returns the skill level requirement for
-- that recipe. If the level could not be determined, then the return
-- value is nil
function p.getRecipeLevel(skillID, recipe)
-- Convert skillID to local ID if not already
local ns, localSkillID = GameData.getLocalID(skillID)
if localSkillID == 'Agility' then
-- For Agility, level is derived from obstacle category
if recipe.category ~= nil then
-- Obstacle
if recipe.category == 0 then
return 1
else
return SkillData.Agility.obstacleUnlockLevels[recipe.category]
end
else
-- Pillar
local nsR, localRecipeID = GameData.getLocalID(recipe.id)
if localRecipeID ~= nil then
if string.find(localRecipeID, '^Pillar') ~= nil then
return 99
elseif string.find(localRecipeID, '^ElitePillar') ~= nil then
return 120
end
end
end
else
-- For all other skills, the recipe should have a level property
return recipe.level
end
end


-- Thieving
-- Thieving
Line 283: Line 341:


function p.getMasteryTokenTable()
function p.getMasteryTokenTable()
-- Defines which skill levels should be included within the output
local skillLevels = {
{
["id"] = 'Base',
["level"] = 99,
["description"] = '[[Full Version|Base Game]] (Level 99)'
}, {
["id"] = 'TotH',
["level"] = 120,
["description"] = Icons.TotH() .. ' [[Throne of the Herald Expansion|Throne of the Herald]] (Level 120)'
}
}
local baseTokenChance = 18500
local baseTokenChance = 18500
local masterySkills = {}
local masteryActionCount = {}
local CCI = Items.getItemByID('melvorD:Clue_Chasers_Insignia')
local CCI_ID = 'melvorD:Clue_Chasers_Insignia'
if CCI == nil then return '' end
local CCI = Items.getItemByID(CCI_ID)
if CCI == nil then
return Shared.printError('Failed to find item with ID ' .. CCI_ID)
end


-- Build table of mastery skills
-- Iterate over each skill with mastery, determining the number of
-- mastery actions for each
for skillLocalID, skill in pairs(SkillData) do
for skillLocalID, skill in pairs(SkillData) do
if skill.masteryTokenID ~= nil then
if skill.masteryTokenID ~= nil then
table.insert(masterySkills, skill)
local actCount = { ["skill"] = skill }
for i, levelDef in ipairs(skillLevels) do
actCount[levelDef.id] = 0
end
 
local recipeKey = p.getSkillRecipeKey(skillLocalID)
if recipeKey ~= nil then
local recipeData = skill[recipeKey]
for i, recipe in ipairs(recipeData) do
if recipe.noMastery == nil or not recipe.noMastery then
local skillLevel = p.getRecipeLevel(skillLocalID, recipe)
if skillLevel ~= nil then
for j, levelDef in ipairs(skillLevels) do
if skillLevel <= levelDef.level then
actCount[levelDef.id] = actCount[levelDef.id] + 1
end
end
end
end
end
end
table.insert(masteryActionCount, actCount)
end
end
end
end
table.sort(masterySkills,
 
local firstID = skillLevels[1].id
table.sort(masteryActionCount,
function(a, b)
function(a, b)
if a.milestoneCount == b.milestoneCount then
if a[firstID] == b[firstID] then
return a.name < b.name
return a.skill.name < b.skill.name
else
else
return a.milestoneCount > b.milestoneCount
return a[firstID] > b[firstID]
end
end
end)
end)
 
-- Generate output table
-- Generate output table
local resultPart = {}
local resultPart = {}
local CCIIcon = Icons.Icon({CCI.name, type='item', notext=true})
local CCIIcon = Icons.Icon({CCI.name, type='item', notext=true})
local columnPairs = Shared.tableCount(skillLevels)


-- Generate header
table.insert(resultPart, '{| class="wikitable sortable"')
table.insert(resultPart, '{| class="wikitable sortable"')
table.insert(resultPart, '\r\n!rowspan="2"|Token!!rowspan="2"|Skill!!colspan="2"|Approximate Mastery Token Chance')
table.insert(resultPart, '\n!rowspan="3"|Token!!rowspan="3"|Skill!!colspan="' .. columnPairs * 2 .. '"|Approximate Mastery Token Chance')
table.insert(resultPart, '\r\n|-\r\n!Without ' .. CCIIcon .. '!!With ' .. CCIIcon)
table.insert(resultPart, '\n|-')
for i, levelDef in ipairs(skillLevels) do
table.insert(resultPart, '\n!colspan="2"| ' .. levelDef.description)
end
table.insert(resultPart, '\n|-' .. string.rep('\n!Without ' .. CCIIcon .. '\n!With ' .. CCIIcon, columnPairs))


for i, skill in ipairs(masterySkills) do
for i, rowData in ipairs(masteryActionCount) do
local token = Items.getItemByID(skill.masteryTokenID)
local token = Items.getItemByID(rowData.skill.masteryTokenID)
local denom = math.floor(baseTokenChance / skill.milestoneCount)
table.insert(resultPart, '\n|-')
local denomCCI = Shared.round(baseTokenChance / (skill.milestoneCount * (1 + CCI.modifiers.increasedOffItemChance / 100)), 0, 0)
table.insert(resultPart, '\n|style="text-align:center"|' .. Icons.Icon({token.name, type='item', size=50, notext=true}))
table.insert(resultPart, '\n|' .. Icons.Icon({rowData.skill.name, type='skill'}))


table.insert(resultPart, '\r\n|-')
for j, levelDef in ipairs(skillLevels) do
table.insert(resultPart, '\r\n|style="text-align:center"|' .. Icons.Icon({token.name, type='item', size=50, notext=true}))
local actCount = rowData[levelDef.id]
table.insert(resultPart, '\r\n|' .. Icons.Icon({skill.name, type='skill'}))
local denom, denomCCI = 0, 0
table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denom .. '"|1/' .. Shared.formatnum(denom))
if actCount > 0 then
table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denomCCI .. '"|1/' .. Shared.formatnum(denomCCI))
denom = math.floor(baseTokenChance / actCount)
denomCCI = Shared.round(baseTokenChance / (actCount * (1 + CCI.modifiers.increasedOffItemChance / 100)), 0, 0)
end
table.insert(resultPart, '\n|style="text-align:right" data-sort-value="' .. denom .. '"|1/' .. Shared.formatnum(denom))
table.insert(resultPart, '\n|style="text-align:right" data-sort-value="' .. denomCCI .. '"|1/' .. Shared.formatnum(denomCCI))
end
end
end
table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\n|}')


return table.concat(resultPart)
return table.concat(resultPart)