Difference between revisions of "Module:Skills"

From Melvor Idle
(Removed redundant references to getSkillID since that's now a Constants function)
(Fixed indenting)
Line 24: Line 24:
  
 
function p.getMasteryUnlockTable(frame)
 
function p.getMasteryUnlockTable(frame)
  local skillName = frame.args ~= nil and frame.args[1] or frame
+
local skillName = frame.args ~= nil and frame.args[1] or frame
  local skillID = Constants.getSkillID(skillName)
+
local skillID = Constants.getSkillID(skillName)
  if skillID == nil then
+
if skillID == nil then
    return "ERROR: Failed to find a skill ID for "..skillName
+
return "ERROR: Failed to find a skill ID for "..skillName
  end
+
end
  
  local unlockTable = SkillData.MasteryUnlocks[skillID]
+
local unlockTable = SkillData.MasteryUnlocks[skillID]
  if unlockTable == nil then
+
if unlockTable == nil then
    return 'ERROR: Failed to find Mastery Unlock data for '..skillName
+
return 'ERROR: Failed to find Mastery Unlock data for '..skillName
  end
+
end
  
  local result = '{|class="wikitable"\r\n!Level!!Unlock'
+
local result = '{|class="wikitable"\r\n!Level!!Unlock'
  for i, unlock in Shared.skpairs(unlockTable) do
+
for i, unlock in Shared.skpairs(unlockTable) do
    result = result..'\r\n|-'
+
result = result..'\r\n|-'
    result = result..'\r\n|'..unlock.level..'||'..unlock.unlock
+
result = result..'\r\n|'..unlock.level..'||'..unlock.unlock
  end
+
end
  result = result..'\r\n|}'
+
result = result..'\r\n|}'
  return result
+
return result
 
end
 
end
  
 
function p.getMasteryCheckpointTable(frame)
 
function p.getMasteryCheckpointTable(frame)
  local skillName = frame.args ~= nil and frame.args[1] or frame
+
local skillName = frame.args ~= nil and frame.args[1] or frame
  local skillID = Constants.getSkillID(skillName)
+
local skillID = Constants.getSkillID(skillName)
  if skillID == nil then
+
if skillID == nil then
    return "ERROR: Failed to find a skill ID for "..skillName
+
return "ERROR: Failed to find a skill ID for "..skillName
  end
+
end
  
  if SkillData.MasteryCheckpoints[skillID] == nil then
+
if SkillData.MasteryCheckpoints[skillID] == nil then
    return 'ERROR: Failed to find Mastery Unlock data for '..skillName
+
return 'ERROR: Failed to find Mastery Unlock data for '..skillName
  end
+
end
  
  local bonuses = SkillData.MasteryCheckpoints[skillID].bonuses
+
local bonuses = SkillData.MasteryCheckpoints[skillID].bonuses
  local totalPoolXP = SkillData.MasteryPoolXP[skillID + 1]
+
local totalPoolXP = SkillData.MasteryPoolXP[skillID + 1]
  
  local result = '{|class="wikitable"\r\n!Pool %!!style="width:100px"|Pool XP!!Bonus'
+
local result = '{|class="wikitable"\r\n!Pool %!!style="width:100px"|Pool XP!!Bonus'
  for i, bonus in Shared.skpairs(bonuses) do
+
for i, bonus in Shared.skpairs(bonuses) do
    result = result..'\r\n|-'
+
result = result..'\r\n|-'
    result = result..'\r\n|'..(MasteryCheckpoints[i] * 100)..'%||'
+
result = result..'\r\n|'..(MasteryCheckpoints[i] * 100)..'%||'
    result = result..Shared.formatnum(totalPoolXP * MasteryCheckpoints[i])..' xp||'..bonus
+
result = result..Shared.formatnum(totalPoolXP * MasteryCheckpoints[i])..' xp||'..bonus
  end
+
end
  result = result..'\r\n|-\r\n!colspan="2"|Total Mastery Pool XP'
+
result = result..'\r\n|-\r\n!colspan="2"|Total Mastery Pool XP'
  result = result..'\r\n|'..Shared.formatnum(totalPoolXP)
+
result = result..'\r\n|'..Shared.formatnum(totalPoolXP)
  result = result..'\r\n|}'
+
result = result..'\r\n|}'
  return result
+
return result
 
end
 
end
  
 
function p._getFarmingTable(category)
 
function p._getFarmingTable(category)
  local seedList = {}
+
local seedList = {}
  if category == 'Allotment' or category == 'Herb' or category == 'Tree' then
+
if category == 'Allotment' or category == 'Herb' or category == 'Tree' then
    seedList = Items.getItems(function(item) return item.tier == category end)
+
seedList = Items.getItems(function(item) return item.tier == category end)
  else
+
else
    return 'ERROR: Invalid farming category. Please choose Allotment, Herb, or Tree'
+
return 'ERROR: Invalid farming category. Please choose Allotment, Herb, or Tree'
  end
+
end
  
  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|Seeds!!'..Icons.Icon({'Farming', type='skill', notext=true})..' Level'
+
result = result..'\r\n!colspan=2|Seeds!!'..Icons.Icon({'Farming', type='skill', notext=true})..' Level'
  result = result..'!!XP!!Growth Time!!Seed Value'
+
result = result..'!!XP!!Growth Time!!Seed Value'
  if category == 'Allotment' then
+
if category == 'Allotment' then
    result = result..'!!colspan="2"|Crop!!Crop Healing!!Crop Value'
+
result = result..'!!colspan="2"|Crop!!Crop Healing!!Crop Value'
  elseif category == 'Herb' then
+
elseif category == 'Herb' then
    result = result..'!!colspan="2"|Herb!!Herb Value'
+
result = result..'!!colspan="2"|Herb!!Herb Value'
  elseif category == 'Tree' then
+
elseif category == 'Tree' then
    result = result..'!!colspan="2"|Logs!!Log Value'
+
result = result..'!!colspan="2"|Logs!!Log Value'
  end
+
end
  result = result..'!!Seed Sources'
+
result = result..'!!Seed Sources'
 
+
  table.sort(seedList, function(a, b) return a.farmingLevel < b.farmingLevel end)
+
table.sort(seedList, function(a, b) return a.farmingLevel < b.farmingLevel end)
  
  for i, seed in pairs(seedList) do
+
for i, seed in pairs(seedList) do
    result = result..'\r\n|-'
+
result = result..'\r\n|-'
    result = result..'\r\n|'..Icons.Icon({seed.name, type='item', size='50', notext=true})..'||[['..seed.name..']]'
+
result = result..'\r\n|'..Icons.Icon({seed.name, type='item', size='50', notext=true})..'||[['..seed.name..']]'
    result = result..'||'..seed.farmingLevel..'||'..Shared.formatnum(seed.farmingXP)
+
result = result..'||'..seed.farmingLevel..'||'..Shared.formatnum(seed.farmingXP)
    result = result..'||data-sort-value="'..seed.timeToGrow..'"|'..Shared.timeString(seed.timeToGrow, true)
+
result = result..'||data-sort-value="'..seed.timeToGrow..'"|'..Shared.timeString(seed.timeToGrow, true)
    result = result..'||data-sort-value="'..seed.sellsFor..'"|'..Icons.GP(seed.sellsFor)
+
result = result..'||data-sort-value="'..seed.sellsFor..'"|'..Icons.GP(seed.sellsFor)
  
    local crop = Items.getItemByID(seed.grownItemID)
+
local crop = Items.getItemByID(seed.grownItemID)
    result = result..'||'..Icons.Icon({crop.name, type='item', size='50', notext=true})..'||[['..crop.name..']]'
+
result = result..'||'..Icons.Icon({crop.name, type='item', size='50', notext=true})..'||[['..crop.name..']]'
    if category == 'Allotment' then
+
if category == 'Allotment' then
      result = result..'||'..Icons.Icon({'Hitpoints', type='skill', notext=true})..' '..(crop.healsFor * 10)
+
result = result..'||'..Icons.Icon({'Hitpoints', type='skill', notext=true})..' '..(crop.healsFor * 10)
    end
+
end
    result = result..'||data-sort-value="'..crop.sellsFor..'"|'..Icons.GP(crop.sellsFor)
+
result = result..'||data-sort-value="'..crop.sellsFor..'"|'..Icons.GP(crop.sellsFor)
    result = result..'||'..ItemSourceTables._getItemSources(seed)
+
result = result..'||'..ItemSourceTables._getItemSources(seed)
  end
+
end
  
  result = result..'\r\n|}'
+
result = result..'\r\n|}'
  return result
+
return result
 
end
 
end
  
 
function p.getFarmingTable(frame)
 
function p.getFarmingTable(frame)
  local category = frame.args ~= nil and frame.args[1] or frame
+
local category = frame.args ~= nil and frame.args[1] or frame
  
  return p._getFarmingTable(category)
+
return p._getFarmingTable(category)
 
end
 
end
  
 
function p.getFarmingFoodTable(frame)
 
function p.getFarmingFoodTable(frame)
  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"|Crop!!'..Icons.Icon({"Farming", type="skill", notext=true})..' Level'
+
result = result..'\r\n!colspan="2"|Crop!!'..Icons.Icon({"Farming", type="skill", notext=true})..' Level'
  result = result..'!!Healing!!Value'
+
result = result..'!!Healing!!Value'
 
+
  local itemArray = Items.getItems(function(item) return item.grownItemID ~= nil end)
+
local itemArray = Items.getItems(function(item) return item.grownItemID ~= nil end)
  
  table.sort(itemArray, function(a, b) return a.farmingLevel < b.farmingLevel end)
+
table.sort(itemArray, function(a, b) return a.farmingLevel < b.farmingLevel end)
  
  for i, item in Shared.skpairs(itemArray) do
+
for i, item in Shared.skpairs(itemArray) do
    local crop = Items.getItemByID(item.grownItemID)
+
local crop = Items.getItemByID(item.grownItemID)
    if crop.healsFor ~= nil and crop.healsFor > 0 then
+
if crop.healsFor ~= nil and crop.healsFor > 0 then
      result = result..'\r\n|-'
+
result = result..'\r\n|-'
      result = result..'\r\n|'..Icons.Icon({crop.name, type='item', notext='true', size='50'})..'||[['..crop.name..']]'
+
result = result..'\r\n|'..Icons.Icon({crop.name, type='item', notext='true', size='50'})..'||[['..crop.name..']]'
      result = result..'||style="text-align:right;"|'..item.farmingLevel
+
result = result..'||style="text-align:right;"|'..item.farmingLevel
      result = result..'||style="text-align:right" data-sort-value="'..crop.healsFor..'"|'..Icons.Icon({"Hitpoints", type="skill", notext=true})..' '..(crop.healsFor * 10)
+
result = result..'||style="text-align:right" data-sort-value="'..crop.healsFor..'"|'..Icons.Icon({"Hitpoints", type="skill", notext=true})..' '..(crop.healsFor * 10)
      result = result..'||style="text-align:right" data-sort-value="'..crop.sellsFor..'"|'..Icons.GP(crop.sellsFor)
+
result = result..'||style="text-align:right" data-sort-value="'..crop.sellsFor..'"|'..Icons.GP(crop.sellsFor)
    end
+
end
  end
+
end
  
  result = result..'\r\n|}'
+
result = result..'\r\n|}'
  
  return result
+
return result
 
end
 
end
  
 
function p.getFarmingPlotTable(frame)
 
function p.getFarmingPlotTable(frame)
  local areaName = frame.args ~= nil and frame.args[1] or frame
+
local areaName = frame.args ~= nil and frame.args[1] or frame
  local patches = nil
+
local patches = nil
  for i, area in Shared.skpairs(SkillData.Farming.Patches) do
+
for i, area in Shared.skpairs(SkillData.Farming.Patches) do
    if area.areaName == areaName then
+
if area.areaName == areaName then
      patches = area.patches
+
patches = area.patches
      break
+
break
    end
+
end
  end
+
end
  if patches == nil then
+
if patches == nil then
    return "ERROR: Invalid area name.[[Category:Pages with script errors"
+
return "ERROR: Invalid area name.[[Category:Pages with script errors"
  end
+
end
  
  local result = '{|class="wikitable"'
+
local result = '{|class="wikitable"'
  result = result..'\r\n!Plot!!'..Icons.Icon({'Farming', type='skill', notext=true})..' Level!!Cost'
+
result = result..'\r\n!Plot!!'..Icons.Icon({'Farming', type='skill', notext=true})..' Level!!Cost'
  
  for i, patch in Shared.skpairs(patches) do
+
for i, patch in Shared.skpairs(patches) do
    result = result..'\r\n|-\r\n|'..i
+
result = result..'\r\n|-\r\n|'..i
    result = result..'||style="text-align:right;" data-sort-value="0"|'..patch.level
+
result = result..'||style="text-align:right;" data-sort-value="0"|'..patch.level
    if patch.cost == 0 then
+
if patch.cost == 0 then
      result = result..'||Free'
+
result = result..'||Free'
    else
+
else
      result = result..'||style="text-align:right;" data-sort-value="'..patch.cost..'"|'..Icons.GP(patch.cost)
+
result = result..'||style="text-align:right;" data-sort-value="'..patch.cost..'"|'..Icons.GP(patch.cost)
    end
+
end
  end
+
end
  
  result = result..'\r\n|}'
+
result = result..'\r\n|}'
  return result
+
return result
 
end
 
end
  
 
function p.getSmithingTable(frame)
 
function p.getSmithingTable(frame)
  local tableType = frame.args ~= nil and frame.args[1] or frame
+
local tableType = frame.args ~= nil and frame.args[1] or frame
  local bar = nil
+
local bar = nil
  if tableType ~= 'Smelting' then
+
if tableType ~= 'Smelting' then
    bar = Items.getItem(tableType)
+
bar = Items.getItem(tableType)
    if bar == nil then
+
if bar == nil then
      return 'ERROR: Could not find an item named '..tableType..' to build a smithing table with'
+
return 'ERROR: Could not find an item named '..tableType..' to build a smithing table with'
    elseif bar.type ~= 'Bar' then
+
elseif bar.type ~= 'Bar' then
      return 'ERROR: '..tableType.." is not a bar and thus can't be used for smithing"
+
return 'ERROR: '..tableType.." is not a bar and thus can't be used for smithing"
    end
+
end
  end
+
end
  
  local smithList = {}
+
local smithList = {}
  for i, item in pairs(ItemData.Items) do
+
for i, item in pairs(ItemData.Items) do
    if item.smithingLevel ~= nil then
+
if item.smithingLevel ~= nil then
      if tableType == 'Smelting' then
+
if tableType == 'Smelting' then
        if item.type == 'Bar' then
+
if item.type == 'Bar' then
          table.insert(smithList, item)
+
table.insert(smithList, item)
        end
+
end
      else
+
else
        for j, req in pairs(item.smithReq) do
+
for j, req in pairs(item.smithReq) do
          if req.id == bar.id then
+
if req.id == bar.id then
            table.insert(smithList, item)
+
table.insert(smithList, item)
          end
+
end
        end
+
end
      end
+
end
    end
+
end
  end
+
end
  
  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!Item!!Name!!'..Icons.Icon({'Smithing', type='skill', notext=true})..' Level!!XP!!Value!!Ingredients'
+
result = result..'\r\n!Item!!Name!!'..Icons.Icon({'Smithing', type='skill', notext=true})..' Level!!XP!!Value!!Ingredients'
  --Adding value/bar for things other than smelting
+
--Adding value/bar for things other than smelting
  if bar ~= nil then result = result..'!!Value/Bar' end
+
if bar ~= nil then result = result..'!!Value/Bar' end
  
  table.sort(smithList, function(a, b)
+
table.sort(smithList, function(a, b)
                          if a.smithingLevel ~= b.smithingLevel then
+
if a.smithingLevel ~= b.smithingLevel then
                            return a.smithingLevel < b.smithingLevel
+
return a.smithingLevel < b.smithingLevel
                          else
+
else
                            return a.name < b.name
+
return a.name < b.name
                          end end)
+
end end)
  for i, item in Shared.skpairs(smithList) do
+
for i, item in Shared.skpairs(smithList) do
    result = result..'\r\n|-'
+
result = result..'\r\n|-'
    result = result..'\r\n|'..Icons.Icon({item.name, type='item', size='50', notext=true})..'||'
+
result = result..'\r\n|'..Icons.Icon({item.name, type='item', size='50', notext=true})..'||'
    local qty = item.smithingQty ~= nil and item.smithingQty or 1
+
local qty = item.smithingQty ~= nil and item.smithingQty or 1
    if qty > 1 then
+
if qty > 1 then
      result = result..item.smithingQty..'x '
+
result = result..item.smithingQty..'x '
    end
+
end
    result = result..'[['..item.name..']]'
+
result = result..'[['..item.name..']]'
    result = result..'||data-sort-value="'..item.smithingLevel..'"|'..Icons._SkillReq('Smithing', item.smithingLevel)
+
result = result..'||data-sort-value="'..item.smithingLevel..'"|'..Icons._SkillReq('Smithing', item.smithingLevel)
    result = result..'||'..item.smithingXP
+
result = result..'||'..item.smithingXP
    local totalValue = item.sellsFor * qty
+
local totalValue = item.sellsFor * qty
    result = result..'||data-sort-value="'..totalValue..'"|'..Icons.GP(item.sellsFor)
+
result = result..'||data-sort-value="'..totalValue..'"|'..Icons.GP(item.sellsFor)
    if qty > 1 then
+
if qty > 1 then
      result = result..' (x'..qty..')'
+
result = result..' (x'..qty..')'
    end
+
end
    result = result..'||'
+
result = result..'||'
    local barQty = 0
+
local barQty = 0
    for i, mat in Shared.skpairs(item.smithReq) do
+
for i, mat in Shared.skpairs(item.smithReq) do
      matItem = Items.getItemByID(mat.id)
+
matItem = Items.getItemByID(mat.id)
      if i > 1 then result = result..', ' end
+
if i > 1 then result = result..', ' end
      result = result..Icons.Icon({matItem.name, type='item', qty=mat.qty, notext=true})
+
result = result..Icons.Icon({matItem.name, type='item', qty=mat.qty, notext=true})
      if bar ~= nil and mat.id == bar.id then
+
if bar ~= nil and mat.id == bar.id then
        barQty = mat.qty
+
barQty = mat.qty
      end
+
end
    end
+
end
    --Add the data for the value per bar
+
--Add the data for the value per bar
    if bar ~= nil then
+
if bar ~= nil then
      if barQty == 0 then
+
if barQty == 0 then
        result = result..'||data-sort-value="0"|N/A'
+
result = result..'||data-sort-value="0"|N/A'
      else
+
else
        local barVal = totalValue / barQty
+
local barVal = totalValue / barQty
        result = result..'||data-sort-value="'..barVal..'"|'..Icons.GP(Shared.round(barVal, 1, 1))
+
result = result..'||data-sort-value="'..barVal..'"|'..Icons.GP(Shared.round(barVal, 1, 1))
      end
+
end
    end
+
end
  end
+
end
  
  result = result..'\r\n|}'
+
result = result..'\r\n|}'
  return result
+
return result
 
end
 
end
  
 
function p.getFiremakingTable(frame)
 
function p.getFiremakingTable(frame)
  local resultPart = {}
+
local resultPart = {}
  table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
+
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
  table.insert(resultPart, '\r\n|-class="headerRow-0"')
+
table.insert(resultPart, '\r\n|-class="headerRow-0"')
  table.insert(resultPart, '\r\n!colspan="2" rowspan="2"|Logs!!rowspan="2"|'..Icons.Icon({'Firemaking', type='skill', notext=true})..' Level')
+
table.insert(resultPart, '\r\n!colspan="2" rowspan="2"|Logs!!rowspan="2"|'..Icons.Icon({'Firemaking', type='skill', notext=true})..' Level')
  table.insert(resultPart, '!!rowspan="2"|Burn Time!!colspan="2"|Without Bonfire!!colspan="2"|With Bonfire!!rowspan="2"|Bonfire Bonus!!rowspan="2"|Bonfire Time')
+
table.insert(resultPart, '!!rowspan="2"|Burn Time!!colspan="2"|Without Bonfire!!colspan="2"|With Bonfire!!rowspan="2"|Bonfire Bonus!!rowspan="2"|Bonfire Time')
  table.insert(resultPart, '\r\n|-class="headerRow-1"')
+
table.insert(resultPart, '\r\n|-class="headerRow-1"')
  table.insert(resultPart, '\r\n!XP!!XP/s!!XP!!XP/s')
+
table.insert(resultPart, '\r\n!XP!!XP/s!!XP!!XP/s')
  
  for i, logData in Shared.skpairs(SkillData.Firemaking) do
+
for i, logData in Shared.skpairs(SkillData.Firemaking) do
  local logs = Items.getItemByID(logData.logID)
+
local logs = Items.getItemByID(logData.logID)
    local name = logs.name
+
local name = logs.name
    local burnTime = logData.baseInterval / 1000
+
local burnTime = logData.baseInterval / 1000
    local bonfireTime = logData.baseBonfireInterval / 1000
+
local bonfireTime = logData.baseBonfireInterval / 1000
    local XPS = logData.baseXP / burnTime
+
local XPS = logData.baseXP / burnTime
    local XP_BF = logData.baseXP * (1 + logData.bonfireXPBonus / 100)
+
local XP_BF = logData.baseXP * (1 + logData.bonfireXPBonus / 100)
    local XPS_BF = XP_BF / burnTime
+
local XPS_BF = XP_BF / burnTime
  
    table.insert(resultPart, '\r\n|-')
+
table.insert(resultPart, '\r\n|-')
    table.insert(resultPart, '\r\n|data-sort-value="'..name..'"|'..Icons.Icon({name, type='item', size='50', notext=true}))
+
table.insert(resultPart, '\r\n|data-sort-value="'..name..'"|'..Icons.Icon({name, type='item', size='50', notext=true}))
    table.insert(resultPart, '||[['..name..']]')
+
table.insert(resultPart, '||[['..name..']]')
    table.insert(resultPart, '||style ="text-align: right;"|'..logData.levelRequired)
+
table.insert(resultPart, '||style ="text-align: right;"|'..logData.levelRequired)
    table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..burnTime..'"|'..Shared.timeString(burnTime, true))
+
table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..burnTime..'"|'..Shared.timeString(burnTime, true))
    table.insert(resultPart, '||style ="text-align: right;"|'..logData.baseXP)
+
table.insert(resultPart, '||style ="text-align: right;"|'..logData.baseXP)
    table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..XPS..'"|'..Shared.round(XPS, 2, 2))
+
table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..XPS..'"|'..Shared.round(XPS, 2, 2))
    table.insert(resultPart, '||style ="text-align: right;"|'..Shared.round(XP_BF, 2, 0))
+
table.insert(resultPart, '||style ="text-align: right;"|'..Shared.round(XP_BF, 2, 0))
    table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..XPS_BF..'"|'..Shared.round(XPS_BF, 2, 2))
+
table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..XPS_BF..'"|'..Shared.round(XPS_BF, 2, 2))
    table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..logData.bonfireXPBonus..'"|'..logData.bonfireXPBonus..'%')
+
table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..logData.bonfireXPBonus..'"|'..logData.bonfireXPBonus..'%')
    table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..bonfireTime..'"|'..Shared.timeString(bonfireTime, true))
+
table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..bonfireTime..'"|'..Shared.timeString(bonfireTime, true))
  end
+
end
  
  table.insert(resultPart, '\r\n|}')
+
table.insert(resultPart, '\r\n|}')
  return table.concat(resultPart)
+
return table.concat(resultPart)
 
end
 
end
  
 
function p.getMasteryTokenTable()
 
function p.getMasteryTokenTable()
  local baseTokenChance = 18500
+
local baseTokenChance = 18500
  local masterySkills = {}
+
local masterySkills = {}
 
+
  -- Find all mastery tokens
+
-- Find all mastery tokens
  local masteryTokens = Items.getItems(function(item) return item.isToken ~= nil and item.skill ~= nil and item.isToken end)
+
local masteryTokens = Items.getItems(function(item) return item.isToken ~= nil and item.skill ~= nil and item.isToken end)
  for i, item in pairs(masteryTokens) do
+
for i, item in pairs(masteryTokens) do
    local milestones = SkillData.Milestones[item.skill + 1]
+
local milestones = SkillData.Milestones[item.skill + 1]
    if milestones ~= nil then
+
if milestones ~= nil then
      table.insert(masterySkills, {tokenRef = i, skillID = item.skill, milestoneCount = milestones})
+
table.insert(masterySkills, {tokenRef = i, skillID = item.skill, milestoneCount = milestones})
    end
+
end
  end
+
end
  table.sort(masterySkills, function(a, b)
+
table.sort(masterySkills, function(a, b)
                              if a['milestoneCount'] == b['milestoneCount'] then
+
if a['milestoneCount'] == b['milestoneCount'] then
                                return a['skillID'] < b['skillID']
+
return a['skillID'] < b['skillID']
                              else
+
else
                                return a['milestoneCount'] > b['milestoneCount']
+
return a['milestoneCount'] > b['milestoneCount']
                              end
+
end
                            end)
+
end)
 
+
  -- Generate output table
+
-- Generate output table
  local resultPart = {}
+
local resultPart = {}
  local CCI = Items.getItem('Clue Chasers Insignia')
+
local CCI = Items.getItem('Clue Chasers Insignia')
  local CCIIcon = Icons.Icon({'Clue Chasers Insignia', type='item', notext=true})
+
local CCIIcon = Icons.Icon({'Clue Chasers Insignia', type='item', notext=true})
  if CCI == nil then return '' end
+
if CCI == nil then return '' end
  
  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, '\r\n!rowspan="2"|Token!!rowspan="2"|Skill!!colspan="2"|Approximate Mastery Token Chance')
  table.insert(resultPart, '\r\n|-\r\n!Without ' .. CCIIcon .. '!!With ' .. CCIIcon)
+
table.insert(resultPart, '\r\n|-\r\n!Without ' .. CCIIcon .. '!!With ' .. CCIIcon)
  
  for i, m in ipairs(masterySkills) do
+
for i, m in ipairs(masterySkills) do
    local token = masteryTokens[m.tokenRef]
+
local token = masteryTokens[m.tokenRef]
    local denom = math.floor(baseTokenChance / m['milestoneCount'])
+
local denom = math.floor(baseTokenChance / m['milestoneCount'])
    local denomCCI = math.floor(baseTokenChance / m['milestoneCount'] * (1 - CCI.increasedItemChance / 100))
+
local denomCCI = math.floor(baseTokenChance / m['milestoneCount'] * (1 - CCI.increasedItemChance / 100))
  
    table.insert(resultPart, '\r\n|-')
+
table.insert(resultPart, '\r\n|-')
    table.insert(resultPart, '\r\n|style="text-align:center"|' .. Icons.Icon({token.name, type='item', size=50, notext=true}))
+
table.insert(resultPart, '\r\n|style="text-align:center"|' .. Icons.Icon({token.name, type='item', size=50, notext=true}))
    table.insert(resultPart, '\r\n|' .. Icons.Icon({Constants.getSkillName(m['skillID']), type='skill'}))
+
table.insert(resultPart, '\r\n|' .. Icons.Icon({Constants.getSkillName(m['skillID']), type='skill'}))
    table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denom .. '"|1/' .. Shared.formatnum(denom))
+
table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denom .. '"|1/' .. Shared.formatnum(denom))
    table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denomCCI .. '"|1/' .. Shared.formatnum(denomCCI))
+
table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denomCCI .. '"|1/' .. Shared.formatnum(denomCCI))
  end
+
end
  table.insert(resultPart, '\r\n|}')
+
table.insert(resultPart, '\r\n|}')
 
+
  return table.concat(resultPart)
+
return table.concat(resultPart)
 
end
 
end
  
 
function p.getSkillUnlockCostTable()
 
function p.getSkillUnlockCostTable()
  local returnPart = {}
+
local returnPart = {}
  table.insert(returnPart, '{| class="wikitable stickyHeader"\r\n|- class="headerRow-0"\r\n!Unlock!!Cost!!Cumulative Cost')
+
table.insert(returnPart, '{| class="wikitable stickyHeader"\r\n|- class="headerRow-0"\r\n!Unlock!!Cost!!Cumulative Cost')
  
  local accCost = 0
+
local accCost = 0
  for i, cost in ipairs(SkillData.SkillUnlockCosts) do
+
for i, cost in ipairs(SkillData.SkillUnlockCosts) do
    accCost = accCost + cost
+
accCost = accCost + cost
    table.insert(returnPart, '|-')
+
table.insert(returnPart, '|-')
    table.insert(returnPart, '|' .. i .. '||' .. Icons.GP(cost) .. '||' .. Icons.GP(accCost))
+
table.insert(returnPart, '|' .. i .. '||' .. Icons.GP(cost) .. '||' .. Icons.GP(accCost))
  end
+
end
  table.insert(returnPart, '|}')
+
table.insert(returnPart, '|}')
  
  return table.concat(returnPart, '\r\n')
+
return table.concat(returnPart, '\r\n')
 
end
 
end
  
 
return p
 
return p

Revision as of 19:16, 8 December 2021

Data pulled from Module:Skills/data


--Some skills have their own modules:
--Module:Magic for Magic
--Module:Prayer for Prayer
--Module:Skills/Agility for Agility
--Module:Skills/Summoning for Summoning
--Module:Skills/Gathering for Mining, Fishing, Woodcutting
--Module:Skills/Artisan for Smithing, Cooking, Herblore, etc.

--Also be aware of:
--Module:Navboxes for navigation boxes appearing near the bottom of pages

local p = {}

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

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

local MasteryCheckpoints = {.1, .25, .5, .95}

function p.getMasteryUnlockTable(frame)
	local skillName = frame.args ~= nil and frame.args[1] or frame
	local skillID = Constants.getSkillID(skillName)
	if skillID == nil then
		return "ERROR: Failed to find a skill ID for "..skillName
	end

	local unlockTable = SkillData.MasteryUnlocks[skillID]
	if unlockTable == nil then
		return 'ERROR: Failed to find Mastery Unlock data for '..skillName
	end

	local result = '{|class="wikitable"\r\n!Level!!Unlock'
	for i, unlock in Shared.skpairs(unlockTable) do
		result = result..'\r\n|-'
		result = result..'\r\n|'..unlock.level..'||'..unlock.unlock
	end
	result = result..'\r\n|}'
	return result
end

function p.getMasteryCheckpointTable(frame)
	local skillName = frame.args ~= nil and frame.args[1] or frame
	local skillID = Constants.getSkillID(skillName)
	if skillID == nil then
		return "ERROR: Failed to find a skill ID for "..skillName
	end

	if SkillData.MasteryCheckpoints[skillID] == nil then
		return 'ERROR: Failed to find Mastery Unlock data for '..skillName
	end

	local bonuses = SkillData.MasteryCheckpoints[skillID].bonuses
	local totalPoolXP = SkillData.MasteryPoolXP[skillID + 1]

	local result = '{|class="wikitable"\r\n!Pool %!!style="width:100px"|Pool XP!!Bonus'
	for i, bonus in Shared.skpairs(bonuses) do
		result = result..'\r\n|-'
		result = result..'\r\n|'..(MasteryCheckpoints[i] * 100)..'%||'
		result = result..Shared.formatnum(totalPoolXP * MasteryCheckpoints[i])..' xp||'..bonus
	end
	result = result..'\r\n|-\r\n!colspan="2"|Total Mastery Pool XP'
	result = result..'\r\n|'..Shared.formatnum(totalPoolXP)
	result = result..'\r\n|}'
	return result
end

function p._getFarmingTable(category)
	local seedList = {}
	if category == 'Allotment' or category == 'Herb' or category == 'Tree' then
		seedList = Items.getItems(function(item) return item.tier == category end)
	else
		return 'ERROR: Invalid farming category. Please choose Allotment, Herb, or Tree'
	end

	local result = '{|class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!colspan=2|Seeds!!'..Icons.Icon({'Farming', type='skill', notext=true})..' Level'
	result = result..'!!XP!!Growth Time!!Seed Value'
	if category == 'Allotment' then
		result = result..'!!colspan="2"|Crop!!Crop Healing!!Crop Value'
	elseif category == 'Herb' then
		result = result..'!!colspan="2"|Herb!!Herb Value'
	elseif category == 'Tree' then
		result = result..'!!colspan="2"|Logs!!Log Value'
	end
	result = result..'!!Seed Sources'
	
	table.sort(seedList, function(a, b) return a.farmingLevel < b.farmingLevel end)

	for i, seed in pairs(seedList) do
		result = result..'\r\n|-'
		result = result..'\r\n|'..Icons.Icon({seed.name, type='item', size='50', notext=true})..'||[['..seed.name..']]'
		result = result..'||'..seed.farmingLevel..'||'..Shared.formatnum(seed.farmingXP)
		result = result..'||data-sort-value="'..seed.timeToGrow..'"|'..Shared.timeString(seed.timeToGrow, true)
		result = result..'||data-sort-value="'..seed.sellsFor..'"|'..Icons.GP(seed.sellsFor)

		local crop = Items.getItemByID(seed.grownItemID)
		result = result..'||'..Icons.Icon({crop.name, type='item', size='50', notext=true})..'||[['..crop.name..']]'
		if category == 'Allotment' then
			result = result..'||'..Icons.Icon({'Hitpoints', type='skill', notext=true})..' '..(crop.healsFor * 10)
		end
		result = result..'||data-sort-value="'..crop.sellsFor..'"|'..Icons.GP(crop.sellsFor)
		result = result..'||'..ItemSourceTables._getItemSources(seed)
	end

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

function p.getFarmingTable(frame)
	local category = frame.args ~= nil and frame.args[1] or frame

	return p._getFarmingTable(category)
end

function p.getFarmingFoodTable(frame)
	local result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!colspan="2"|Crop!!'..Icons.Icon({"Farming", type="skill", notext=true})..' Level'
	result = result..'!!Healing!!Value'
	
	local itemArray = Items.getItems(function(item) return item.grownItemID ~= nil end)

	table.sort(itemArray, function(a, b) return a.farmingLevel < b.farmingLevel end)

	for i, item in Shared.skpairs(itemArray) do
		local crop = Items.getItemByID(item.grownItemID)
		if crop.healsFor ~= nil and crop.healsFor > 0 then
			result = result..'\r\n|-'
			result = result..'\r\n|'..Icons.Icon({crop.name, type='item', notext='true', size='50'})..'||[['..crop.name..']]'
			result = result..'||style="text-align:right;"|'..item.farmingLevel
			result = result..'||style="text-align:right" data-sort-value="'..crop.healsFor..'"|'..Icons.Icon({"Hitpoints", type="skill", notext=true})..' '..(crop.healsFor * 10)
			result = result..'||style="text-align:right" data-sort-value="'..crop.sellsFor..'"|'..Icons.GP(crop.sellsFor)
		end
	end

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

	return result
end

function p.getFarmingPlotTable(frame)
	local areaName = frame.args ~= nil and frame.args[1] or frame
	local patches = nil
	for i, area in Shared.skpairs(SkillData.Farming.Patches) do
		if area.areaName == areaName then
			patches = area.patches
			break
		end
	end
	if patches == nil then
		return "ERROR: Invalid area name.[[Category:Pages with script errors"
	end

	local result = '{|class="wikitable"'
	result = result..'\r\n!Plot!!'..Icons.Icon({'Farming', type='skill', notext=true})..' Level!!Cost'

	for i, patch in Shared.skpairs(patches) do
		result = result..'\r\n|-\r\n|'..i
		result = result..'||style="text-align:right;" data-sort-value="0"|'..patch.level
		if patch.cost == 0 then
			result = result..'||Free'
		else
			result = result..'||style="text-align:right;" data-sort-value="'..patch.cost..'"|'..Icons.GP(patch.cost)
		end
	end

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

function p.getSmithingTable(frame)
	local tableType = frame.args ~= nil and frame.args[1] or frame
	local bar = nil
	if tableType ~= 'Smelting' then
		bar = Items.getItem(tableType)
		if bar == nil then
			return 'ERROR: Could not find an item named '..tableType..' to build a smithing table with'
		elseif bar.type ~= 'Bar' then
			return 'ERROR: '..tableType.." is not a bar and thus can't be used for smithing"
		end
	end

	local smithList = {}
	for i, item in pairs(ItemData.Items) do
		if item.smithingLevel ~= nil then
			if tableType == 'Smelting' then
				if item.type == 'Bar' then
					table.insert(smithList, item)
				end
			else
				for j, req in pairs(item.smithReq) do
					if req.id == bar.id then
						table.insert(smithList, item)
					end
				end
			end
		end
	end

	local result = '{|class="wikitable sortable stickyHeader"'
	result = result..'\r\n|-class="headerRow-0"'
	result = result..'\r\n!Item!!Name!!'..Icons.Icon({'Smithing', type='skill', notext=true})..' Level!!XP!!Value!!Ingredients'
	--Adding value/bar for things other than smelting
	if bar ~= nil then result = result..'!!Value/Bar' end

	table.sort(smithList, function(a, b)
													if a.smithingLevel ~= b.smithingLevel then
														return a.smithingLevel < b.smithingLevel
													else
														return a.name < b.name
													end end)
	for i, item in Shared.skpairs(smithList) do
		result = result..'\r\n|-'
		result = result..'\r\n|'..Icons.Icon({item.name, type='item', size='50', notext=true})..'||'
		local qty = item.smithingQty ~= nil and item.smithingQty or 1
		if qty > 1 then
			result = result..item.smithingQty..'x '
		end
		result = result..'[['..item.name..']]'
		result = result..'||data-sort-value="'..item.smithingLevel..'"|'..Icons._SkillReq('Smithing', item.smithingLevel)
		result = result..'||'..item.smithingXP
		local totalValue = item.sellsFor * qty
		result = result..'||data-sort-value="'..totalValue..'"|'..Icons.GP(item.sellsFor)
		if qty > 1 then
			result = result..' (x'..qty..')'
		end
		result = result..'||'
		local barQty = 0
		for i, mat in Shared.skpairs(item.smithReq) do
			matItem = Items.getItemByID(mat.id)
			if i > 1 then result = result..', ' end
			result = result..Icons.Icon({matItem.name, type='item', qty=mat.qty, notext=true})
			if bar ~= nil and mat.id == bar.id then
				barQty = mat.qty
			end
		end
		--Add the data for the value per bar
		if bar ~= nil then
			if barQty == 0 then
				result = result..'||data-sort-value="0"|N/A'
			else
				local barVal = totalValue / barQty
				result = result..'||data-sort-value="'..barVal..'"|'..Icons.GP(Shared.round(barVal, 1, 1))
			end
		end
	end

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

function p.getFiremakingTable(frame)
	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
	table.insert(resultPart, '\r\n|-class="headerRow-0"')
	table.insert(resultPart, '\r\n!colspan="2" rowspan="2"|Logs!!rowspan="2"|'..Icons.Icon({'Firemaking', type='skill', notext=true})..' Level')
	table.insert(resultPart, '!!rowspan="2"|Burn Time!!colspan="2"|Without Bonfire!!colspan="2"|With Bonfire!!rowspan="2"|Bonfire Bonus!!rowspan="2"|Bonfire Time')
	table.insert(resultPart, '\r\n|-class="headerRow-1"')
	table.insert(resultPart, '\r\n!XP!!XP/s!!XP!!XP/s')

	for i, logData in Shared.skpairs(SkillData.Firemaking) do
		local logs = Items.getItemByID(logData.logID)
		local name = logs.name
		local burnTime = logData.baseInterval / 1000
		local bonfireTime = logData.baseBonfireInterval / 1000
		local XPS = logData.baseXP / burnTime
		local XP_BF = logData.baseXP * (1 + logData.bonfireXPBonus / 100)
		local XPS_BF = XP_BF / burnTime

		table.insert(resultPart, '\r\n|-')
		table.insert(resultPart, '\r\n|data-sort-value="'..name..'"|'..Icons.Icon({name, type='item', size='50', notext=true}))
		table.insert(resultPart, '||[['..name..']]')
		table.insert(resultPart, '||style ="text-align: right;"|'..logData.levelRequired)
		table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..burnTime..'"|'..Shared.timeString(burnTime, true))
		table.insert(resultPart, '||style ="text-align: right;"|'..logData.baseXP)
		table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..XPS..'"|'..Shared.round(XPS, 2, 2))
		table.insert(resultPart, '||style ="text-align: right;"|'..Shared.round(XP_BF, 2, 0))
		table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..XPS_BF..'"|'..Shared.round(XPS_BF, 2, 2))
		table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..logData.bonfireXPBonus..'"|'..logData.bonfireXPBonus..'%')
		table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..bonfireTime..'"|'..Shared.timeString(bonfireTime, true))
	end

	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

function p.getMasteryTokenTable()
	local baseTokenChance = 18500
	local masterySkills = {}
	
	-- Find all mastery tokens
	local masteryTokens = Items.getItems(function(item) return item.isToken ~= nil and item.skill ~= nil and item.isToken end)
	for i, item in pairs(masteryTokens) do
		local milestones = SkillData.Milestones[item.skill + 1]
		if milestones ~= nil then
			table.insert(masterySkills, {tokenRef = i, skillID = item.skill, milestoneCount = milestones})
		end
	end
	table.sort(masterySkills, function(a, b)
									if a['milestoneCount'] == b['milestoneCount'] then
										return a['skillID'] < b['skillID']
									else
										return a['milestoneCount'] > b['milestoneCount']
									end
								end)
	
	-- Generate output table
	local resultPart = {}
	local CCI = Items.getItem('Clue Chasers Insignia')
	local CCIIcon = Icons.Icon({'Clue Chasers Insignia', type='item', notext=true})
	if CCI == nil then return '' end

	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, '\r\n|-\r\n!Without ' .. CCIIcon .. '!!With ' .. CCIIcon)

	for i, m in ipairs(masterySkills) do
		local token = masteryTokens[m.tokenRef]
		local denom = math.floor(baseTokenChance / m['milestoneCount'])
		local denomCCI = math.floor(baseTokenChance / m['milestoneCount'] * (1 - CCI.increasedItemChance / 100))

		table.insert(resultPart, '\r\n|-')
		table.insert(resultPart, '\r\n|style="text-align:center"|' .. Icons.Icon({token.name, type='item', size=50, notext=true}))
		table.insert(resultPart, '\r\n|' .. Icons.Icon({Constants.getSkillName(m['skillID']), type='skill'}))
		table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denom .. '"|1/' .. Shared.formatnum(denom))
		table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. denomCCI .. '"|1/' .. Shared.formatnum(denomCCI))
	end
	table.insert(resultPart, '\r\n|}')
	
	return table.concat(resultPart)
end

function p.getSkillUnlockCostTable()
	local returnPart = {}
	table.insert(returnPart, '{| class="wikitable stickyHeader"\r\n|- class="headerRow-0"\r\n!Unlock!!Cost!!Cumulative Cost')

	local accCost = 0
	for i, cost in ipairs(SkillData.SkillUnlockCosts) do
		accCost = accCost + cost
		table.insert(returnPart, '|-')
		table.insert(returnPart, '|' .. i .. '||' .. Icons.GP(cost) .. '||' .. Icons.GP(accCost))
	end
	table.insert(returnPart, '|}')

	return table.concat(returnPart, '\r\n')
end

return p