4,980
edits
m (Simple fix for Firemaking Primary and Secondary products not showing Firemaking as a source) |
(Overhauled Creation Tables; Add support for Abyssal gems in Item and Loot sources;) |
||
Line 21: | Line 21: | ||
local function doesRecipeHaveItemID(recipe, itemID) | local function doesRecipeHaveItemID(recipe, itemID) | ||
if recipe.productId == itemID then | if recipe.productId == itemID then | ||
return true | return true | ||
elseif Shared.contains(recipe.primaryProducts, itemID) or Shared.contains(recipe.secondaryProducts, itemID) then | elseif Shared.contains(recipe.primaryProducts, itemID) or Shared.contains(recipe.secondaryProducts, itemID) then | ||
return true | return true | ||
elseif type(recipe.products) == 'table' then | elseif type(recipe.products) == 'table' then | ||
return GameData.getEntityByProperty(recipe.products, 'itemID', itemID) ~= nil | |||
end | end | ||
return false | return false | ||
end | end | ||
Line 41: | Line 33: | ||
local skill = '' | local skill = '' | ||
local specialReq = nil | local specialReq = nil | ||
local | local source = nil | ||
local time = 0 | local time = 0 | ||
local maxTime = nil | local maxTime = nil | ||
Line 47: | Line 39: | ||
local isAbyssal = false | local isAbyssal = false | ||
local xp = 0 | local xp = 0 | ||
local qty = nil | local qty = 1 | ||
local | local costs = nil | ||
local chance = nil | |||
local | local tableData = {} | ||
local itemID = item.id | local itemID = item.id | ||
--First figure out what skill is used to make this... | --First figure out what skill is used to make this... | ||
Line 56: | Line 49: | ||
local skillIDs = { | local skillIDs = { | ||
['Gathering'] = { | ['Gathering'] = { | ||
['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' }, | ||
['Harvesting'] = { recipeKey = 'veinData' } | ['Harvesting'] = { recipeKey = 'veinData' } | ||
}, | }, | ||
Line 79: | Line 73: | ||
local skillData = SkillData[localSkillID] | local skillData = SkillData[localSkillID] | ||
local skill = skillData.name | local skill = skillData.name | ||
local lvl, isAbyssal, xp, qty, | local lvl, isAbyssal, xp, qty, source, costs, time, maxTime, chance = 0, false, 0, 1, nil, nil, 0, nil, nil | ||
for i, recipe in ipairs(skillData[dataProp.recipeKey]) do | for i, recipe in ipairs(skillData[dataProp.recipeKey]) do | ||
local hasProduct | local hasProduct = doesRecipeHaveItemID(recipe, itemID) | ||
if hasProduct then | if hasProduct then | ||
lvl, isAbyssal = Skills.getRecipeLevelRealm(localSkillID, recipe) | lvl, isAbyssal = Skills.getRecipeLevelRealm(localSkillID, recipe) | ||
xp = recipe.baseAbyssalExperience or recipe.baseExperience | xp = recipe.baseAbyssalExperience or recipe.baseExperience | ||
qty = recipe.baseQuantity or 1 | qty = recipe.baseQuantity or 1 | ||
source = Icons.Icon({ skill, type='skill', class=(isAbyssal and 'abyss-icon' or '') }) | |||
if localSkillID == 'Farming' then | if localSkillID == 'Farming' then | ||
costs = { recipe.seedCost } | |||
local catData = GameData.getEntityByID(skillData.categories, recipe.categoryID) | local catData = GameData.getEntityByID(skillData.categories, recipe.categoryID) | ||
qty = 5 * catData.harvestMultiplier | qty = 5 * catData.harvestMultiplier | ||
end | end | ||
Line 102: | Line 96: | ||
elseif skillData.baseInterval ~= nil then | elseif skillData.baseInterval ~= nil then | ||
time = skillData.baseInterval / 1000 | time = skillData.baseInterval / 1000 | ||
elseif localSkillID == 'Cartography' then | |||
time = 5 | |||
end | end | ||
if itemID == 'melvorF:Ash' then | -- Item chance and recipe costs | ||
qty = | if localSkillID == 'Firemaking' then | ||
local itemChanceData = GameData.getEntityByProperty(SkillData.Firemaking.primaryProducts, 'itemID', itemID) | |||
if itemChanceData ~= nil then | |||
chance = itemChanceData.chance .. '%' | |||
elseif itemID == 'melvorD:Generous_Fire_Spirit' then | |||
chance = '0.1%' | |||
end | |||
if Shared.contains({ 'melvorD:Generous_Fire_Spirit', 'melvorD:Coal_Ore', 'melvorTotH:Charcoal' }, itemID) then | |||
costs = 'Any ' .. Icons.Icon({ 'Firemaking', 'Melvor Logs', img='Melvor Logo', section='Melvor Logs' }) | |||
else | |||
local costItem = Items.getItemByID(recipe.logID) | |||
costs = Icons.Icon({ costItem.name, type='item', qty=1 }) | |||
end | |||
if itemID == 'melvorF:Ash' then | |||
qty = time | |||
elseif itemID == 'melvorItA:Withered_Ash' or itemID == 'melvorItA:Eternal_Ash' then | |||
qty = math.max(math.floor(recipe.abyssalLevel / 10), 1) | |||
end | |||
elseif localSkillID == 'Cartography' then | |||
local costItem = Items.getItemByID(recipe.costs.items[1].id) | |||
costs = Icons.Icon({ costItem.name, type='item', qty=1 }) | |||
elseif localSkillID == 'Harvesting' then | |||
local totalWeight = 0 | |||
local itemChanceData = nil | |||
for i, product in ipairs(recipe.products) do | |||
totalWeight = totalWeight + (product.weight or 0) | |||
if product.itemID == itemID then itemChanceData = product end | |||
end | |||
if itemChanceData ~= nil then | |||
chance = Num.round2((itemChanceData.weight / totalWeight * 100), 2) .. '%' | |||
specialReq = itemChanceData.minIntensityPercent .. '% ' .. Icons.Icon({ recipe.name, type='vein', notext=true }) .. ' Intensity' | |||
end | |||
end | end | ||
-- Special requirements | -- Special requirements | ||
if recipe.totalMasteryRequired ~= nil then | if recipe.totalMasteryRequired ~= nil then | ||
specialReq = Icons.Icon({'Mastery', notext=true}) .. Num.formatnum(recipe.totalMasteryRequired) .. ' total [[' .. skill .. ']] [[Mastery]]' | specialReq = Icons.Icon({ 'Mastery', notext=true }) .. ' ' .. Num.formatnum(recipe.totalMasteryRequired) .. ' total [[' .. skill .. ']] [[Mastery]]' | ||
end | end | ||
table.insert( | table.insert(tableData, { | ||
-- | ['skill'] = skill, | ||
break | ['lvl'] = lvl, | ||
['isAbyssal'] = isAbyssal, | |||
['xp'] = xp, | |||
['costs'] = costs, | |||
['qty'] = qty, | |||
['source'] = source, | |||
['time'] = time, | |||
['maxTime'] = maxTime, | |||
['specialReq'] = specialReq, | |||
['chance'] = chance | |||
}) | |||
-- Most recipes have a single item source or the item source data | |||
-- is nearly all the same. The following items have some uniqueness | |||
if not Shared.contains({ 'melvorF:Ash', 'melvorItA:Withered_Ash', 'melvorAoD:Paper' }, itemID) then break end | |||
end | end | ||
end | end | ||
Line 122: | Line 167: | ||
local skillData = SkillData[localSkillID] | local skillData = SkillData[localSkillID] | ||
local skill = skillData.name | local skill = skillData.name | ||
local lvl, isAbyssal, xp, qty, | local lvl, isAbyssal, xp, qty, source, costs, time, maxTime = 0, false, 0, 1, Icons.Icon({ skill, type='skill' }), nil, 0, 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 130: | Line 175: | ||
xp = recipe.baseAbyssalExperience or recipe.baseExperience | xp = recipe.baseAbyssalExperience or recipe.baseExperience | ||
qty = recipe.baseQuantity or 1 | qty = recipe.baseQuantity or 1 | ||
source = Icons.Icon({ skill, type='skill', class=(isAbyssal and 'abyss-icon' or '') }) | |||
-- Action time | -- Action time | ||
if recipe.baseMinInterval ~= nil then | if recipe.baseMinInterval ~= nil then | ||
Line 142: | Line 183: | ||
end | end | ||
elseif recipe.baseInterval ~= nil then | elseif recipe.baseInterval ~= nil then | ||
time = recipe.baseInterval /1000 | time = recipe.baseInterval / 1000 | ||
elseif skillData.baseInterval ~= nil then | elseif skillData.baseInterval ~= nil then | ||
time = skillData.baseInterval / 1000 | time = skillData.baseInterval / 1000 | ||
Line 152: | Line 193: | ||
if levelUnlock ~= nil then | if levelUnlock ~= nil then | ||
specialReq = Icons._MasteryReq(item.name, levelUnlock.level, false) | specialReq = Icons._MasteryReq(item.name, levelUnlock.level, false) | ||
end | |||
end | |||
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 | |||
specialReq = Icons.Icon({ 'Cooking', categoryName, section = 'Cooking Upgrades', img = categoryIconName, type = 'upgrade' }) | |||
end | end | ||
end | end | ||
Line 168: | Line 225: | ||
local shard = Items.getItemByID(itemCost.id) | local shard = Items.getItemByID(itemCost.id) | ||
if shard ~= nil then | if shard ~= nil then | ||
table.insert(shardCostArray, Icons.Icon({shard.name, type='item' | table.insert(shardCostArray, Icons.Icon({ shard.name, type='item', qty=itemCost.quantity })) | ||
end | end | ||
end | end | ||
-- Other costs | -- Other costs | ||
table.insert(otherCostArray, Common.getCostString({ ["items"] = {}, ["currencies"] = recipe.currencyCosts})) | table.insert(otherCostArray, Common.getCostString({ ["items"] = {}, ["currencies"] = recipe.currencyCosts })) | ||
for j, nonShardID in ipairs(recipe.nonShardItemCosts) do | for j, nonShardID in ipairs(recipe.nonShardItemCosts) do | ||
local nonShard = Items.getItemByID(nonShardID) | local nonShard = Items.getItemByID(nonShardID) | ||
Line 178: | Line 235: | ||
local itemValue = math.max(nonShard.sellsFor, 20) | local itemValue = math.max(nonShard.sellsFor, 20) | ||
local nonShardQty = math.max(1, math.ceil(recipeCost / itemValue)) | local nonShardQty = math.max(1, math.ceil(recipeCost / itemValue)) | ||
table.insert(otherCostArray, Icons.Icon({nonShard.name, type='item' | table.insert(otherCostArray, Icons.Icon({ nonShard.name, type='item', qty=nonShardQty })) | ||
end | end | ||
end | end | ||
costs = table.concat(shardCostArray, '<br>') | |||
if not Shared.tableIsEmpty(otherCostArray) then | if not Shared.tableIsEmpty(otherCostArray) then | ||
local costLen = Shared.tableCount(otherCostArray) | local costLen = Shared.tableCount(otherCostArray) | ||
costs = costs .. '<br>' .. (costLen == 1 and '' or 'and one of the following:<br>') .. table.concat(otherCostArray, "<br>'''OR''' ") | |||
end | end | ||
specialReq = 'At least 1 ' .. Icons.Icon({'Summoning%23Summoning Marks', item.name, img=item.name, type='mark'}) .. ' mark discovered' | specialReq = 'At least 1 ' .. Icons.Icon({ 'Summoning%23Summoning Marks', item.name, img=item.name, type='mark' }) .. ' mark discovered' | ||
table.insert( | table.insert(tableData, { | ||
['skill'] = skill, | |||
['lvl'] = lvl, | |||
['isAbyssal'] = isAbyssal, | |||
['xp'] = xp, | |||
['costs'] = costs, | |||
['qty'] = qty, | |||
['source'] = source, | |||
['time'] = time, | |||
['specialReq'] = specialReq | |||
}) | |||
-- Some items (such as Arrow shafts) have multiple recipes | -- Some items (such as Arrow shafts) have multiple recipes | ||
elseif type(recipe.alternativeCosts) == 'table' then | elseif type(recipe.alternativeCosts) == 'table' then | ||
local reqPart, qtyPart = {}, {} | local reqPart, qtyPart = {}, {} | ||
for j, altCost in ipairs(recipe.alternativeCosts) do | for j, altCost in ipairs(recipe.alternativeCosts) do | ||
local | local costsStr = '' | ||
for k, itemCost in ipairs(altCost.itemCosts) do | for k, itemCost in ipairs(altCost.itemCosts) do | ||
if k > 1 then costsStr = costsStr .. '<br>' end | |||
local reqItem = Items.getItemByID(itemCost.id) | local reqItem = Items.getItemByID(itemCost.id) | ||
if reqItem == nil then | if reqItem == nil then | ||
costsStr = costsStr .. itemCost.quantity .. 'x ?????' | |||
else | else | ||
costsStr = costsStr .. Icons.Icon({ reqItem.name, type='item', qty=itemCost.quantity }) | |||
end | end | ||
end | end | ||
costsStr = costsStr .. Common.getCostString({ ["items"] = {}, ["currencies"] = recipe.currencyCosts }, '') | |||
table.insert(tableData, { | |||
table.insert( | ['skill'] = skill, | ||
['lvl'] = lvl, | |||
['isAbyssal'] = isAbyssal, | |||
['xp'] = xp, | |||
['costs'] = costsStr, | |||
['qty'] = Num.formatnum(qty * altCost.quantityMultiplier), | |||
['source'] = Icons.Icon({ skill, type='skill' }), | |||
['time'] = time, | |||
['maxTime'] = maxTime, | |||
['specialReq'] = specialReq | |||
}) | |||
end | end | ||
-- 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 | ||
table.insert( | table.insert(tableData, { | ||
['skill'] = skill, | |||
['lvl'] = lvl, | |||
['isAbyssal'] = isAbyssal, | |||
['xp'] = xp, | |||
['costs'] = recipe.itemCosts, | |||
['qty'] = qty, | |||
['source'] = Icons.Icon({ skill, type='skill' }), | |||
['time'] = time, | |||
['maxTime'] = maxTime, | |||
['specialReq'] = specialReq, | |||
['currencyCost'] = recipe.currencyCosts | |||
}) | |||
end | end | ||
end | end | ||
Line 222: | Line 307: | ||
-- Gems are handled by _getItemLootSourceTable() | -- Gems are handled by _getItemLootSourceTable() | ||
for i, altSpell in ipairs(Magic.getSpellsBySpellBook('altMagic')) do | for i, altSpell in ipairs(Magic.getSpellsBySpellBook('altMagic')) do | ||
if altSpell.produces == | if altSpell.produces == itemID then | ||
table.insert( | table.insert(tableData, { | ||
['skill'] = 'Magic', | |||
['lvl'] = altSpell.level, | |||
['isAbyssal'] = false, | |||
['xp'] = altSpell.baseExperience, | |||
['costs'] = altSpell.runesRequired, | |||
['qty'] = altSpell.productionRatio, | |||
['source'] = Icons.Icon({ altSpell.name, type='spell' }), | |||
['time'] = 2, | |||
['altCosts'] = Magic._getAltSpellCostText(altSpell) | |||
}) | |||
end | end | ||
end | end | ||
if Shared. | -- Add in Astrology creation items manually since each constellation has (mostly) | ||
-- the same creation information so looping through them is not necessary | |||
local stardustChanceData = GameData.getEntityByProperty(SkillData.Astrology.baseRandomItemChances, 'itemID', itemID) | |||
if stardustChanceData ~= nil then | |||
local namespace, localID = Shared.getLocalID(stardustChanceData.itemID) | |||
local isAbyssal = namespace == 'melvorItA' | |||
table.insert(tableData, { | |||
['skill'] = 'Astrology', | |||
['lvl'] = 1, | |||
['isAbyssal'] = isAbyssal, | |||
['qty'] = qty, | |||
['xp'] = (isAbyssal and 1238 or 5), -- Use the (A)XP value for the first (abyssal) constellation | |||
['source'] = Icons.Icon({ 'Astrology', type='skill', class=(isAbyssal and 'abyss-icon' or '') }), | |||
['time'] = 3, | |||
['chance'] = stardustChanceData.chance .. '%' | |||
}) | |||
end | end | ||
if Shared.tableIsEmpty(tableData) then | |||
return '' | |||
return | |||
else | else | ||
return p. | return p.buildCreationTable(tableData, item) | ||
end | end | ||
end | end | ||
function p. | function p.buildCreationTable(tableData, item) | ||
local | local showSource = false | ||
local | local showRequirements = false | ||
local showInputs = false | |||
local showOutputs = false | |||
local showXP = false | |||
table | 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].skill ~= tableData[i].skill then | |||
showRequirements = true | |||
colspan = colspan + 1 | |||
end | |||
if not showInputs and tableData[1].costs ~= tableData[i].costs then | |||
showInputs = true | |||
colspan = colspan + 1 | |||
end | |||
if not showOutputs and tableData[1].qty ~= tableData[i].qty then | |||
showOutputs = true | |||
colspan = colspan + 1 | |||
end | |||
if not showXP and tableData[1].xp ~= tableData[i].xp then | |||
showXP = true | |||
colspan = colspan + 1 | |||
end | |||
if not showTime and tableData[1].time ~= tableData[i].time then | |||
showTime = true | |||
colspan = colspan + 1 | |||
end | |||
if not showChance and tableData[1].chance ~= tableData[i].chance then | |||
showChance = true | |||
colspan = colspan + 1 | |||
end | |||
end | end | ||
colspan = math.max(colspan, 1) | |||
local function addCostsRow(row, data, span) | |||
local costsRow = row:tag('td'):attr('colspan', span) | |||
if type(data.costs) == 'table' then | |||
for i, mat in ipairs(data.costs) do | |||
if i > 1 then costsRow:tag('br') end | |||
function | |||
if type( | |||
for i, mat in ipairs( | |||
if i > 1 then | |||
local matItem = Items.getItemByID(mat.id) | local matItem = Items.getItemByID(mat.id) | ||
if matItem == nil then | if matItem == nil then | ||
costsRow:wikitext(mat.quantity .. 'x ?????') | |||
else | else | ||
costsRow:wikitext(Icons.Icon({ matItem.name, type='item', qty=mat.quantity })) | |||
end | end | ||
end | end | ||
if currencyCost ~= nil then | if data.currencyCost ~= nil then | ||
costsRow:wikitext('<br>' .. Common.getCostString({ ["items"] = {}, ["currencies"] = data.currencyCost }, '')) | |||
end | end | ||
else | else | ||
table. | costsRow:wikitext(data.costs) | ||
end | |||
if data.altCosts ~= nil then | |||
costsRow:wikitext('<br>' .. data.altCosts:gsub(', ', '<br>')) | |||
end | |||
end | |||
local resultTable = mw.html.create('table') | |||
resultTable:addClass('wikitable') | |||
local tableHeader = resultTable:tag('tr') | |||
if showSource then tableHeader:tag('th'):wikitext('Source') end | |||
if showRequirements then tableHeader:tag('th'):wikitext('Requires') end | |||
if showInputs then tableHeader:tag('th'):wikitext('Inputs') end | |||
if showOutputs then tableHeader:tag('th'):wikitext('Outputs') end | |||
if showXP then tableHeader:tag('th'):wikitext('Exp') end | |||
if showTime then tableHeader:tag('th'):wikitext('Time') end | |||
if showChance then tableHeader:tag('th'):wikitext('Chance') end | |||
for i, data in ipairs(tableData) do | |||
local recipeRow = resultTable:tag('tr') | |||
if showSource then recipeRow:tag('td'):wikitext(data.source) end | |||
if showRequirements then | |||
local tableReqs = recipeRow:tag('td'):wikitext(Icons._SkillReq(data.skill, data.lvl, false, (data.isAbyssal and "melvorItA:Abyssal" or nil))) | |||
if data.specialReq ~= nil then | |||
recipeRow:tag('br'):wikitext(data.specialReq) | |||
end | |||
end | |||
if showInputs and data.costs ~= nil then | |||
addCostsRow(recipeRow, data, 1) | |||
elseif showInputs then | |||
recipeRow:tag('td'):wikitext('N/A'):addClass('table-na') | |||
end | |||
if showOutputs then recipeRow:tag('td'):wikitext(Icons.Icon({ item.name, type='item', notext=true, qty=data.qty })):addClass('center') end | |||
if showXP then | |||
recipeRow:tag('td') | |||
:wikitext(Icons.Icon({ data.skill, notext=true, type='skill', class=(data.isAbyssal and 'abyss-icon' or '') })) | |||
:wikitext(' ' .. Num.formatnum(data.xp) .. (data.isAbyssal and ' AXP' or ' XP')) | |||
end | |||
if showTime then recipeRow:tag('td'):wikitext(Shared.timeString(data.time, true)):addClass('center') end | |||
if showChance then recipeRow:tag('td'):wikitext((data.chance or '100%')):addClass('center') end | |||
end | |||
if not showSource and tableData[1].source ~= nil then | |||
resultTable:tag('tr') | |||
:tag('th'):wikitext('Source'):css('text-align', 'right') | |||
:tag('td'):attr('colspan', colspan):wikitext(tableData[1].source) | |||
end | |||
if not showRequirements and tableData[1].skill ~= nil and tableData[1].lvl ~= nil then | |||
local reqRow = resultTable:tag('tr') | |||
:tag('th'):wikitext('Requires'):css('text-align', 'right') | |||
local reqData = reqRow:tag('td'):attr('colspan', colspan) | |||
reqData:wikitext(Icons._SkillReq(tableData[1].skill, tableData[1].lvl, false, (tableData[1].isAbyssal and "melvorItA:Abyssal" or nil))) | |||
if tableData[1].specialReq ~= nil then | |||
reqData:wikitext('<br>' .. tableData[1].specialReq) | |||
end | |||
end | |||
if not showInputs and tableData[1].costs ~= nil then | |||
local costRow = resultTable:tag('tr') | |||
:tag('th'):wikitext('Inputs'):css('text-align', 'right') | |||
addCostsRow(costRow, tableData[1], colspan) | |||
end | |||
if not showOutputs and tableData[1].qty ~= nil then | |||
resultTable:tag('tr') | |||
:tag('th'):wikitext('Outputs'):css('text-align', 'right') | |||
:tag('td'):attr('colspan', colspan):wikitext(Icons.Icon({ item.name, type='item', qty=tableData[1].qty })) | |||
end | |||
if not showXP and tableData[1].xp ~= nil then | |||
resultTable:tag('tr') | |||
:tag('th'):wikitext('Base Exp'):css('text-align', 'right') | |||
:tag('td'):attr('colspan', colspan):wikitext(Num.formatnum(tableData[1].xp) .. (tableData[1].isAbyssal and ' AXP' or ' XP')) | |||
end | |||
if not showTime and tableData[1].time ~= nil then | |||
resultTable:tag('tr') | |||
local timeHeader = resultTable:tag('th'):wikitext('Base Time'):css('text-align', 'right') | |||
local timeData = timeHeader:tag('td'):attr('colspan', colspan) | |||
timeData:wikitext(Shared.timeString(tableData[1].time, true)) | |||
if tableData[1].maxTime ~= nil and tableData[1].maxTime > tableData[1].time then | |||
timeData:wikitext(' - ' .. Shared.timeString(tableData[1].maxTime, true)) | |||
end | end | ||
end | end | ||
if | if not showChance and tableData[1].chance ~= nil then | ||
resultTable:tag('tr') | |||
:tag('th'):wikitext('Base Chance'):css('text-align', 'right') | |||
:tag('td'):attr('colspan', colspan):wikitext(tableData[1].chance) | |||
end | end | ||
return | return tostring(resultTable) | ||
end | end | ||
Line 368: | Line 562: | ||
} | } | ||
for entity, dungeons in pairs(dungeonEntities) do | for entity, dungeons in pairs(dungeonEntities) do | ||
for i, dungeon in ipairs(dungeons) do | for i, dungeon in ipairs(dungeons) do | ||
if (dungeon.oneTimeRewardID ~= nil and item.id == dungeon.oneTimeRewardID) or | if (dungeon.oneTimeRewardID ~= nil and item.id == dungeon.oneTimeRewardID) or | ||
(type(dungeon.rewardItemIDs) == 'table' and Shared.contains(dungeon.rewardItemIDs, item.id)) then | (type(dungeon.rewardItemIDs) == 'table' and Shared.contains(dungeon.rewardItemIDs, item.id)) then | ||
table.insert(dungeonStrPart, Icons.Icon({dungeon.name, type= | table.insert(dungeonStrPart, Icons.Icon({dungeon.name, type='combatArea', notext=true})) | ||
elseif dungeon.eventID ~= nil then | elseif dungeon.eventID ~= nil then | ||
-- Is the item dropped from a combat event (e.g. Impending Darkness event)? | -- Is the item dropped from a combat event (e.g. Impending Darkness event)? | ||
Line 380: | Line 573: | ||
if item.id == itemRewardID then | if item.id == itemRewardID then | ||
local dungPrefix = (eventCycle == Shared.tableCount(event.itemRewardIDs) and '' or eventCycle .. (eventCycle == 1 and ' cycle' or ' cycles') .. ' of ') | local dungPrefix = (eventCycle == Shared.tableCount(event.itemRewardIDs) and '' or eventCycle .. (eventCycle == 1 and ' cycle' or ' cycles') .. ' of ') | ||
table.insert(dungeonStrPart, dungPrefix .. Icons.Icon({dungeon.name, type= | table.insert(dungeonStrPart, dungPrefix .. Icons.Icon({dungeon.name, type='combatArea', notext=true})) | ||
break | break | ||
end | end | ||
Line 707: | Line 900: | ||
-- Mining: Gems | -- Mining: Gems | ||
if (GameData.getEntityByProperty('randomGems', 'itemID', item.id) ~= nil or | if (GameData.getEntityByProperty('randomGems', 'itemID', item.id) ~= nil or | ||
GameData.getEntityByProperty('randomSuperiorGems', 'itemID', item.id) ~= nil) then | GameData.getEntityByProperty('randomSuperiorGems', 'itemID', item.id) ~= nil or | ||
GameData.getEntityByProperty('randomAbyssalGems', 'itemID', item.id) ~= nil) then | |||
table.insert(lineArray, Icons.Icon({"Mining", type='skill', notext=true})..' [[Mining#Gems|Gem]]') | table.insert(lineArray, Icons.Icon({"Mining", type='skill', notext=true})..' [[Mining#Gems|Gem]]') | ||
elseif item.id == SkillData.Mining.runestoneItemID then | elseif item.id == SkillData.Mining.runestoneItemID then | ||
Line 743: | Line 937: | ||
elseif rareDrop.itemID == 'melvorD:Mysterious_Stone' then | elseif rareDrop.itemID == 'melvorD:Mysterious_Stone' then | ||
local foundItem = Items.getItemByID('melvorD:Crown_of_Rhaelyx') | local foundItem = Items.getItemByID('melvorD:Crown_of_Rhaelyx') | ||
subText = '<br | subText = '<br>after finding ' .. Icons.Icon({foundItem.name, type='item'}) | ||
end | end | ||
if type(rareDrop.gamemodes) == 'table' then | if type(rareDrop.gamemodes) == 'table' then | ||
Line 825: | Line 1,019: | ||
table.insert(resultPart, '* '..table.concat(lineArray, "\r\n* ")) | table.insert(resultPart, '* '..table.concat(lineArray, "\r\n* ")) | ||
else | else | ||
table.insert(resultPart, '<div style="max-width:180px;text-align:right">' .. table.concat(lineArray, "<br | table.insert(resultPart, '<div style="max-width:180px;text-align:right">' .. table.concat(lineArray, "<br>") .. '</div>') | ||
end | end | ||
if addCategories then table.insert(resultPart, table.concat(categoryArray, '')) end | if addCategories then table.insert(resultPart, table.concat(categoryArray, '')) end | ||
Line 944: | Line 1,138: | ||
} | } | ||
for entity, dungeons in pairs(dungeonEntities) do | for entity, dungeons in pairs(dungeonEntities) do | ||
for i, dungeon in ipairs(dungeons) do | for i, dungeon in ipairs(dungeons) do | ||
if (dungeon.oneTimeRewardID ~= nil and item.id == dungeon.oneTimeRewardID) or | if (dungeon.oneTimeRewardID ~= nil and item.id == dungeon.oneTimeRewardID) or | ||
(type(dungeon.rewardItemIDs) == 'table' and Shared.contains(dungeon.rewardItemIDs, item.id)) then | (type(dungeon.rewardItemIDs) == 'table' and Shared.contains(dungeon.rewardItemIDs, item.id)) then | ||
table.insert(dropRows, { | table.insert(dropRows, { | ||
source = Icons.Icon({dungeon.name, type= | source = Icons.Icon({dungeon.name, type='combatArea'}), | ||
level = '[['..entity..']]', | level = '[['..entity..']]', | ||
minqty = 1, | minqty = 1, | ||
Line 962: | Line 1,155: | ||
for eventCycle, itemRewardID in ipairs(event.itemRewardIDs) do | for eventCycle, itemRewardID in ipairs(event.itemRewardIDs) do | ||
if item.id == itemRewardID then | if item.id == itemRewardID then | ||
local sourceTxt = Icons.Icon({dungeon.name, type= | local sourceTxt = Icons.Icon({dungeon.name, type='combatArea'}) .. (eventCycle == Shared.tableCount(event.itemRewardIDs) and '' or ', Cycle ' .. eventCycle) | ||
table.insert(dropRows, { | table.insert(dropRows, { | ||
source = sourceTxt, | source = sourceTxt, | ||
Line 1,085: | Line 1,278: | ||
-- Mining: Gems, and also Alt. Magic spells producing random gems | -- Mining: Gems, and also Alt. Magic spells producing random gems | ||
if Shared.contains({'Gem', 'Superior Gem'}, item.type) then | if Shared.contains({'Gem', 'Superior Gem', 'Abyssal Gem'}, item.type) then | ||
local gemKeys = { 'randomGems', 'randomSuperiorGems' } | local gemKeys = { 'randomGems', 'randomSuperiorGems', 'randomAbyssalGems' } | ||
for i, gemKey in ipairs(gemKeys) do | for i, gemKey in ipairs(gemKeys) do | ||
local thisGem, totalGemWeight = nil, 0 | local thisGem, totalGemWeight = nil, 0 | ||
Line 1,120: | Line 1,313: | ||
-- Check for Alt. Magic spells also | -- Check for Alt. Magic spells also | ||
local producesKey = (gemKey == 'randomGems' and 'RandomGem') or 'RandomSuperiorGem' | local producesKey = (gemKey == 'randomGems' and 'RandomGem') or (gemKey == 'randomSuperiorGems' and 'RandomSuperiorGem') or nil | ||
for j, spell in ipairs(Magic.getSpellsBySpellBook('altMagic')) do | if producesKey ~= nil then | ||
for j, spell in ipairs(Magic.getSpellsBySpellBook('altMagic')) do | |||
if spell.produces ~= nil and spell.produces == producesKey then | |||
table.insert(dropRows, { | |||
source = Icons.Icon({spell.name, type=Magic._getSpellIconType(spell)}), | |||
level = Icons.Icon({'Alternative Magic', type='skill', img='Magic', notext=true}) .. ' Level ' .. spell.level, | |||
levelNum = spell.level, | |||
minqty = thisGem.minQuantity, | |||
qty = thisGem.maxQuantity, | |||
weight = thisGem.weight, | |||
totalWeight = totalGemWeight, | |||
expIcon = Icons.getExpansionIcon(spell.id)}) | |||
end | |||
end | end | ||
end | end | ||
Line 1,455: | Line 1,650: | ||
"Signet Ring Half (a)", | "Signet Ring Half (a)", | ||
"Signet Ring Half (b)", | "Signet Ring Half (b)", | ||
"Astrology Lesser Relic", | "Astrology Lesser Relic", | ||
"Mysterious Stone", | "Mysterious Stone", | ||
"Gold Topaz Ring", | |||
"Charcoal", | |||
"Ash", | |||
"Coal Ore", | |||
"Rune Essence", | |||
"Gold Bar", | "Gold Bar", | ||
"Rune Platebody", | "Rune Platebody", | ||
"Arrow Shafts", | "Arrow Shafts", | ||
Line 1,466: | Line 1,663: | ||
"Water Rune", | "Water Rune", | ||
"Steam Rune", | "Steam Rune", | ||
"Wolf", | "Wolf", | ||
" | "Fox", | ||
"Leprechaun", | "Leprechaun", | ||
"Void Wisp", | |||
"Redwood Logs", | "Redwood Logs", | ||
"Shadow Raven Nest", | |||
"Raw Shrimp", | |||
"Shrimp", | |||
"Carrot Cake", | "Carrot Cake", | ||
"Carrot Cake (Perfect)", | "Carrot Cake (Perfect)", | ||
"Mantalyme Herb", | "Mantalyme Herb", | ||
"Carrot", | "Carrot", | ||
"Controlled Heat Potion II", | |||
"Topaz", | "Topaz", | ||
" | "Oricha", | ||
"Nightopal", | |||
"Sanguine Blade", | "Sanguine Blade", | ||
"Ring of Power", | "Ring of Power", | ||
Line 1,482: | Line 1,684: | ||
"Chapeau Noir", | "Chapeau Noir", | ||
"Stardust", | "Stardust", | ||
"Golden Stardust", | |||
"Abyssal Stardust", | |||
"Rope", | "Rope", | ||
"Ancient Ring of Mastery", | "Ancient Ring of Mastery", | ||
Line 1,487: | Line 1,691: | ||
"Gem Gloves", | "Gem Gloves", | ||
"Thief's Moneysack", | "Thief's Moneysack", | ||
"Golden Star", | "Golden Star", | ||
"Slayer Deterer", | "Slayer Deterer", | ||
Line 1,494: | Line 1,697: | ||
"Aranite Brush", | "Aranite Brush", | ||
"Barrier Dust", | "Barrier Dust", | ||
" | "Obsidian Tendril", | ||
" | "Obsidian Bark", | ||
"Obsidian Thorn", | |||
"Obsidian Vein Seed", | |||
"Elite Chest", | |||
} | } | ||
local checkFuncs = { | local checkFuncs = { | ||
--p.getItemSourceTables, | --p.getItemSourceTables, | ||
p.getCreationTable, | |||
--p.getItemSources, | --p.getItemSources, | ||
--p.getItemLootSourceTable, | --p.getItemLootSourceTable, |