Anonymous

Module:Items/SourceTables/Sandbox: Difference between revisions

From Melvor Idle
Add Harvesting item chance data; Change common FM products' input to 'Any Melvor Logs' instead of '1 Normal Logs'; Cleanup some stuff
m (Clean up chance data)
(Add Harvesting item chance data; Change common FM products' input to 'Any Melvor Logs' instead of '1 Normal Logs'; Cleanup some stuff)
Line 29: Line 29:
'Rune Essence', -- Multi source (Category, Time, XP, Qty, Runes)
'Rune Essence', -- Multi source (Category, Time, XP, Qty, Runes)
'Coal Ore',  -- Multi source (Same Qty, everything else is different)
'Coal Ore',  -- Multi source (Same Qty, everything else is different)
'Charcoal',
'Ash', -- Requires a fix in _getCreationTable
'Ash', -- Requires a fix in _getCreationTable
'Withered Ash', -- Requires a fix in _getCreationTable
'Withered Ash', -- Requires a fix in _getCreationTable
'Eternal Ash',
'Generous Fire Spirit',
'Generous Fire Spirit',
-- "Circlet of Rhaelyx", -- The following commented out items have no creation source data; This may appear later
-- "Circlet of Rhaelyx", -- The following commented out items have no creation source data; This may appear later
Line 76: Line 78:
"Barrier Dust",
"Barrier Dust",
-- "Shadow Raven Nest",
-- "Shadow Raven Nest",
'Obsidian Vein Seed'
'Obsidian Tendril',
'Obsidian Bark',
'Obsidian Thorn',
'Obsidian Vein Seed',
}
}


Line 87: Line 92:
local function doesRecipeHaveItemID(recipe, itemID)
local function doesRecipeHaveItemID(recipe, itemID)
if recipe.productId == itemID then
if recipe.productId == itemID then
return true, nil
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, nil
return true
elseif type(recipe.products) == 'table' then
elseif type(recipe.products) == 'table' then
for i, product in ipairs(recipe.products) do
return GameData.getEntityByProperty(recipe.products, 'itemID', itemID) ~= nil
if product.itemID == itemID then
local specialReq = nil
if recipe.products[i].minIntensityPercent ~= nil then
specialReq = recipe.products[i].minIntensityPercent .. '% Intensity'
end
return true, specialReq
end
end
end
end
return false, nil
return false
end
end


Line 149: Line 146:
local lvl, isAbyssal, xp, qty, source, costs, time, maxTime, chance = 0, false, 0, 0, nil, nil, 0, nil, nil
local lvl, isAbyssal, xp, qty, source, costs, time, maxTime, chance = 0, false, 0, 0, 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, specialReq = doesRecipeHaveItemID(recipe, itemID)
local hasProduct = doesRecipeHaveItemID(recipe, itemID)
if hasProduct then
if hasProduct then
lvl, isAbyssal = Skills.getRecipeLevelRealm(localSkillID, recipe)
lvl, isAbyssal = Skills.getRecipeLevelRealm(localSkillID, recipe)
Line 182: Line 179:
end
end


local costItem = Items.getItemByID(recipe.logID)
if Shared.contains({ 'melvorD:Generous_Fire_Spirit', 'melvorD:Coal_Ore', 'melvorTotH:Charcoal' }, itemID) then
costs = Icons.Icon({costItem.name, type='item', qty=1})
costs = 'Any {{Icon|Woodcutting|Melvor Logs|img=Melvor Realm|ext=svg|section=Logs}}'
else
local costItem = Items.getItemByID(recipe.logID)
costs = Icons.Icon({ costItem.name, type='item', qty=1 })
end


if itemID == 'melvorF:Ash' then
if itemID == 'melvorF:Ash' then
qty = time
qty = time
elseif itemID == 'melvorItA:Withered_Ash' then
elseif itemID == 'melvorItA:Withered_Ash' or itemID == 'melvorItA:Eternal_Ash' then
qty = math.max(math.floor(recipe.abyssalLevel / 10), 1)
qty = math.max(math.floor(recipe.abyssalLevel / 10), 1)
end
end
elseif localSkillID == 'Cartography' then
elseif localSkillID == 'Cartography' then
local costItem = Items.getItemByID(recipe.costs.items[1].id)
local costItem = Items.getItemByID(recipe.costs.items[1].id)
costs = Icons.Icon({costItem.name, type='item', qty=1})
costs = Icons.Icon({ costItem.name, type='item', qty=1 })
elseif itemID == 'melvorD:Coal_Ore' then
elseif localSkillID == 'Harvesting' then
chance = '100%'
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(tableData, {
table.insert(tableData, {
Line 215: Line 228:
-- Most recipes have a single item source or the item source data
-- Most recipes have a single item source or the item source data
-- is nearly all the same. The following items have some uniqueness
-- 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
if not Shared.contains({ 'melvorF:Ash', 'melvorItA:Withered_Ash', 'melvorAoD:Paper' }, itemID) then break end
end
end
end
end
Line 283: Line 296:
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', qty=itemCost.quantity}))
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 293: Line 306:
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', qty=nonShardQty}))
table.insert(otherCostArray, Icons.Icon({ nonShard.name, type='item', qty=nonShardQty }))
end
end
end
end
Line 301: Line 314:
costs = costs .. '<br>' .. (costLen == 1 and '' or 'and one of the following:<br>') .. table.concat(otherCostArray, "<br>'''OR''' ")
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(tableData, {
table.insert(tableData, {
['skill'] = skill,
['skill'] = skill,
Line 311: Line 324:
['source'] = source,
['source'] = source,
['time'] = time,
['time'] = time,
['maxTime'] = nil,
['specialReq'] = specialReq
['specialReq'] = specialReq
})
})
Line 325: Line 337:
costsStr = costsStr .. itemCost.quantity .. 'x ?????'
costsStr = costsStr .. itemCost.quantity .. 'x ?????'
else
else
costsStr = costsStr .. Icons.Icon({reqItem.name, type='item', qty=itemCost.quantity})
costsStr = costsStr .. Icons.Icon({ reqItem.name, type='item', qty=itemCost.quantity })
end
end
end
end
costsStr = costsStr .. (Common.getCostString({ ["items"] = {}, ["currencies"] = recipe.currencyCosts}) or '')
costsStr = costsStr .. (Common.getCostString({ ["items"] = {}, ["currencies"] = recipe.currencyCosts }) or '')
table.insert(tableData, {
table.insert(tableData, {
['skill'] = skill,
['skill'] = skill,
Line 376: Line 388:
['source'] = Icons.Icon({ altSpell.name, type='spell' }),
['source'] = Icons.Icon({ altSpell.name, type='spell' }),
['time'] = 2,
['time'] = 2,
['maxTime'] = 2,
['altCosts'] = Magic._getAltSpellCostText(altSpell)
['altCosts'] = Magic._getAltSpellCostText(altSpell)
})
})
Line 388: Line 399:
local namespace, localID = Shared.getLocalID(stardustChanceData.itemID)
local namespace, localID = Shared.getLocalID(stardustChanceData.itemID)
local isAbyssal = namespace == 'melvorItA'
local isAbyssal = namespace == 'melvorItA'
local chance = nil
table.insert(tableData, {
table.insert(tableData, {
['skill'] = 'Astrology',
['skill'] = 'Astrology',
['lvl'] = 1,
['lvl'] = 1,
['isAbyssal'] = isAbyssal,
['isAbyssal'] = isAbyssal,
['xp'] = (isAbyssal and 1238 or 5),
['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 '')}),
['source'] = Icons.Icon({ 'Astrology', type='skill', class=(isAbyssal and 'abyss-icon' or '')}),
['time'] = 3,
['time'] = 3,
Line 403: Line 413:
return ''
return ''
else
else
return p.buildCreationTable2(tableData, item)
return p.buildCreationTable(tableData, item)
end
end
end
end


function p.getAltMagicTable(frame)
function p.buildCreationTable(tableData, item)
local spellName = frame.args ~= nil and frame.args[1] or frame
local spell = Magic.getSpell(spellName, 'altMagic')
if spell == nil then
return Shared.printError('Could not find Alt. Magic spell "' .. spellName .. '"')
else
return p._buildAltMagicTable(spell)
end
end
 
function p._buildAltMagicTable(spell)
local resultPart = {}
local imgType = Magic._getSpellIconType(spell)
table.insert(resultPart, '{|class="wikitable"\r\n|-')
table.insert(resultPart, '\r\n!colspan="2"|'..Icons.Icon({spell.name, type=imgType}))
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Requirements')
table.insert(resultPart, '\r\n|'..Icons._SkillReq('Magic', spell.level))
 
local costText = Magic._getAltSpellCostText(spell)
if costText ~= nil then
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Materials')
table.insert(resultPart, '\r\n| ' .. costText)
end
 
--Add runes
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Runes\r\n| ' .. Magic._getSpellRunes(spell))
 
--Now just need the output quantity, xp, and casting time (which is always 2)
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Quantity\r\n|' .. spell.productionRatio)
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base XP\r\n|' .. spell.baseExperience)
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Cast Time\r\n|2s')
table.insert(resultPart, '\r\n|}')
return table.concat(resultPart)
end
 
function p.buildCreationTable2(tableData, item)
local showSource = false
local showSource = false
local showRequirements = false
local showRequirements = false
Line 450: Line 425:
local showTime = false
local showTime = false
local showChance = false
local showChance = false
local colspan = -1
local colspan = -1 -- colspan only needs to be set when there are 3+ columns in the table


for i, data in ipairs(tableData) do
for i, data in ipairs(tableData) do
Line 483: Line 458:
end
end


local function addCostsRow(row, data, colspan)
colspan = math.max(colspan, 1)
local costsRow = row:tag('td'):attr('colspan', (colspan >= 2 and colspan or 1))
 
local function addCostsRow(row, data, span)
local costsRow = row:tag('td'):attr('colspan', span)
if type(data.costs) == 'table' then
if type(data.costs) == 'table' then
for i, mat in ipairs(data.costs) do
for i, mat in ipairs(data.costs) do
Line 544: Line 521:
if showXP then recipeRow:tag('td'):wikitext(Icons.Icon({data.skill, (Num.formatnum(data.xp) .. (data.isAbyssal and ' AXP' or ' XP')), nolink=true, type='skill'})) end
if showXP then recipeRow:tag('td'):wikitext(Icons.Icon({data.skill, (Num.formatnum(data.xp) .. (data.isAbyssal and ' AXP' or ' XP')), nolink=true, type='skill'})) end
if showTime then recipeRow:tag('td'):wikitext(Shared.timeString(data.time, true)):addClass('center') 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):addClass('center') end
if showChance then recipeRow:tag('td'):wikitext((data.chance or '100%')):addClass('center') end
end
end


Line 552: Line 529:
:wikitext('Source')
:wikitext('Source')
:css('text-align', 'right')
:css('text-align', 'right')
:tag('td'):attr('colspan', (colspan >= 2 and colspan or 1)):wikitext(tableData[1].source)
:tag('td'):attr('colspan', colspan):wikitext(tableData[1].source)
end
end
if not showRequirements and tableData[1].skill ~= nil and tableData[1].lvl ~= nil then
if not showRequirements and tableData[1].skill ~= nil and tableData[1].lvl ~= nil then
Line 559: Line 536:
:wikitext('Requires')
:wikitext('Requires')
:css('text-align', 'right')
:css('text-align', 'right')
local reqData = reqRow:tag('td'):attr('colspan', (colspan >= 2 and colspan or 1))
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)))
reqData:wikitext(Icons._SkillReq(tableData[1].skill, tableData[1].lvl, false, (tableData[1].isAbyssal and "melvorItA:Abyssal" or nil)))


Line 579: Line 556:
:wikitext('Outputs')
:wikitext('Outputs')
:css('text-align', 'right')
:css('text-align', 'right')
:tag('td'):attr('colspan', (colspan >= 2 and colspan or 1)):wikitext(Icons.Icon({ item.name, type='item', qty=tableData[1].qty }))
:tag('td'):attr('colspan', colspan):wikitext(Icons.Icon({ item.name, type='item', qty=tableData[1].qty }))
end
end
if not showXP and tableData[1].xp ~= nil then
if not showXP and tableData[1].xp ~= nil then
Line 586: Line 563:
:wikitext('Base Exp')
:wikitext('Base Exp')
:css('text-align', 'right')
:css('text-align', 'right')
:tag('td'):attr('colspan', (colspan >= 2 and colspan or 1)):wikitext(Num.formatnum(tableData[1].xp) .. (tableData[1].isAbyssal and ' AXP' or ' XP'))
:tag('td'):attr('colspan', colspan):wikitext(Num.formatnum(tableData[1].xp) .. (tableData[1].isAbyssal and ' AXP' or ' XP'))
end
end
if not showTime and tableData[1].time ~= nil then
if not showTime and tableData[1].time ~= nil then
Line 595: Line 572:
:css('text-align', 'right')
:css('text-align', 'right')


local timeData = timeHeader:tag('td'):attr('colspan', (colspan >= 2 and colspan or 1))
local timeData = timeHeader:tag('td'):attr('colspan', colspan)
timeData:wikitext(Shared.timeString(tableData[1].time, true))
timeData:wikitext(Shared.timeString(tableData[1].time, true))


Line 607: Line 584:
:wikitext('Base Chance')
:wikitext('Base Chance')
:css('text-align', 'right')
:css('text-align', 'right')
:tag('td'):attr('colspan', (colspan >= 2 and colspan or 1)):wikitext(tableData[1].chance)
:tag('td'):attr('colspan', colspan):wikitext(tableData[1].chance)
end
end


return '==' .. item.name .. '==\n' .. tostring(resultTable) -- TODO: Remove item.name header
return '==' .. item.name .. '==\n' .. tostring(resultTable) -- TODO: Remove item.name header
end
function p.buildCreationTable(skill, lvl, isAbyssal, xp, req, qty, category, time, maxTime, specialReq, currencyCost)
if qty == nil then qty = 1 end
local resultPart = {}
table.insert(resultPart, '{|class="wikitable"')
table.insert(resultPart, '\r\n!colspan="2"|Item ' .. (req == nil and 'Creation' or 'Production'))
table.insert(resultPart, '\r\n|-\r\n!style="text-align: right;"|Requirements')
table.insert(resultPart, '\r\n|'..Icons._SkillReq(skill, lvl, false, (isAbyssal and "melvorItA:Abyssal" or nil)))
if specialReq ~= nil then table.insert(resultPart, '<br>'..specialReq) end
if req ~= nil then
table.insert(resultPart, '\r\n|-\r\n!style="text-align: right;"|Materials\r\n|')
if type(req) == 'table' then
for i, mat in ipairs(req) do
if i > 1 then table.insert(resultPart, '<br>') end
local matItem = Items.getItemByID(mat.id)
if matItem == nil then
table.insert(resultPart, mat.quantity..'x ?????')
else
table.insert(resultPart, Icons.Icon({matItem.name, type='item', qty=mat.quantity}))
end
end
if currencyCost ~= nil then
table.insert(resultPart, Common.getCostString({ ["items"] = {}, ["currencies"] = currencyCost }))
end
else
table.insert(resultPart, req)
end
end
if category ~= nil then
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Recipe Category')
table.insert(resultPart, '\r\n|'..category)
end
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Quantity')
table.insert(resultPart, '\r\n|'..qty)
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Experience')
table.insert(resultPart, '\r\n|'..Num.formatnum(xp)..' XP')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Creation Time')
table.insert(resultPart, '\r\n|'..Shared.timeString(time, true))
if maxTime ~= nil and maxTime > time then table.insert(resultPart, ' - '..Shared.timeString(maxTime, true)) end
table.insert(resultPart, '\r\n|}')
return table.concat(resultPart)
end
end