4,978
edits
(Separate Rune costs in Creation Table; Add Township and Superheat creation data into Creation Table;) |
(Centered Qty and Chance in Loot Tables; Make Creation Table sortable and give it a sticky header; Pull Arch and Mining & Alt Magic Gem sources into Creation Tables; Sorted tables by output quantity) |
||
Line 18: | Line 18: | ||
['melvorAoD:EarthGolem'] = 'Earth Golem (AoD)' | ['melvorAoD:EarthGolem'] = 'Earth Golem (AoD)' | ||
} | } | ||
local function doesRecipeHaveItemID(recipe, itemID) | local function doesRecipeHaveItemID(recipe, itemID) | ||
Line 49: | Line 32: | ||
function p._getCreationTableData(item, tableData) | function p._getCreationTableData(item, tableData) | ||
if tableData == nil then tableData = {} end | if tableData == nil then tableData = {} end | ||
local itemID = item.id | local itemID = item.id | ||
Line 68: | Line 38: | ||
local skillIDs = { | local skillIDs = { | ||
['Gathering'] = { | ['Gathering'] = { | ||
['Farming'] = { recipeKey = 'recipes | ['Farming'] = { recipeKey = 'recipes' }, | ||
['Woodcutting'] = { recipeKey = 'trees | ['Woodcutting'] = { recipeKey = 'trees' }, | ||
['Fishing'] = { recipeKey = 'fish | ['Fishing'] = { recipeKey = 'fish' }, | ||
['Firemaking'] = { recipeKey = 'logs | ['Firemaking'] = { recipeKey = 'logs' }, | ||
['Mining'] = { recipeKey = 'rockData | ['Mining'] = { recipeKey = 'rockData' }, | ||
['Cartography'] = { recipeKey = 'paperRecipes | ['Cartography'] = { recipeKey = 'paperRecipes' }, | ||
['Harvesting'] = { recipeKey = 'veinData | ['Harvesting'] = { recipeKey = 'veinData' } | ||
}, | }, | ||
['Artisan'] = { | ['Artisan'] = { | ||
Line 92: | Line 62: | ||
local skillData = SkillData[localSkillID] | local skillData = SkillData[localSkillID] | ||
local skill = skillData.name | local skill = skillData.name | ||
local reqs | local lvl, reqs, isAbyssal, xp, costs, qty, source, time, maxTime, weight, totalWeight = nil, nil, false, nil, nil, nil, nil, nil, nil, nil, nil, nil | ||
for i, recipe in ipairs(skillData[dataProp.recipeKey]) do | for i, recipe in ipairs(skillData[dataProp.recipeKey]) do | ||
local hasProduct = doesRecipeHaveItemID(recipe, itemID) | local hasProduct = doesRecipeHaveItemID(recipe, itemID) | ||
Line 163: | Line 133: | ||
table.insert(tableData, { | table.insert(tableData, { | ||
['skill'] = skill, | ['skill'] = skill, | ||
['lvl'] = lvl, | |||
['reqs'] = reqs, | ['reqs'] = reqs, | ||
['isAbyssal'] = isAbyssal, | ['isAbyssal'] = isAbyssal, | ||
Line 186: | Line 157: | ||
local skillData = SkillData[localSkillID] | local skillData = SkillData[localSkillID] | ||
local skill = skillData.name | local skill = skillData.name | ||
local reqs | local lvl, reqs, isAbyssal, xp, costs, qty, source, time, maxTime = nil, nil, false, nil, nil, nil, nil, nil, nil, nil | ||
for i, recipe in ipairs(skillData.recipes) do | for i, recipe in ipairs(skillData.recipes) do | ||
if recipe.productID == itemID or | if recipe.productID == itemID or | ||
Line 213: | Line 184: | ||
if levelUnlock ~= nil then | if levelUnlock ~= nil then | ||
reqs = reqs .. '<br>' .. Icons._MasteryReq(item.name, levelUnlock.level, false) | reqs = reqs .. '<br>' .. Icons._MasteryReq(item.name, levelUnlock.level, false) | ||
end | end | ||
end | end | ||
Line 266: | Line 221: | ||
table.insert(tableData, { | table.insert(tableData, { | ||
['skill'] = skill, | ['skill'] = skill, | ||
[' | ['lvl'] = lvl, | ||
['reqs'] = reqs, | |||
['isAbyssal'] = isAbyssal, | ['isAbyssal'] = isAbyssal, | ||
['xp'] = xp, | ['xp'] = xp, | ||
Line 278: | Line 234: | ||
local reqPart, qtyPart = {}, {} | local reqPart, qtyPart = {}, {} | ||
for j, altCost in ipairs(recipe.alternativeCosts) do | for j, altCost in ipairs(recipe.alternativeCosts) do | ||
table.insert(tableData, { | table.insert(tableData, { | ||
['skill'] = skill, | ['skill'] = skill, | ||
[' | ['lvl'] = lvl, | ||
['reqs'] = reqs, | |||
['isAbyssal'] = isAbyssal, | ['isAbyssal'] = isAbyssal, | ||
['xp'] = xp, | ['xp'] = xp, | ||
['costs'] = | ['costs'] = Common.getCostString({ ["items"] = altCost.itemCosts, ["currencies"] = recipe.currencyCosts }), | ||
['qty'] = qty * altCost.quantityMultiplier, | ['qty'] = qty * altCost.quantityMultiplier, | ||
['source'] = | ['source'] = source, | ||
['time'] = time, | ['time'] = time, | ||
['maxTime'] = maxTime | ['maxTime'] = maxTime | ||
Line 303: | Line 249: | ||
-- Finally, normal recipes with a single set of item costs | -- Finally, normal recipes with a single set of item costs | ||
elseif type(recipe.itemCosts) == 'table' and not Shared.tableIsEmpty(recipe.itemCosts) then | elseif type(recipe.itemCosts) == 'table' and not Shared.tableIsEmpty(recipe.itemCosts) then | ||
if localSkillID == 'Cooking' then | |||
-- Cooking includes the required utility (fire, furnace, pot) as a special requirement | |||
local cookingCatIcon = { | |||
["melvorD:Fire"] = 'Normal Cooking Fire', | |||
["melvorD:Furnace"] = 'Basic Furnace', | |||
["melvorD:Pot"] = 'Basic Pot' | |||
} | |||
local categoryIconName, categoryName = cookingCatIcon[recipe.categoryID], nil | |||
local recipeCategory = GameData.getEntityByID(SkillData.Cooking.categories, recipe.categoryID) | |||
if recipeCategory ~= nil then | |||
categoryName = recipeCategory.modifierName or recipeCategory.name | |||
end | |||
if categoryIconName ~= nil and categoryName ~= nil then | |||
reqs = reqs .. '<br>' .. Icons.Icon({ 'Cooking', categoryName, section = 'Cooking Upgrades', img = categoryIconName, type = 'upgrade' }) | |||
end | |||
end | |||
table.insert(tableData, { | table.insert(tableData, { | ||
['skill'] = skill, | ['skill'] = skill, | ||
[' | ['lvl'] = lvl, | ||
['reqs'] = reqs, | |||
['isAbyssal'] = isAbyssal, | ['isAbyssal'] = isAbyssal, | ||
['xp'] = xp, | ['xp'] = xp, | ||
['costs'] = recipe.itemCosts, | ['costs'] = Common.getCostString({ ["items"] = recipe.itemCosts, ["currencies"] = recipe.currencyCosts }), | ||
['qty'] = qty, | ['qty'] = qty, | ||
['source'] = | ['source'] = source, | ||
['time'] = time, | ['time'] = time, | ||
['maxTime'] = maxTime | ['maxTime'] = maxTime | ||
}) | }) | ||
end | end | ||
Line 327: | Line 290: | ||
local imgType = Magic._getSpellIconType(altSpell) | local imgType = Magic._getSpellIconType(altSpell) | ||
table.insert(tableData, { | table.insert(tableData, { | ||
['skill'] = 'Magic', | ['skill'] = 'Alt Magic', | ||
['reqs'] = Icons. | ['lvl'] = altSpell.level, | ||
['reqs'] = Icons.Icon({'Alt Magic', type='skill', notext=true}) .. ' Level ' .. altSpell.level, | |||
['isAbyssal'] = false, | ['isAbyssal'] = false, | ||
['xp'] = altSpell.baseExperience, | ['xp'] = altSpell.baseExperience, | ||
Line 348: | Line 312: | ||
table.insert(tableData, { | table.insert(tableData, { | ||
['skill'] = 'Astrology', | ['skill'] = 'Astrology', | ||
['lvl'] = 1, | |||
['reqs'] = Icons._SkillReq('Astrology', 1, false, (isAbyssal and 'melvorItA:Abyssal' or nil)), | ['reqs'] = Icons._SkillReq('Astrology', 1, false, (isAbyssal and 'melvorItA:Abyssal' or nil)), | ||
['isAbyssal'] = isAbyssal, | ['isAbyssal'] = isAbyssal, | ||
['qty'] = | ['qty'] = 1, | ||
['xp'] = (isAbyssal and 1238 or 5), -- Use the XP value for the first constellation | ['xp'] = (isAbyssal and 1238 or 5), -- Use the XP value for the first constellation | ||
['source'] = Icons.Icon({ 'Astrology', type='skill', class=(isAbyssal and 'abyss-icon' or nil) }), | ['source'] = Icons.Icon({ 'Astrology', type='skill', class=(isAbyssal and 'abyss-icon' or nil) }), | ||
Line 358: | Line 323: | ||
end | end | ||
-- Can we find this in an Archaeology digsite? | |||
for i, drop in ipairs(p._getItemArchSources(item)) do | |||
if drop.name ~= nil then | |||
table.insert(tableData, { | |||
['skill'] = 'Archaeology', | |||
['lvl'] = drop.level, | |||
['reqs'] = Icons._SkillReq('Archaeology', drop.level) .. ' ('..drop.size..')', | |||
['isAbyssal'] = false, | |||
['minqty'] = drop.minQty, | |||
['qty'] = drop.maxQty, | |||
['source'] = Icons.Icon({ drop.name, type='poi' }), | |||
['time'] = 4, | |||
['weight'] = drop.dropWt, | |||
['totalWeight'] = drop.totalWt | |||
--['expIcon'] = Icons.getExpansionIcon(drop.id)}), | |||
}) | |||
end | |||
end | |||
-- Mining: Gems, and also Alt. Magic spells producing random gems | |||
local | if Shared.contains({'Gem', 'Superior Gem', 'Abyssal Gem'}, item.type) then | ||
local gemKeys = { 'randomGems', 'randomSuperiorGems', 'randomAbyssalGems' } | |||
for i, gemKey in ipairs(gemKeys) do | |||
local thisGem, totalGemWeight = nil, 0 | |||
for j, gem in ipairs(GameData.rawData[gemKey]) do | |||
totalGemWeight = totalGemWeight + gem.weight | |||
if gem.itemID == item.id then | |||
thisGem = gem | |||
end | |||
end | |||
if thisGem ~= nil then | |||
--local expIcon = '' | |||
local sourceTxt, lvl, isAbyssal = nil, nil, false | |||
if item.type == 'Abyssal Gem' then | |||
sourceTxt = '[[Mining#Abyssal Gems|Abyssal Gem]]' | |||
lvl = 1 | |||
isAbyssal = true | |||
elseif item.type == 'Superior Gem' then | |||
--expIcon = Icons.TotH() | |||
sourceTxt = '[[Mining#Superior Gems|Superior Gem]]' | |||
-- Superior gems can only be found with Mining 100 or above | |||
lvl = 100 | |||
else | |||
sourceTxt = '[[Mining#Gems|Gem]]' | |||
-- Gems can only be found with any Mining level | |||
lvl = 1 | |||
end | |||
table.insert(tableData, { | |||
['skill'] = 'Mining', | |||
['lvl'] = lvl, | |||
['reqs'] = Icons._SkillReq('Mining', lvl, false, (isAbyssal and 'melvorItA:Abyssal' or nil)), | |||
['isAbyssal'] = isAbyssal, | |||
['minqty'] = thisGem.minQuantity, | |||
['qty'] = thisGem.maxQuantity, | |||
['source'] = sourceTxt, | |||
['time'] = 3, | |||
['weight'] = thisGem.weight, | |||
['totalWeight'] = totalGemWeight, | |||
--expIcon = expIcon | |||
}) | |||
-- Check for Alt. Magic spells also | |||
local producesKey = (gemKey == 'randomGems' and 'RandomGem') or (gemKey == 'randomSuperiorGems' and 'RandomSuperiorGem') or nil | |||
if producesKey ~= nil then | |||
for j, spell in ipairs(Magic.getSpellsBySpellBook('altMagic')) do | |||
if spell.produces ~= nil and spell.produces == producesKey then | |||
table.insert(tableData, { | |||
['skill'] = 'Alt Magic', | |||
['lvl'] = spell.level, | |||
['reqs'] = Icons.Icon({'Alt Magic', type='skill', notext=true}) .. ' Level ' .. spell.level, | |||
['minqty'] = thisGem.minQuantity, | |||
['qty'] = thisGem.maxQuantity, | |||
['source'] = Icons.Icon({ spell.name, type=Magic._getSpellIconType(spell) }), | |||
['time'] = 2, | |||
['weight'] = thisGem.weight, | |||
['totalWeight'] = totalGemWeight, | |||
--expIcon = Icons.getExpansionIcon(spell.id) | |||
}) | |||
end | |||
end | |||
end | |||
end | |||
end | end | ||
if not showRequirements and tableData[1].reqs ~= tableData[i].reqs then | end | ||
showRequirements = true | |||
colspan = colspan + 1 | return tableData | ||
end | |||
function p.buildCreationTable(item, tableData) | |||
if Shared.tableIsEmpty(tableData) then return '' end | |||
table.sort(tableData, function(a, b) return (a.qty or 1) < (b.qty or 1) end) | |||
local showSource = false | |||
local showRequirements = false | |||
local showInputs = false | |||
local showRunes = false | |||
local showOutputs = false | |||
local showXP = false | |||
local showTime = false | |||
local showChance = false | |||
local colspan = -1 -- colspan only needs to be set when there are 3+ columns in the table | |||
for i, data in ipairs(tableData) do | |||
if not showSource and tableData[1].source ~= tableData[i].source then | |||
showSource = true | |||
colspan = colspan + 1 | |||
end | |||
if not showRequirements and tableData[1].reqs ~= tableData[i].reqs then | |||
showRequirements = true | |||
colspan = colspan + 1 | |||
end | end | ||
if not showInputs and tableData[1].costs ~= tableData[i].costs then | if not showInputs and tableData[1].costs ~= tableData[i].costs then | ||
Line 391: | Line 444: | ||
colspan = colspan + 1 | colspan = colspan + 1 | ||
end | end | ||
if not showOutputs and tableData[1].qty ~= tableData[i].qty then | if not showOutputs and (tableData[1].qty ~= tableData[i].qty or tableData[1].contents ~= tableData[i].contents) then | ||
showOutputs = true | showOutputs = true | ||
colspan = colspan + 1 | colspan = colspan + 1 | ||
Line 422: | Line 475: | ||
costsRow:wikitext(Icons.Icon({ matItem.name, type='item', qty=mat.quantity })) | costsRow:wikitext(Icons.Icon({ matItem.name, type='item', qty=mat.quantity })) | ||
end | end | ||
end | end | ||
else | else | ||
Line 434: | Line 483: | ||
local resultTable = mw.html.create('table') | local resultTable = mw.html.create('table') | ||
resultTable:addClass('wikitable') | resultTable:addClass('wikitable stickyHeader') | ||
local tableHeader = resultTable:tag('tr') | local tableHeader = resultTable:tag('tr'):addClass('headerRow-0') | ||
local makeSortable = Shared.contains({ showSource, showRequirements, showInputs, showRunes, showOutputs, showXP, showTime, showChance }, true) | |||
if makeSortable then | |||
resultTable:addClass('sortable') | |||
end | |||
if showSource then tableHeader:tag('th'):wikitext('Source') end | if showSource then tableHeader:tag('th'):wikitext('Source') end | ||
Line 446: | Line 500: | ||
if showChance then tableHeader:tag('th'):wikitext('Chance'):attr('colspan', 2) end | if showChance then tableHeader:tag('th'):wikitext('Chance'):attr('colspan', 2) end | ||
-- Populate table data with any unique entries (Ex: Ash's Inputs, Outputs, Exp, Time) | if makeSortable then | ||
-- Populate table data with any unique entries (Ex: Ash's Inputs, Outputs, Exp, Time) | |||
for i, data in ipairs(tableData) do | |||
local recipeRow = resultTable:tag('tr') | |||
if showSource then recipeRow:tag('td'):wikitext(data.source):attr('data-sort-value', data.skill) end | |||
if showRequirements then | |||
if data.reqs ~= nil then | |||
recipeRow:tag('td'):wikitext(data.reqs):attr('data-sort-value', (data.lvl or 0)) | |||
else | |||
recipeRow:tag('td'):wikitext('N/A'):addClass('table-na'):attr('data-sort-value', 0) | |||
end | |||
end | end | ||
if showInputs then | |||
if data.costs ~= nil then | |||
addCostsRow(recipeRow, data, 1) | |||
else | |||
recipeRow:tag('td'):wikitext('N/A'):addClass('table-na') | |||
end | |||
end | end | ||
if showRunes then | |||
if data.runeCost ~= nil then | |||
recipeRow:tag('td'):wikitext(data.runeCost):addClass('center') | |||
else | |||
recipeRow:tag('td'):wikitext('N/A'):addClass('table-na') | |||
end | |||
end | end | ||
if showOutputs then | |||
local outputData = recipeRow:tag('td'):attr('data-sort-value', (data.qty or 1)) | |||
local outputData = recipeRow:tag('td'): | if data.contents ~= nil then | ||
if data.center then outputData:addClass('center') end | outputData:wikitext(data.contents) | ||
if data.center then outputData:addClass('center') end | |||
elseif data.qty ~= nil then | |||
if data.minqty ~= nil and data.minqty ~= data.qty then | |||
outputRow:wikitext((data.minqty ~= nil and (Num.formatnum(data.minqty) .. ' - ') or '')) | |||
end | |||
outputData:wikitext(Icons.Icon({ item.name, type='item', notext=true, qty=(data.qty or 1) })):addClass('center'):attr('data-sort-value', (data.qty or 1)) | |||
else | |||
outputData:wikitext('N/A'):addClass('table-na') | |||
end | |||
end | end | ||
if showXP then | |||
if data.skill ~= nil and data.xp ~= nil then | |||
local iconClass = (data.isAbyssal and 'abyss-icon' or nil) | |||
local xpText = (data.isAbyssal and ' AXP' or ' XP') | |||
recipeRow:tag('td'):attr('data-sort-value', data.xp) | |||
:wikitext(Icons.Icon({ data.skill, notext=true, type='skill', class=iconClass })) | |||
:wikitext(' ' .. Num.formatnum(data.xp) .. xpText) | |||
else | |||
recipeRow:tag('td'):wikitext('N/A'):addClass('table-na'):attr('data-sort-value', 0) | |||
end | |||
end | end | ||
if showTime then | |||
if data.time ~= nil then | |||
recipeRow:tag('td'):wikitext(Shared.timeString(data.time, true)):addClass('center'):attr('data-sort-value', data.time) | |||
else | |||
recipeRow:tag('td'):wikitext('N/A'):addClass('table-na') | |||
end | |||
end | end | ||
if showChance then | |||
if data.weight ~= nil then | |||
-- If chance is less than 0.10% then show 2 significant figures, otherwise 2 decimal places | |||
local chance = data.weight / (data.totalWeight or 100) * 100 | |||
local fmt = (chance < 0.10 and '%.2g') or '%.2f' | |||
local percent = string.format(fmt, chance) | |||
recipeRow:tag('td'):wikitext(Num.fraction(data.weight, (data.totalWeight or 100))):addClass('center'):attr('data-sort-value', percent) | |||
recipeRow:tag('td'):wikitext(percent .. '%'):addClass('center') | |||
else | |||
recipeRow:tag('td'):wikitext('100%'):addClass('center'):attr('colspan', 2):attr('data-sort-value', 100) | |||
end | |||
end | end | ||
end | end | ||
Line 518: | Line 586: | ||
resultTable:tag('tr') | resultTable:tag('tr') | ||
:tag('th'):wikitext('Source'):css('text-align', 'right') | :tag('th'):wikitext('Source'):css('text-align', 'right') | ||
:tag('td'):attr('colspan', colspan):wikitext(tableData[1].source) | |||
end | end | ||
Line 534: | Line 602: | ||
end | end | ||
if showRunes and type(tableData[1].runeCost) == 'string' then | if not showRunes and type(tableData[1].runeCost) == 'string' then | ||
resultTable:tag('tr') | |||
:tag('th'):wikitext('Runes'):css('text-align', 'right') | |||
:tag('td'):wikitext(tableData[1].runeCost):addClass('center') | |||
end | end | ||
if not showOutputs and tableData[1].qty ~= nil then | if not showOutputs and (tableData[1].qty ~= nil or tableData[1].contents ~= nil) then | ||
local outputRow = resultTable:tag('tr') | local outputRow = resultTable:tag('tr') | ||
:tag('th'):wikitext('Outputs'):css('text-align', 'right') | :tag('th'):wikitext('Outputs'):css('text-align', 'right') | ||
if | if tableData[1].contents ~= nil then | ||
outputRow:tag('td'):wikitext(tableData[1]. | outputRow:tag('td'):wikitext(tableData[1].contents) | ||
else | else | ||
outputRow:tag('td'):attr('colspan', colspan):wikitext(Icons.Icon({ item.name, type='item', qty=(tableData[1].qty or 1) })) | local outputData = outputRow:tag('td'):attr('colspan', colspan) | ||
if tableData[1].minqty ~= nil and tableData[1].minqty ~= tableData[1].qty then | |||
outputData:wikitext((tableData[1].minqty ~= nil and (Num.formatnum(tableData[1].minqty) .. ' - ') or '')) | |||
end | |||
outputData:wikitext(Icons.Icon({ item.name, type='item', qty=(tableData[1].qty or 1) })) | |||
end | end | ||
end | end | ||
Line 554: | Line 627: | ||
resultTable:tag('tr') | resultTable:tag('tr') | ||
:tag('th'):wikitext('Base Exp'):css('text-align', 'right') | :tag('th'):wikitext('Base Exp'):css('text-align', 'right') | ||
:tag('td'):attr('colspan', colspan):wikitext(Num.formatnum(tableData[1].xp) .. xpText) | |||
end | end | ||
Line 562: | Line 635: | ||
local timeData = timeHeader:tag('td'):attr('colspan', colspan) | local timeData = timeHeader:tag('td'):attr('colspan', colspan) | ||
:wikitext(Shared.timeString(tableData[1].time, true)) | |||
if tableData[1].maxTime ~= nil and tableData[1].maxTime > tableData[1].time then | if tableData[1].maxTime ~= nil and tableData[1].maxTime > tableData[1].time then | ||
Line 570: | Line 643: | ||
if not showChance and tableData[1].weight ~= nil then | if not showChance and tableData[1].weight ~= nil then | ||
-- If chance is less than 0.10% then show 2 significant figures, otherwise 2 decimal places | |||
local chance = tableData[1].weight / (tableData[1].totalWeight or 100) * 100 | |||
local fmt = (chance < 0.10 and '%.2g') or '%.2f' | |||
local percent = string.format(fmt, chance) | |||
local chanceData = resultTable:tag('tr') | local chanceData = resultTable:tag('tr') | ||
:tag('th'):wikitext('Base Chance'):css('text-align', 'right') | :tag('th'):wikitext('Base Chance'):css('text-align', 'right') | ||
:tag('td'):attr('colspan', colspan) | |||
:wikitext(Num.fraction(tableData[1].weight, (tableData[1].totalWeight or 100)) .. ' (' .. percent .. '%)') | |||
end | end | ||
Line 1,115: | Line 1,191: | ||
function p._getItemLootSourceTable(item) | function p._getItemLootSourceTable(item) | ||
local resultPart = {} | local resultPart = {} | ||
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') | table.insert(resultPart, '{| class="wikitable sortable stickyHeader col-3-center col-4-center"') | ||
table.insert(resultPart, '\r\n|- class="headerRow-0"') | table.insert(resultPart, '\r\n|- class="headerRow-0"') | ||
table.insert(resultPart, '\r\n!Source!!Level!! | table.insert(resultPart, '\r\n!Source!!Level!!Qty!!colspan="2"|Chance') | ||
--Set up function for adding rows | --Set up function for adding rows | ||
Line 1,135: | Line 1,211: | ||
end | end | ||
table.insert(rowPart, '\r\n|style="text-align: left;" data-sort-value="'..levelValue..'"|'..expIcon..' '..level) | table.insert(rowPart, '\r\n|style="text-align: left;" data-sort-value="'..levelValue..'"|'..expIcon..' '..level) | ||
table.insert(rowPart, '\r\n| | table.insert(rowPart, '\r\n|data-sort-value="'..qty..'"|'..Num.formatnum(minqty)) | ||
if qty ~= minqty then table.insert(rowPart, ' - '..Num.formatnum(qty)) end | if qty ~= minqty then table.insert(rowPart, ' - '..Num.formatnum(qty)) end | ||
local chance = weight / totalWeight * 100 | local chance = weight / totalWeight * 100 | ||
Line 1,152: | Line 1,228: | ||
table.insert(rowPart, '\r\n|colspan="2" ') | table.insert(rowPart, '\r\n|colspan="2" ') | ||
else | else | ||
table.insert(rowPart, '\r\n| | table.insert(rowPart, '\r\n|data-sort-value="' .. chanceStr .. '"| ' .. Num.fraction(weight, totalWeight) .. '\r\n|') | ||
end | end | ||
end | end | ||
if weight == -1 then | if weight == -1 then | ||
--Weight of -1 means this is a weird row that has a variable percentage | --Weight of -1 means this is a weird row that has a variable percentage | ||
table.insert(rowPart, ' | table.insert(rowPart, 'data-sort-value="0"|Varies (see Thieving page)') | ||
else | else | ||
table.insert(rowPart, ' | table.insert(rowPart, 'data-sort-value="'.. chanceStr .. '"|'..chanceStr..'%') | ||
end | end | ||
return table.concat(rowPart) | return table.concat(rowPart) | ||
Line 1,180: | Line 1,256: | ||
level = Icons.Icon({'Combat', 'Monsters', notext=true}) .. ' Level ' .. Num.formatnum(monsterLevel), | level = Icons.Icon({'Combat', 'Monsters', notext=true}) .. ' Level ' .. Num.formatnum(monsterLevel), | ||
levelNum = monsterLevel, | levelNum = monsterLevel, | ||
minqty = drop.minQty, | minqty = drop.minQty, | ||
qty = drop.maxQty, | qty = drop.maxQty, | ||
Line 1,349: | Line 1,409: | ||
end | end | ||
--Make sure to return nothing if there are no drop sources | |||
if Shared.tableIsEmpty(dropRows) then return '' end | |||
table.sort(dropRows, function(a, b) | |||
--Make sure to return nothing if there are no drop sources | |||
if Shared.tableIsEmpty(dropRows) then return '' end | |||
table.sort(dropRows, function(a, b) | |||
if a.weight / a.totalWeight == b.weight / b.totalWeight then | if a.weight / a.totalWeight == b.weight / b.totalWeight then | ||
if a.minqty + a.qty == b.minqty + b.qty then | if a.minqty + a.qty == b.minqty + b.qty then | ||
Line 1,442: | Line 1,446: | ||
local upgrade = GameData.getEntityByProperty('itemUpgrades', 'upgradedItemID', item.id) | local upgrade = GameData.getEntityByProperty('itemUpgrades', 'upgradedItemID', item.id) | ||
if upgrade ~= nil then | if upgrade ~= nil then | ||
local | local reqs = nil | ||
if item.charges ~= nil and item.tier ~= nil then | |||
local levelUnlock = GameData.getEntityByProperty(SkillData.Herblore.masteryLevelUnlocks, 'descriptionID', item.tier + 1) | |||
if levelUnlock ~= nil then | |||
reqs = Icons._MasteryReq(item.name, levelUnlock.level, false) | |||
end | |||
end | |||
table.insert(tableData, { | table.insert(tableData, { | ||
['costs'] = | ['reqs'] = reqs, | ||
['qty'] = 1, | ['costs'] = Common.getCostString({ ["items"] = upgrade.itemCosts, ["currencies"] = upgrade.currencyCosts }), | ||
['source'] = '[[Upgrading Items|Item Upgrade]]' | ['qty'] = (upgrade.quantity or 1), | ||
['source'] = '[[Upgrading Items|Item ' .. (upgrade.isDowngrade and 'Downgrade' or 'Upgrade') ..']]' | |||
}) | }) | ||
end | end | ||
Line 1,505: | Line 1,513: | ||
table.insert(tableData, { | table.insert(tableData, { | ||
['skill'] = 'Magic', | ['skill'] = 'Alt Magic', | ||
['reqs'] = smithingReq .. '<br>' .. Icons. | ['lvl'] = spell.level, | ||
['reqs'] = smithingReq .. '<br>' .. Icons.Icon({'Alt Magic', type='skill', notext=true}) .. ' Level ' .. spell.level, | |||
['isAbyssal'] = false, | ['isAbyssal'] = false, | ||
['xp'] = spell.baseExperience, | ['xp'] = spell.baseExperience, | ||
Line 1,541: | Line 1,550: | ||
local resName = (res ~= nil and res.name) or 'Unknown' | local resName = (res ~= nil and res.name) or 'Unknown' | ||
local resQty = math.max(item.sellsFor, 2) | local resQty = math.max(item.sellsFor, 2) | ||
local townshipReq = GameData.getEntityByProperty(tradeDef.unlockRequirements, 'skillID', 'melvorD:Township') | |||
local lvl = townshipReq.level + (townshipReq.type == 'AbyssalLevel' and 120 or 0) | |||
table.insert(tableData, { | table.insert(tableData, { | ||
['reqs'] = | ['lvl'] = lvl, | ||
['reqs'] = Common.getRequirementString(tradeDef.unlockRequirements), | |||
['isAbyssal'] = namespace == 'melvorItA', | ['isAbyssal'] = namespace == 'melvorItA', | ||
['costs'] = Icons.Icon({ resName, qty=resQty, type='resource' }), | ['costs'] = Icons.Icon({ resName, qty=resQty, type='resource' }), | ||
['qty'] = 1, | ['qty'] = 1, | ||
['source'] = Icons.Icon({'Township', 'Trader', type='skill'}), | ['source'] = Icons.Icon({ 'Township', 'Trader', type='skill' }), | ||
}) | }) | ||
break | break | ||
Line 1,557: | Line 1,569: | ||
end | end | ||
function p._getItemShopTableData(item, tableData) | function p._getItemShopTableData(item, tableData) | ||
if tableData == nil then tableData = {} end | if tableData == nil then tableData = {} end | ||
Line 1,567: | Line 1,578: | ||
local namespace, localID = Shared.getLocalID(purchase.id) | local namespace, localID = Shared.getLocalID(purchase.id) | ||
local source = nil | local source = nil | ||
-- Show icon text when it's the only | -- Show icon text when it's the only source of this item | ||
local notext = (Shared.tableCount(tableData) + Shared.tableCount(purchaseArray) > 1) | local notext = (Shared.tableCount(tableData) + Shared.tableCount(purchaseArray) > 1) | ||
Line 1,581: | Line 1,592: | ||
['reqs'] = Common.getRequirementString(purchase.purchaseRequirements), | ['reqs'] = Common.getRequirementString(purchase.purchaseRequirements), | ||
['isAbyssal'] = namespace == 'melvorItA', | ['isAbyssal'] = namespace == 'melvorItA', | ||
['costs'] = | ['costs'] = Common.getCostString(purchase.cost), | ||
['qty'] = Shop._getPurchaseContents(purchase, true, notext), | ['qty'] = purchaseData.qty, | ||
['contents'] = Shop._getPurchaseContents(purchase, true, notext), | |||
['source'] = source, | ['source'] = source, | ||
['center'] = notext | ['center'] = notext | ||
Line 1,611: | Line 1,623: | ||
table.insert(resultPart, sourceTable) | table.insert(resultPart, sourceTable) | ||
end | end | ||
local lootTable = p._getItemLootSourceTable(item) | local lootTable = p._getItemLootSourceTable(item) | ||
if lootTable ~= '' then | if lootTable ~= '' then | ||
Line 1,617: | Line 1,629: | ||
table.insert(resultPart, '===Loot===\r\n'..lootTable) | table.insert(resultPart, '===Loot===\r\n'..lootTable) | ||
end | end | ||
return table.concat(resultPart) | return table.concat(resultPart) | ||
end | end | ||
Line 1,718: | Line 1,730: | ||
if found ~= nil then | if found ~= nil then | ||
table.insert(resultArray, { | table.insert(resultArray, { | ||
id = digSite.id, | id = digSite.id, | ||
Line 1,725: | Line 1,735: | ||
level = digSite.level, | level = digSite.level, | ||
size = sizeName, | size = sizeName, | ||
minQty = | minQty = found.minQuantity, | ||
maxQty = | maxQty = found.maxQuantity, | ||
dropWt = found.weight, | dropWt = found.weight, | ||
totalWt = sizeWeight}) | totalWt = sizeWeight | ||
}) | |||
end | end | ||
end | end | ||
Line 1,741: | Line 1,752: | ||
end | end | ||
--[[ | |||
-- Uncomment this block and execute 'p.test()' within the debug console | -- Uncomment this block and execute 'p.test()' within the debug console | ||
-- to test after making changes | -- to test after making changes | ||
Line 1,751: | Line 1,762: | ||
-- "Signet Ring Half (b)", | -- "Signet Ring Half (b)", | ||
-- "Astrology Lesser Relic", | -- "Astrology Lesser Relic", | ||
"Mysterious Stone", | |||
"Charge Stone of Rhaelyx", | |||
"Gold Topaz Ring", | |||
"Charcoal", | "Charcoal", | ||
"Ash", | "Ash", | ||
"Coal Ore", | "Coal Ore", | ||
"Golden Star", | |||
"Potion Box III", | |||
"Rune Essence", | "Rune Essence", | ||
"Dragonite Bar", | "Dragonite Bar", | ||
"Holy Dust", | |||
-- "Rune Platebody", | -- "Rune Platebody", | ||
"Arrow Shafts", | "Arrow Shafts", | ||
Line 1,790: | Line 1,805: | ||
"Mastery Token (Cooking)", | "Mastery Token (Cooking)", | ||
"Thief's Moneysack", | "Thief's Moneysack", | ||
-- "Slayer Deterer", | -- "Slayer Deterer", | ||
"Paper", | "Paper", | ||
-- "Lemon", | -- "Lemon", | ||
"Aranite Brush", | "Aranite Brush", | ||
"Charged Diamond Shard", | |||
"Barrier Dust", | "Barrier Dust", | ||
"Gloom Resin", | "Gloom Resin", | ||
Line 1,812: | Line 1,827: | ||
"Dragon Javelin", | "Dragon Javelin", | ||
"Skillers Body", | "Skillers Body", | ||
"Abyssal Compost", | |||
} | } | ||
local checkFuncs = { | local checkFuncs = { | ||
Line 1,839: | Line 1,855: | ||
end | end | ||
end | end | ||
--]] | |||
return p | return p |