17,101
edits
(_buildAstrologyConstellationTable: Remove time column, which has been relocated to Astrology/Training) |
(Update for v1.1) |
||
Line 1: | Line 1: | ||
--Splitting some functions into here to avoid bloating a single file | --Splitting some functions into here to avoid bloating a single file | ||
local p = {} | local p = {} | ||
local Constants = require('Module:Constants') | local Constants = require('Module:Constants') | ||
local Shared = require('Module:Shared') | local Shared = require('Module:Shared') | ||
local GameData = require('Module:GameData') | |||
local SkillData = GameData.skillData | |||
local Items = require('Module:Items') | local Items = require('Module:Items') | ||
local Icons = require('Module:Icons') | local Icons = require('Module:Icons') | ||
local Shop = require('Module:Shop') | |||
local Skills = require('Module:Skills') | local Skills = require('Module:Skills') | ||
local ItemSourceTables = require('Module:Items/SourceTables') | local ItemSourceTables = require('Module:Items/SourceTables') | ||
-- TODO Move tool tables to Module:Shop | |||
function p.getAxeTable(frame) | function p.getAxeTable(frame) | ||
local toolArray = | local toolArray = Shop.getPurchases( | ||
function(purch) | |||
return purch.category == 'melvorD:SkillUpgrades' and string.find(purch.id, '_Axe$') ~= nil | |||
end) | |||
end | |||
local result = '{| class="wikitable"' | local result = '{| class="wikitable"' | ||
Line 28: | Line 27: | ||
local total = 0 | local total = 0 | ||
for i, tool in | for i, tool in ipairs(toolArray) do | ||
result = result..'\r\n|-' | result = result..'\r\n|-' | ||
result = result..'\r\n|style="min-width:25px" data-sort-value="'..tool. | result = result..'\r\n|style="min-width:25px" data-sort-value="'..tool.customName..'"|'..Icons.Icon({tool.customName, type='upgrade', size='50', notext=true}) | ||
result = result..'||'..tool. | result = result..'||'..tool.customName | ||
local level = 1 | local level = 1 | ||
if tool. | if tool.purchaseRequirements ~= nil and not Shared.tableIsEmpty(tool.purchaseRequirements) then | ||
--Gonna be lazy and assume there's only the one skill level and it's the one we care about | --Gonna be lazy and assume there's only the one skill level and it's the one we care about | ||
level = tool.unlockRequirements.skillLevel[1] | level = tool.unlockRequirements.skillLevel[1].level | ||
end | end | ||
result = result..'||style="text-align:right"|'..level | result = result..'||style="text-align:right"|'..level | ||
result = result..'||style="text-align:right" data-sort-value="'..tool.cost.gp..'"|'..Icons.GP(tool.cost.gp) | result = result..'||style="text-align:right" data-sort-value="'..tool.cost.gp..'"|'..Icons.GP(tool.cost.gp) | ||
local cutTime = tool.contains.modifiers.decreasedSkillIntervalPercent[1] | -- TODO TotH tools have other modifiers which should be included | ||
local cutTime = 0 | |||
if tool.contains.modifiers.decreasedSkillIntervalPercent ~= nil then | |||
cutTime = tool.contains.modifiers.decreasedSkillIntervalPercent[1].value | |||
end | |||
total = total + cutTime | total = total + cutTime | ||
result = result..'||style="text-align:right"|-'..cutTime..'%' | result = result..'||style="text-align:right"|-'..cutTime..'%' | ||
Line 51: | Line 54: | ||
function p.getPickaxeTable(frame) | function p.getPickaxeTable(frame) | ||
local toolArray = | local toolArray = Shop.getPurchases( | ||
function(purch) | |||
return purch.category == 'melvorD:SkillUpgrades' and string.find(purch.id, '_Pickaxe$') ~= nil | |||
end) | |||
end | |||
local result = '{| class="wikitable"' | local result = '{| class="wikitable"' | ||
Line 67: | Line 68: | ||
local total2 = 0 | local total2 = 0 | ||
for i, tool in | for i, tool in ipairs(toolArray) do | ||
result = result..'\r\n|-' | result = result..'\r\n|-' | ||
result = result..'\r\n|style="min-width:25px" data-sort-value="'..tool. | result = result..'\r\n|style="min-width:25px" data-sort-value="'..tool.customName..'"|'..Icons.Icon({tool.customName, type='upgrade', size='50', notext=true}) | ||
result = result..'||'..tool. | result = result..'||'..tool.customName | ||
local level = 1 | local level = 1 | ||
if tool. | if tool.purchaseRequirements ~= nil and not Shared.tableIsEmpty(tool.purchaseRequirements) then | ||
--Gonna be lazy and assume there's only the one skill level and it's the one we care about | --Gonna be lazy and assume there's only the one skill level and it's the one we care about | ||
level = tool.unlockRequirements.skillLevel[1] | level = tool.unlockRequirements.skillLevel[1].level | ||
end | end | ||
result = result..'||style="text-align:right"|'..level | result = result..'||style="text-align:right"|'..level | ||
result = result..'||style="text-align:right" data-sort-value="'..tool.cost.gp..'"|'..Icons.GP(tool.cost.gp) | result = result..'||style="text-align:right" data-sort-value="'..tool.cost.gp..'"|'..Icons.GP(tool.cost.gp) | ||
local cutTime = tool.contains.modifiers.decreasedSkillIntervalPercent[1] | -- TODO TotH tools have other modifiers which should be included | ||
local cutTime = 0 | |||
if tool.contains.modifiers.decreasedSkillIntervalPercent ~= nil then | |||
cutTime = tool.contains.modifiers.decreasedSkillIntervalPercent[1].value | |||
end | |||
total = total + cutTime | total = total + cutTime | ||
Line 85: | Line 90: | ||
result = result..'||style="text-align:right"|-'..total..'%' | result = result..'||style="text-align:right"|-'..total..'%' | ||
local OreDouble = tool.contains.modifiers.increasedChanceToDoubleOres | local OreDouble = (tool.contains.modifiers.increasedChanceToDoubleOres or 0) | ||
total2 = total2 + OreDouble | total2 = total2 + OreDouble | ||
Line 97: | Line 102: | ||
function p.getRodTable(frame) | function p.getRodTable(frame) | ||
local toolArray = | local toolArray = Shop.getPurchases( | ||
function(purch) | |||
return purch.category == 'melvorD:SkillUpgrades' and string.find(purch.id, '_Fishing_Rod$') ~= nil | |||
end) | |||
end | |||
local result = '{| class="wikitable"' | local result = '{| class="wikitable"' | ||
Line 114: | Line 117: | ||
for i, tool in Shared.skpairs(toolArray) do | for i, tool in Shared.skpairs(toolArray) do | ||
result = result..'\r\n|-' | result = result..'\r\n|-' | ||
result = result..'\r\n|style="min-width:25px" data-sort-value="'..tool. | result = result..'\r\n|style="min-width:25px" data-sort-value="'..tool.customName..'"|'..Icons.Icon({tool.customName, type='upgrade', size='50', notext=true}) | ||
result = result..'||'..tool. | result = result..'||'..tool.customName | ||
local level = 1 | local level = 1 | ||
if tool. | if tool.purchaseRequirements ~= nil and not Shared.tableIsEmpty(tool.purchaseRequirements) then | ||
--Gonna be lazy and assume there's only the one skill level and it's the one we care about | --Gonna be lazy and assume there's only the one skill level and it's the one we care about | ||
level = tool.unlockRequirements.skillLevel[1] | level = tool.unlockRequirements.skillLevel[1].level | ||
end | end | ||
result = result..'||style="text-align:right"|'..level | result = result..'||style="text-align:right"|'..level | ||
result = result..'||style="text-align:right" data-sort-value="'..tool.cost.gp..'"|'..Icons.GP(tool.cost.gp) | result = result..'||style="text-align:right" data-sort-value="'..tool.cost.gp..'"|'..Icons.GP(tool.cost.gp) | ||
local cutTime = tool.contains.modifiers.decreasedSkillIntervalPercent[1] | -- TODO TotH tools have other modifiers which should be included | ||
local cutTime = 0 | |||
if tool.contains.modifiers.decreasedSkillIntervalPercent ~= nil then | |||
cutTime = tool.contains.modifiers.decreasedSkillIntervalPercent[1].value | |||
end | |||
total = total + cutTime | total = total + cutTime | ||
result = result..'||style="text-align:right"|-'..cutTime..'%' | result = result..'||style="text-align:right"|-'..cutTime..'%' | ||
Line 140: | Line 147: | ||
result = result..'!!XP!!Cut Time!!XP/s!!GP/s' | result = result..'!!XP!!Cut Time!!XP/s!!GP/s' | ||
for i, tree in | for i, tree in ipairs(SkillData.Woodcutting.trees) do | ||
local log = Items.getItemByID(tree.productId) | |||
result = result..'\r\n|-' | result = result..'\r\n|-' | ||
result = result..'\r\n|style="min-width:25px" data-sort-value="'..tree.name..'"|'..Icons.Icon({log.name, img=tree.name, type='tree', notext=true, size=50}) | |||
result = result..'||'..tree.name..'' | |||
result = result..'\r\n|style="min-width:25px" data-sort-value="'.. | result = result..'||style="min-width:25px" data-sort-value="'..log.name..'"|'..Icons.Icon({log.name, type='item', notext=true, size=50}) | ||
result = result..'||'.. | result = result..'||'..Icons.Icon({log.name, type='item', noicon=true}) | ||
result = result..'||style="min-width:25px" data-sort-value="'.. | result = result..'||style="text-align:right"|'..tree.level | ||
result = result..'||'..Icons.Icon({ | |||
result = result..'||style="text-align:right"|'..tree. | |||
result = result..'||style="text-align:right"|'..tree.baseExperience | result = result..'||style="text-align:right"|'..tree.baseExperience | ||
result = result..'||style="text-align:right" data-sort-value="'..tree.baseInterval..'"|'..Shared.timeString(tree.baseInterval/1000, true) | result = result..'||style="text-align:right" data-sort-value="'..tree.baseInterval..'"|'..Shared.timeString(tree.baseInterval/1000, true) | ||
local XPs = tree.baseExperience / (tree.baseInterval / 1000) | local XPs = tree.baseExperience / (tree.baseInterval / 1000) | ||
local GPs = log.sellsFor / (tree.baseInterval / 1000) | |||
local GPs = | |||
result = result..'||style="text-align:right"|'..Shared.round(XPs, 2, 2) | result = result..'||style="text-align:right"|'..Shared.round(XPs, 2, 2) | ||
result = result..'||style="text-align:right" data-sort-value="'..GPs..'"|'..Icons.GP(Shared.round(GPs, 2, 2)) | result = result..'||style="text-align:right" data-sort-value="'..GPs..'"|'..Icons.GP(Shared.round(GPs, 2, 2)) | ||
Line 164: | Line 169: | ||
function p.getSpecialFishingTable(frame) | function p.getSpecialFishingTable(frame) | ||
local totalWt, lootValue = 0, 0 | local totalWt, lootValue = 0, 0 | ||
local itemArray = | local itemArray = GameData.getEntities(SkillData.Fishing.specialItems, function(item) return true end) | ||
for i, itemDef in ipairs(itemArray) do | for i, itemDef in ipairs(itemArray) do | ||
totalWt = totalWt + itemDef | totalWt = totalWt + itemDef.weight | ||
end | end | ||
-- Sort the loot table by weight in descending order | -- Sort the loot table by weight in descending order | ||
Line 175: | Line 180: | ||
table.insert(resultPart, '\r\n|- class="headerRow-0"\r\n!colspan="2"| Item\r\n!Value\r\n!colspan="2"|Chance') | table.insert(resultPart, '\r\n|- class="headerRow-0"\r\n!colspan="2"| Item\r\n!Value\r\n!colspan="2"|Chance') | ||
for i, itemDef in ipairs(itemArray) do | for i, itemDef in ipairs(itemArray) do | ||
local item = Items.getItemByID(itemDef | local item = Items.getItemByID(itemDef.itemID) | ||
if item ~= nil then | if item ~= nil then | ||
local dropChance = itemDef | local dropChance = itemDef.weight / totalWt * 100 | ||
-- If chance is less than 0.10% then show 2 significant figures, otherwise 2 decimal places | -- If chance is less than 0.10% then show 2 significant figures, otherwise 2 decimal places | ||
local fmt = (dropChance < 0.10 and '%.2g') or '%.2f' | local fmt = (dropChance < 0.10 and '%.2g') or '%.2f' | ||
Line 183: | Line 188: | ||
table.insert(resultPart, '\r\n| ' .. Icons.Icon({item.name, type='item', noicon=true})) | table.insert(resultPart, '\r\n| ' .. Icons.Icon({item.name, type='item', noicon=true})) | ||
table.insert(resultPart, '\r\n|data-sort-value="' .. item.sellsFor .. '"| ' .. Icons.GP(math.floor(item.sellsFor))) | table.insert(resultPart, '\r\n|data-sort-value="' .. item.sellsFor .. '"| ' .. Icons.GP(math.floor(item.sellsFor))) | ||
table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. itemDef | table.insert(resultPart, '\r\n|style="text-align:right" data-sort-value="' .. itemDef.weight .. '"| ' .. Shared.fraction(itemDef.weight, totalWt)) | ||
table.insert(resultPart, '\r\n|style="text-align:right"| ' .. string.format(fmt, dropChance) .. '%') | table.insert(resultPart, '\r\n|style="text-align:right"| ' .. string.format(fmt, dropChance) .. '%') | ||
lootValue = lootValue + (dropChance / 100 * item.sellsFor) | lootValue = lootValue + (dropChance / 100 * item.sellsFor) | ||
Line 199: | Line 204: | ||
local itemArray = {} | local itemArray = {} | ||
for i, itemID in ipairs(SkillData.Fishing. | for i, itemID in ipairs(SkillData.Fishing.junkItemIDs) do | ||
local item = Items.getItemByID(itemID) | local item = Items.getItemByID(itemID) | ||
if item ~= nil then | if item ~= nil then | ||
Line 223: | Line 228: | ||
result = result..'!!XP!!Respawn Time!!Ore Value' | result = result..'!!XP!!Respawn Time!!Ore Value' | ||
local mineData = | local mineData = GameData.getEntities(SkillData.Mining.rockData, function(rock) return true end) | ||
table.sort(mineData, function(a, b) return a.level < b.level end) | |||
table.sort(mineData, function(a, b) return a. | |||
for i, oreData in Shared.skpairs(mineData) do | for i, oreData in Shared.skpairs(mineData) do | ||
local ore = Items.getItemByID(oreData. | local ore = Items.getItemByID(oreData.productID) | ||
result = result..'\r\n|-\r\n|style="min-width:25px"|'..Icons.Icon({ore.name, type='item', size='50', notext=true}) | result = result..'\r\n|-\r\n|style="min-width:25px"|'..Icons.Icon({ore.name, type='item', size='50', notext=true}) | ||
result = result..'||'..Icons.Icon({ore.name, type='item', noicon=true}) | result = result..'||'..Icons.Icon({ore.name, type='item', noicon=true}) | ||
result = result..'||style="text-align:right"|'..oreData. | result = result..'||style="text-align:right"|'..oreData.level..'||style="text-align:right"|'..oreData.baseExperience | ||
result = result..'||style="text-align:right" data-sort-value="'..oreData.baseRespawnInterval..'"|' | result = result..'||style="text-align:right" data-sort-value="'..oreData.baseRespawnInterval..'"|' | ||
result = result..Shared.timeString(oreData.baseRespawnInterval / 1000, true) | result = result..Shared.timeString(oreData.baseRespawnInterval / 1000, true) | ||
Line 241: | Line 245: | ||
end | end | ||
-- TODO TotH has random superior gems also | |||
function p.getMiningGemsTable(frame) | function p.getMiningGemsTable(frame) | ||
local result = '{|class="wikitable sortable stickyHeader"' | local result = '{|class="wikitable sortable stickyHeader"' | ||
Line 246: | Line 251: | ||
result = result..'\r\n!colspan=2|Gem!!Gem Chance!!Gem Price' | result = result..'\r\n!colspan=2|Gem!!Gem Chance!!Gem Price' | ||
local totalWeight = 0 | |||
for i, gemData in | for i, gemData in ipairs(GameData.rawData.randomGems) do | ||
local gem = Items.getItemByID(gemData. | totalWeight = totalWeight + gemData.weight | ||
end | |||
for i, gemData in ipairs(GameData.rawData.randomGems) do | |||
local gem = Items.getItemByID(gemData.itemID) | |||
result = result..'\r\n|-\r\n|style="min-width:25px"|' | result = result..'\r\n|-\r\n|style="min-width:25px"|' | ||
result = result..Icons.Icon({gem.name, type='item', size='50', notext=true}) | result = result..Icons.Icon({gem.name, type='item', size='50', notext=true}) | ||
result = result..'||'..Icons.Icon({gem.name, type='item', noicon=true}) | result = result..'||'..Icons.Icon({gem.name, type='item', noicon=true}) | ||
result = result..'||style="text-align:right"|'..string.format("%.1f%%", gemData. | result = result..'||style="text-align:right"|'..string.format("%.1f%%", gemData.weight / totalWeight * 100) | ||
result = result..'||data-sort-value="'..gem.sellsFor..'"|'..Icons.GP(gem.sellsFor) | result = result..'||data-sort-value="'..gem.sellsFor..'"|'..Icons.GP(gem.sellsFor) | ||
end | end | ||
Line 261: | Line 270: | ||
function p.getFishTable(frame) | function p.getFishTable(frame) | ||
local recipeList = | local recipeList = GameData.getEntities(SkillData.Fishing.fish, function(fish) return true end) | ||
table.sort(recipeList, function(a, b) return a.level < b.level end) | |||
table.sort(recipeList, function(a, b) return | |||
-- Determine cooking levels for all fish | -- Determine cooking levels for all fish | ||
local cookReq = {} | local cookReq = {} | ||
for i, recipe in ipairs(SkillData.Cooking. | for i, recipe in ipairs(SkillData.Cooking.recipes) do | ||
-- This assumes that each raw fish only appears in a single recipe, which is a bit rubbish | -- This assumes that each raw fish only appears in a single recipe, which is a bit rubbish | ||
-- but currently holds | -- but currently holds | ||
Line 286: | Line 292: | ||
table.insert(resultPart, '\r\n!' .. Icons.Icon({'Cooking', type='skill', notext=true}) .. ' Level') | table.insert(resultPart, '\r\n!' .. Icons.Icon({'Cooking', type='skill', notext=true}) .. ' Level') | ||
for i, recipe in ipairs(recipeList) do | for i, recipe in ipairs(recipeList) do | ||
local fish = Items.getItemByID(recipe. | local fish = Items.getItemByID(recipe.productID) | ||
if fish ~= nil then | if fish ~= nil then | ||
local timeSortVal = (recipe.baseMinInterval + recipe.baseMaxInterval) / 2000 | local timeSortVal = (recipe.baseMinInterval + recipe.baseMaxInterval) / 2000 | ||
local timeStr = string.format("%.1fs - %.1fs", recipe.baseMinInterval / 1000, recipe.baseMaxInterval / 1000) | local timeStr = string.format("%.1fs - %.1fs", recipe.baseMinInterval / 1000, recipe.baseMaxInterval / 1000) | ||
local XPs = recipe. | local XPs = recipe.baseExperience / timeSortVal | ||
local GPs = fish.sellsFor / timeSortVal | local GPs = fish.sellsFor / timeSortVal | ||
local cookSortVal = cookReq[recipe.itemID] or 0 | local cookSortVal = cookReq[recipe.itemID] or 0 | ||
Line 316: | Line 322: | ||
result = result..'\r\n!Junk Chance\r\n!Special Chance' | result = result..'\r\n!Junk Chance\r\n!Special Chance' | ||
for i, area in ipairs(SkillData.Fishing. | for i, area in ipairs(SkillData.Fishing.areas) do | ||
result = result..'\r\n|-' | result = result..'\r\n|-' | ||
result = result..'\r\n| style ="text-align: left;" |'..area.name | result = result..'\r\n| style ="text-align: left;" |'..area.name | ||
local fishArray = {} | local fishArray = {} | ||
for j, | for j, fishID in ipairs(area.fishIDs) do | ||
local fishItem = Items.getItemByID( | local fishItem = Items.getItemByID(fishID) | ||
if fishItem ~= nil then | if fishItem ~= nil then | ||
table.insert(fishArray, Icons.Icon({fishItem.name, type='item'})) | table.insert(fishArray, Icons.Icon({fishItem.name, type='item'})) | ||
Line 338: | Line 344: | ||
end | end | ||
-- TODO Expose list of NPCs somewhere when applicable (e.g. for Thieving Shorts) | |||
function p.getThievingGeneralRareTable(frame) | function p.getThievingGeneralRareTable(frame) | ||
local rareTxt = '{|class="wikitable sortable"' | local rareTxt = '{|class="wikitable sortable"' | ||
rareTxt = rareTxt..'\r\n!Item!!Qty' | rareTxt = rareTxt..'\r\n!Item!!Qty' | ||
rareTxt = rareTxt..'!!Price!!colspan="2"|Chance' | rareTxt = rareTxt..'!!Price!!colspan="2"|Chance' | ||
for i, drop in pairs(SkillData.Thieving. | for i, drop in pairs(SkillData.Thieving.generalRareItems) do | ||
local thisItem = Items.getItemByID(drop.itemID) | local thisItem = Items.getItemByID(drop.itemID) | ||
local odds = drop.chance | local odds = drop.chance | ||
Line 370: | Line 377: | ||
table.insert(normalTxt, '===Possible Common Drops:===\r\nUp to one of these will be received on a successful pickpocket:') | table.insert(normalTxt, '===Possible Common Drops:===\r\nUp to one of these will be received on a successful pickpocket:') | ||
local totalWt = 0 | local totalWt = 0 | ||
local lootChance = SkillData.Thieving. | local lootChance = SkillData.Thieving.itemChance | ||
local lootValue = 0 | local lootValue = 0 | ||
--First loop through to get the total weight so we have it for later | --First loop through to get the total weight so we have it for later | ||
for i, loot in pairs(npc.lootTable) do | for i, loot in pairs(npc.lootTable) do | ||
totalWt = totalWt + loot | totalWt = totalWt + loot.weight | ||
end | end | ||
Line 382: | Line 389: | ||
table.insert(normalTxt, '!!Price!!colspan="2"|Chance') | table.insert(normalTxt, '!!Price!!colspan="2"|Chance') | ||
local lootTable = GameData.getEntities(npc.lootTable, function(loot) return true end) | |||
--Then sort the loot table by weight | --Then sort the loot table by weight | ||
table.sort( | table.sort(lootTable, function(a, b) return a.weight > b.weight end) | ||
for i, | for i, loot in ipairs(lootTable) do | ||
local thisItem = Items.getItemByID( | local thisItem = Items.getItemByID(loot.id) | ||
if thisItem ~= nil then | if thisItem ~= nil then | ||
table.insert(normalTxt, '\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item'})) | table.insert(normalTxt, '\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item'})) | ||
Line 392: | Line 399: | ||
table.insert(normalTxt, '\r\n|-\r\n|Unknown Item[[Category:Pages with script errors]]') | table.insert(normalTxt, '\r\n|-\r\n|Unknown Item[[Category:Pages with script errors]]') | ||
end | end | ||
table.insert(normalTxt, '||style="text-align:right" data-sort-value="'.. | table.insert(normalTxt, '||style="text-align:right" data-sort-value="'..(loot.minQuantity + loot.maxQuantity)..'"|') | ||
if | if loot.minQuantitiy ~= loot.maxQuantitiy then | ||
table.insert(normalTxt, ' | table.insert(normalTxt, Shared.formatnum(loot.minQuantitiy) .. ' - ' .. Shared.formatnum(loot.maxQuantity)) | ||
else | |||
table.insert(normalTxt, Shared.formatnum(loot.maxQuantity)) | |||
end | end | ||
--Adding price columns | --Adding price columns | ||
Line 405: | Line 413: | ||
else | else | ||
itemPrice = thisItem.sellsFor ~= nil and thisItem.sellsFor or 0 | itemPrice = thisItem.sellsFor ~= nil and thisItem.sellsFor or 0 | ||
if itemPrice == 0 or | if itemPrice == 0 or loot.minQuantity == loot.maxQuantitiy then | ||
table.insert(normalTxt, '||'..Icons.GP(itemPrice)) | table.insert(normalTxt, '||'..Icons.GP(itemPrice)) | ||
else | else | ||
table.insert(normalTxt, '||'..Icons.GP(itemPrice, itemPrice * | table.insert(normalTxt, '||'..Icons.GP(itemPrice * loot.minQuantitiy, itemPrice * loot.maxQuantitiy)) | ||
end | end | ||
end | end | ||
--Getting the drop chance | --Getting the drop chance | ||
local dropChance = ( | local dropChance = (loot.weight / totalWt * lootChance) | ||
if dropChance | if dropChance < 100 then | ||
--Show fraction as long as it isn't going to be 1/1 | --Show fraction as long as it isn't going to be 1/1 | ||
table.insert(normalTxt, '||style="text-align:right" data-sort-value="'.. | table.insert(normalTxt, '||style="text-align:right" data-sort-value="'..loot.weight..'"') | ||
table.insert(normalTxt, '|'..Shared.fraction( | table.insert(normalTxt, '|'..Shared.fraction(loot.weight * lootChance, totalWt * 100)) | ||
table.insert(normalTxt, '||') | table.insert(normalTxt, '||') | ||
else | else | ||
table.insert(normalTxt, '||colspan="2" data-sort-value="'.. | table.insert(normalTxt, '||colspan="2" data-sort-value="'..loot.weight..'"') | ||
end | end | ||
table.insert(normalTxt, 'style="text-align:right"|'..Shared.round(dropChance, 2, 2)..'%') | table.insert(normalTxt, 'style="text-align:right"|'..Shared.round(dropChance, 2, 2)..'%') | ||
--Adding to the average loot value based on price & dropchance | --Adding to the average loot value based on price & dropchance | ||
lootValue = lootValue + (dropChance * 0.01 * itemPrice * ( | lootValue = lootValue + (dropChance * 0.01 * itemPrice * (loot.minQuantitiy + loot.maxQuantitiy) / 2) | ||
end | end | ||
if Shared.tableCount(npc.lootTable) > 1 then | if Shared.tableCount(npc.lootTable) > 1 then | ||
Line 456: | Line 464: | ||
areaTxt = areaTxt..'\r\n!Item!!Qty' | areaTxt = areaTxt..'\r\n!Item!!Qty' | ||
areaTxt = areaTxt..'!!Price!!colspan="2"|Chance' | areaTxt = areaTxt..'!!Price!!colspan="2"|Chance' | ||
local dropLines = {} | local dropLines = {} | ||
for i, drop in pairs(area.uniqueDrops) do | for i, drop in pairs(area.uniqueDrops) do | ||
local thisItem = Items.getItemByID(drop. | local thisItem = Items.getItemByID(drop.id) | ||
local lineTxt = '' | local lineTxt = '' | ||
lineTxt = lineTxt..'\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item'}) | lineTxt = lineTxt..'\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item'}) | ||
lineTxt = lineTxt..'||data-sort-value="'..drop. | lineTxt = lineTxt..'||data-sort-value="'..drop.quantity..'"| '..Shared.formatnum(drop.quantity)..'||data-sort-value="'..thisItem.sellsFor..'"|'..Icons.GP(thisItem.sellsFor) | ||
lineTxt = lineTxt..'||style="text-align:right"|'..Shared.fraction(1, 1/(SkillData.Thieving. | lineTxt = lineTxt..'||style="text-align:right"|'..Shared.fraction(1, 1/(SkillData.Thieving.baseAreaUniqueChance/100)) | ||
lineTxt = lineTxt..'||'..Shared.round(SkillData.Thieving.AreaUniqueChance, 2, 2)..'%' | lineTxt = lineTxt..'||'..Shared.round(SkillData.Thieving.AreaUniqueChance, 2, 2)..'%' | ||
dropLines[thisItem.name] = lineTxt | dropLines[thisItem.name] = lineTxt | ||
Line 471: | Line 478: | ||
end | end | ||
areaTxt = areaTxt..'\r\n|-class="sortbottom" \r\n!colspan="3"|Total:' | areaTxt = areaTxt..'\r\n|-class="sortbottom" \r\n!colspan="3"|Total:' | ||
areaTxt = areaTxt..'\r\n|style="text-align:right"|'..Shared.fraction(1, 1/(SkillData.Thieving. | areaTxt = areaTxt..'\r\n|style="text-align:right"|'..Shared.fraction(1, 1/(SkillData.Thieving.baseAreaUniqueChance/100))..'||' | ||
areaTxt = areaTxt..'style="text-align:right"|'..Shared.round(SkillData.Thieving. | areaTxt = areaTxt..'style="text-align:right"|'..Shared.round(SkillData.Thieving.baseAreaUniqueChance, 2, 2)..'%' | ||
areaTxt = areaTxt..'\r\n|}' | areaTxt = areaTxt..'\r\n|}' | ||
table.insert(sectionTxt, areaTxt) | table.insert(sectionTxt, areaTxt) | ||
if npc.uniqueDrop ~= nil and npc.uniqueDrop. | if npc.uniqueDrop ~= nil and npc.uniqueDrop.id ~= nil then | ||
local uniqueTxt = '===Possible NPC Unique Drop===' | local thisItem = Items.getItemByID(npc.uniqueDrop.id) | ||
if thisItem ~= nil then | |||
local uniqueTxt = '===Possible NPC Unique Drop===' | |||
uniqueTxt = uniqueTxt..'\r\nThe chance of receiving the unique drop for an NPC is based on a combination of several factors.' | |||
uniqueTxt = uniqueTxt..' The unique drop chance for an NPC is included in the tooltip for your Stealth against that NPC.' | |||
uniqueTxt = uniqueTxt..'\r\nThe unique drop for the '..npc.name..' is ' | |||
if npc.uniqueDrop.quantity > 1 then | |||
uniqueTxt = uniqueTxt..Icons.Icon({thisItem.name, type='item', qty=npc.uniqueDrop.quantity}) | |||
else | |||
uniqueTxt = uniqueTxt..Icons.Icon({thisItem.name, type='item'}) | |||
end | |||
table.insert(sectionTxt, uniqueTxt) | |||
end | end | ||
end | end | ||
Line 508: | Line 516: | ||
result = result..'\r\n|- class="headerRow-0"' | result = result..'\r\n|- class="headerRow-0"' | ||
result = result..'\r\n!colspan="2"|Name!!Area!!'..Icons.Icon({'Thieving', type='skill', notext=true})..' Level!!Experience!!Max Hit!!Perception!!GP!!Unique Drop' | result = result..'\r\n!colspan="2"|Name!!Area!!'..Icons.Icon({'Thieving', type='skill', notext=true})..' Level!!Experience!!Max Hit!!Perception!!GP!!Unique Drop' | ||
local npcArray = | local npcArray = GameData.getEntities(SkillData.Thieving.npcs, function(npc) return true end) | ||
table.sort(npcArray, function(a, b) return a.level < b.level end) | table.sort(npcArray, function(a, b) return a.level < b.level end) | ||
for i, npc in | for i, npc in ipairs(npcArray) do | ||
result = result..'\r\n|-' | result = result..'\r\n|-' | ||
result = result..'\r\n|'..Icons.Icon({npc.name, type='thieving', size='50', notext=true}) | result = result..'\r\n|'..Icons.Icon({npc.name, type='thieving', size='50', notext=true}) | ||
Line 518: | Line 526: | ||
result = result..'||'..area.name | result = result..'||'..area.name | ||
result = result..'||data-sort-value="' .. npc.level .. '"| '..Icons._SkillReq('Thieving', npc.level) | result = result..'||data-sort-value="' .. npc.level .. '"| '..Icons._SkillReq('Thieving', npc.level) | ||
result = result..'||style="text-align:right"|'..npc. | result = result..'||style="text-align:right"|'..npc.baseExperience | ||
result = result..'||style="text-align:right"|'..(npc.maxHit * 10) | result = result..'||style="text-align:right"|'..(npc.maxHit * 10) | ||
result = result..'||style="text-align:right"|'..npc.perception | result = result..'||style="text-align:right"|'..npc.perception | ||
result = result..'||data-sort-value="' .. npc.maxGP .. '"|'..Icons.GP(1, npc.maxGP) | result = result..'||data-sort-value="' .. npc.maxGP .. '"|'..Icons.GP(1, npc.maxGP) | ||
if npc.uniqueDrop ~= nil | if npc.uniqueDrop ~= nil then | ||
local uniqueDrop = Items.getItemByID(npc.uniqueDrop. | local uniqueDrop = Items.getItemByID(npc.uniqueDrop.id) | ||
if npc.uniqueDrop. | if npc.uniqueDrop.quantity > 1 then | ||
result = result..'||data-sort-value="'..uniqueDrop.name..'"|'..Icons.Icon({uniqueDrop.name, type='item', qty = npc.uniqueDrop. | result = result..'||data-sort-value="'..uniqueDrop.name..'"|'..Icons.Icon({uniqueDrop.name, type='item', qty = npc.uniqueDrop.quantity}) | ||
else | else | ||
result = result..'||data-sort-value="'..uniqueDrop.name..'"|'..Icons.Icon({uniqueDrop.name, type='item'}) | result = result..'||data-sort-value="'..uniqueDrop.name..'"|'..Icons.Icon({uniqueDrop.name, type='item'}) | ||
Line 544: | Line 552: | ||
table.insert(resultPart, '\r\n!Area!!'..Icons.Icon({'Thieving', type='skill', notext=true})..' Level!!NPCs!!Unique Drops') | table.insert(resultPart, '\r\n!Area!!'..Icons.Icon({'Thieving', type='skill', notext=true})..' Level!!NPCs!!Unique Drops') | ||
for i, area in ipairs(SkillData.Thieving.areas) do | |||
for i, area in ipairs( | |||
local minLevel, npcList, areaItemList = nil, {}, {} | local minLevel, npcList, areaItemList = nil, {}, {} | ||
-- Build NPC list & determine level for area, this is the minimum | -- Build NPC list & determine level for area, this is the minimum | ||
-- Thieving level required for all NPCs within that area | -- Thieving level required for all NPCs within that area | ||
if area.npcs ~= nil and Shared. | if area.npcs ~= nil and not Shared.tableIsEmpty(area.npcs) then | ||
for j, npcID in ipairs(area.npcs) do | for j, npcID in ipairs(area.npcs) do | ||
local npc = Skills.getThievingNPCByID(npcID) | |||
local npc = | |||
if minLevel == nil or npc.level < minLevel then | if minLevel == nil or npc.level < minLevel then | ||
minLevel = npc.level | minLevel = npc.level | ||
Line 566: | Line 571: | ||
if area.uniqueDrops ~= nil and Shared.tableCount(area.uniqueDrops) > 0 then | if area.uniqueDrops ~= nil and Shared.tableCount(area.uniqueDrops) > 0 then | ||
for k, drop in ipairs(area.uniqueDrops) do | for k, drop in ipairs(area.uniqueDrops) do | ||
local areaItem = Items.getItemByID(drop. | local areaItem = Items.getItemByID(drop.id) | ||
if areaItem == nil then | if areaItem == nil then | ||
table.insert(areaItemList, 'Unknown[[Category:Pages with script errors]]') | table.insert(areaItemList, 'Unknown[[Category:Pages with script errors]]') | ||
else | else | ||
local iconDef = {areaItem.name, type='item'} | local iconDef = {areaItem.name, type='item'} | ||
if drop. | if drop.quantity > 1 then | ||
iconDef.qty = drop. | iconDef.qty = drop.quantity | ||
end | end | ||
table.insert(areaItemList, Icons.Icon(iconDef)) | table.insert(areaItemList, Icons.Icon(iconDef)) | ||
Line 593: | Line 598: | ||
end | end | ||
function p._getFarmingTable( | function p._getFarmingTable(categoryName) | ||
local | local category = GameData.getEntityByName(SkillData.Farming.categories, categoryName) | ||
if category == ' | if category == nil then | ||
return 'ERROR: Invalid farming category. Please choose Allotments, Herbs, or Trees' | |||
end | |||
return ' | local seedList = GameData.getEntities(SkillData.Farming.recipes, | ||
function(recipe) | |||
return recipe.categoryID == category.id | |||
end) | |||
if Shared.tableIsEmpty(seedList) then | |||
return '' | |||
end | end | ||
Line 605: | Line 615: | ||
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.id == 'melvorD: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.id == 'melvorD:Herb' then | ||
result = result..'!!colspan="2"|Herb!!Herb Value' | result = result..'!!colspan="2"|Herb!!Herb Value' | ||
elseif category == 'Tree' then | elseif category.id == 'melvorD:Tree' then | ||
result = result..'!!colspan="2"|Logs!!Log Value' | result = result..'!!colspan="2"|Logs!!Log Value' | ||
end | end | ||
Line 616: | Line 626: | ||
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 | for i, seed in ipairs(seedList) do | ||
result = result..'\r\n|-' | local seedItem = Items.getItemByID(seed.seedCost.id) | ||
local productItem = Items.getItemByID(seed.productId) | |||
if seedItem ~= nil and productItem ~= nil then | |||
result = result..'\r\n|-' | |||
result = result..'\r\n|'..Icons.Icon({seedItem.name, type='item', size='50', notext=true})..'||[['..seedItem.name..']]' | |||
result = result..'||'..seed.level..'||'..Shared.formatnum(seed.baseExperience) | |||
result = result..'||data-sort-value="'..(seed.baseInterval / 1000)..'"|'..Shared.timeString(seed.baseInterval / 1000, true) | |||
result = result..'||data-sort-value="'..seedItem.sellsFor..'"|'..Icons.GP(seedItem.sellsFor) | |||
result = result..'||'..Icons.Icon({productItem.name, type='item', size='50', notext=true})..'||[['..productItem.name..']]' | |||
if category.id == 'melvorD:Allotment' then | |||
result = result..'||'..Icons.Icon({'Hitpoints', type='skill', notext=true})..' '..((productItem.healsFor or 0) * 10) | |||
end | |||
result = result..'||data-sort-value="'..productItem.sellsFor..'"|'..Icons.GP(productItem.sellsFor) | |||
result = result..'||'..ItemSourceTables._getItemSources(seedItem.id) | |||
end | end | ||
end | end | ||
Line 648: | Line 660: | ||
result = result..'!!Healing!!Value' | result = result..'!!Healing!!Value' | ||
local | local recipes = GameData.getEntities(SkillData.Farming.recipes, | ||
function(recipe) | |||
table.sort( | local product = Items.getItemByID(recipe.productID) | ||
return product ~= nil and product.healsFor ~= nil and product.healsFor > 0 | |||
end) | |||
table.sort(recipes, function(a, b) return a.level < b.level end) | |||
for i, | for i, recipe in ipairs(recipes) do | ||
local | local product = Items.getItemByID(recipe.productID) | ||
if | if product ~= nil and product.healsFor ~= nil and product.healsFor > 0 then | ||
result = result..'\r\n|-' | result = result..'\r\n|-' | ||
result = result..'\r\n|'..Icons.Icon({ | result = result..'\r\n|'..Icons.Icon({product.name, type='item', notext='true', size='50'})..'||[['..product.name..']]' | ||
result = result..'||style="text-align:right;"|'.. | result = result..'||style="text-align:right;"|'..recipe.level | ||
result = result..'||style="text-align:right" data-sort-value="'.. | result = result..'||style="text-align:right" data-sort-value="'..product.healsFor..'"|'..Icons.Icon({"Hitpoints", type="skill", notext=true})..' '..(product.healsFor * 10) | ||
result = result..'||style="text-align:right" data-sort-value="'.. | result = result..'||style="text-align:right" data-sort-value="'..product.sellsFor..'"|'..Icons.GP(product.sellsFor) | ||
end | end | ||
end | end |