Anonymous

Module:Items/SourceTables/Sandbox: Difference between revisions

From Melvor Idle
Initial commit for overhauled Creation Tables (Status: Incomplete)
mNo edit summary
(Initial commit for overhauled Creation Tables (Status: Incomplete))
Line 18: Line 18:
['melvorAoD:EarthGolem'] = 'Earth Golem (AoD)'
['melvorAoD:EarthGolem'] = 'Earth Golem (AoD)'
}
}
function p.testCreationTables()
-- TODO:
-- Fix TODOs throughout file then remove this test function
-- (Major) Either add all the data from _getItemSourceTables into a single table or convert those over to a similar style table as well
-- If a single table is used, a new header will need to be added (maybe?); Could use 'Category'/'Source'
-- Consider adding more skills into the sources; Stardust has a single source from Firemaking
-- Add the recipe as the category, such as 'Mithril Rock' for Mithril Ore
-- Ash and Withered Ash is showing a single source (Needs a fix in _getCreationTable)
-- Add chance data in _getCreationTable (Ex: Ash, Withered Ash, Stardust from FM)
-- If a table has a rowspan of 3 to (maxRows - 1) then the "Global" information needs to have the rowspan attribute (See Coal Ore's Base Quantity)
-- Should Skill XP be Value - Skill Icon - 'XP' or Skill Icon - Value - 'XP' ?
local tables = {}
local checkItems = {
'Dragonite Ore', -- Single source; This should have no change from the live version
'Arrow Shafts', -- Multi source (Costs, Qty)
'Rune Essence', -- Multi source (Category, Time, XP, Qty, Runes)
'Coal Ore',  -- Multi source (Same Qty, everything else is different)
'Ash', -- Requires a fix in _getCreationTable
'Withered Ash', -- Requires a fix in _getCreationTable
-- "Circlet of Rhaelyx", -- The following commented out items have no creation source data; This may appear later
-- "Jewel of Rhaelyx",
-- "Signet Ring Half (a)",
-- "Signet Ring Half (b)",
"Gold Topaz Ring",
-- "Astrology Lesser Relic",
-- "Mysterious Stone",
"Gold Bar",
"Raw Shrimp",
"Coal Ore",
"Rune Platebody",
"Yew Longbow",
"Water Rune",
"Steam Rune",
"Controlled Heat Potion II",
"Wolf", -- Melvor Tablet with multiple recipe costs
"Fox", -- Has a base shard cost and multi recipe cost that is also shards
"Leprechaun", -- Has a currency
"Void Wisp", -- Abyssal Tablet with a single recipe
"Redwood Logs",
"Carrot Cake",
"Carrot Cake (Perfect)",
"Mantalyme Herb",
"Carrot",
-- "Topaz",
-- "Sanguine Blade",
-- "Ring of Power",
-- "Infernal Claw",
-- "Chapeau Noir",
"Stardust",
-- "Rope",
-- "Ancient Ring of Mastery",
-- "Mastery Token (Cooking)",
-- "Gem Gloves",
"Thief's Moneysack",
-- "Golden Stardust",
-- "Golden Star",
-- "Slayer Deterer",
-- "Paper",
-- "Lemon",
-- "Aranite Brush",
"Barrier Dust",
-- "Shadow Raven Nest",
'Obsidian Vein Seed'
}
for i, itemID in ipairs(checkItems) do
table.insert(tables, p._getCreationTable(Items.getItem(itemID)))
end
return table.concat(tables, '\n')
end


local function doesRecipeHaveItemID(recipe, itemID)
local function doesRecipeHaveItemID(recipe, itemID)
Line 48: Line 119:
local xp = 0
local xp = 0
local qty = nil
local qty = nil
local req = nil
local costs = nil


local tables = {}
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 79: Line 150:
local skillData = SkillData[localSkillID]
local skillData = SkillData[localSkillID]
local skill = skillData.name
local skill = skillData.name
local lvl, isAbyssal, xp, qty, req, category, time, maxTime = 0, false, 0, 0, nil, nil, 0, nil
local lvl, isAbyssal, xp, qty, costs, category, time, maxTime = 0, false, 0, 0, nil, nil, 0, 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, specialReq = doesRecipeHaveItemID(recipe, itemID)
Line 87: Line 158:
qty = recipe.baseQuantity or 1
qty = recipe.baseQuantity or 1
if localSkillID == 'Farming' then
if localSkillID == 'Farming' then
req = { recipe.seedCost }
costs = { recipe.seedCost }
local catData = GameData.getEntityByID(skillData.categories, recipe.categoryID)
local catData = GameData.getEntityByID(skillData.categories, recipe.categoryID)
category = catData.name
category = catData.name
Line 110: Line 181:
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(tables, p.buildCreationTable(skill, lvl, isAbyssal, xp, req, qty, category, time, maxTime, specialReq))
table.insert(tableData, { ['skill'] = skill, ['lvl'] = lvl, ['isAbyssal'] = isAbyssal, ['xp'] = xp, ['costs'] = costs, ['qty'] = qty, ['category'] = category, ['time'] = time, ['maxTime'] = maxTime, ['specialReq'] = specialReq })
-- Assumes item has a single source per skill
-- Assumes item has a single source per skill
break
break
Line 168: Line 239:
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', notext=true, qty=itemCost.quantity}))
table.insert(shardCostArray, Icons.Icon({shard.name, type='item', qty=itemCost.quantity}))
end
end
end
end
Line 178: Line 249:
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', notext=true, qty=nonShardQty}))
table.insert(otherCostArray, Icons.Icon({nonShard.name, type='item', qty=nonShardQty}))
end
end
end
end
req = table.concat(shardCostArray, ', ')
req = 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)
req = req .. '<br/>' .. (costLen == 1 and '' or 'and one of the following:<br/>') .. table.concat(otherCostArray, "<br/>'''OR''' ")
req = req .. '<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(tables, p.buildCreationTable(skill, lvl, isAbyssal, xp, req, qty, category, time, nil, specialReq))
table.insert(tableData, { ['skill'] = skill, ['lvl'] = lvl, ['isAbyssal'] = isAbyssal, ['xp'] = xp, ['costs'] = req, ['qty'] = qty, ['category'] = category, ['time'] = time, ['maxTime'] = nil, ['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 reqSubPart = {}
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
table.insert(reqSubPart, itemCost.quantity .. 'x ?????')
costsStr = costsStr .. itemCost.quantity .. 'x ?????'
else
else
table.insert(reqSubPart, 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 '')
table.insert(reqSubPart, Common.getCostString({ ["items"] = {}, ["currencies"] = recipe.currencyCosts}))
table.insert(tableData, { ['skill'] = skill, ['lvl'] = lvl, ['isAbyssal'] = isAbyssal, ['xp'] = xp, ['costs'] = costsStr, ['qty'] = Num.formatnum(qty * altCost.quantityMultiplier), ['category'] = category, ['time'] = time, ['maxTime'] = maxTime, ['specialReq'] = specialReq })
table.insert(reqPart, table.concat(reqSubPart, ', '))
table.insert(qtyPart, Num.formatnum(qty * altCost.quantityMultiplier))
end
end
local sep = "<br/>'''OR''' "
req = table.concat(reqPart, sep)
local qtyText = table.concat(qtyPart, sep)
table.insert(tables, p.buildCreationTable(skill, lvl, isAbyssal, xp, req, qtyText, category, time, maxTime, specialReq))
-- 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(tables, p.buildCreationTable(skill, lvl, isAbyssal, xp, recipe.itemCosts, qty, category, time, maxTime, specialReq, recipe.currencyCosts))
table.insert(tableData, { ['skill'] = skill, ['lvl'] = lvl, ['isAbyssal'] = isAbyssal, ['xp'] = xp, ['costs'] = recipe.itemCosts, ['qty'] = qty, ['category'] = category, ['time'] = time, ['maxTime'] = maxTime, ['specialReq'] = specialReq, ['currencyCost'] = recipe.currencyCosts })
end
end
end
end
Line 223: Line 289:
for i, altSpell in ipairs(Magic.getSpellsBySpellBook('altMagic')) do
for i, altSpell in ipairs(Magic.getSpellsBySpellBook('altMagic')) do
if altSpell.produces == item.id then
if altSpell.produces == item.id then
table.insert(tables, p._buildAltMagicTable(altSpell))
table.insert(tableData, { ['skill'] = 'Magic', ['lvl'] = altSpell.level, ['isAbyssal'] = false, ['xp'] = altSpell.baseExperience, ['costs'] = altSpell.runesRequired, ['qty'] = altSpell.productionRatio, ['category'] = altSpell.name, ['time'] = 2, ['maxTime'] = 2, ['altCosts'] = Magic._getAltSpellCostText(altSpell) })
end
end
end
end


if Shared.tableIsEmpty(tables) then
if Shared.tableIsEmpty(tableData) then
return ''
return ''
else
else
return table.concat(tables, '\r\n')
return p.buildCreationTable2(tableData, item)
end
end
end
end
Line 267: Line 333:
table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')
return table.concat(resultPart)
return table.concat(resultPart)
end
function p.buildCreationTable2(tableData, item)
local showCategory = false
local showRequirements = false
local showInputs = false
local showOutputs = false
local showXP = false
local showTime = false
local showChance = false
for i, data in ipairs(tableData) do
if not showCategory and tableData[1].category ~= tableData[i].category then showCategory = true end
if not showRequirements and tableData[1].skill ~= tableData[i].skill then showRequirements = true end
if not showInputs and tableData[1].costs ~= tableData[i].costs then showInputs = true end
if not showOutputs and tableData[1].qty ~= tableData[i].qty then showOutputs = true end
if not showXP and tableData[1].xp ~= tableData[i].xp then showXP = true end
if not showTime and tableData[1].time ~= tableData[i].time then showTime = true end
if not showChance and tableData[1].chance ~= tableData[i].chance then showChance = true end
end
local function addCostsRow(row, data)
local costsRow = row:tag('td')
if type(data.costs) == 'table' then
for i, mat in ipairs(data.costs) do
if i > 1 then costsRow:tag('br') end
local matItem = Items.getItemByID(mat.id)
if matItem == nil then
costsRow:wikitext(mat.quantity .. 'x ?????')
else
costsRow:wikitext(Icons.Icon({matItem.name, type='item', qty=mat.quantity}))
end
end
if data.currencyCost ~= nil then
costsRow:wikitext('<br>' .. (Common.getCostString({ ["items"] = {}, ["currencies"] = data.currencyCost }) or ''))
end
else
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 showCategory then tableHeader:tag('th'):wikitext('Category') end
if showRequirements then tableHeader:tag('th'):wikitext('Requirements') 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
if data.qty == nil then data.qty = 1 end
local recipeRow = resultTable:tag('tr')
if showCategory then recipeRow:tag('td'):wikitext(data.category) 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)
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(Num.formatnum(data.xp) .. ' ' .. Icons.Icon({data.skill, notext=true, type='skill'}) .. (data.isAbyssal and ' AXP' or ' XP')):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
end
if not showCategory and tableData[1].category ~= nil then
resultTable:tag('tr')
:tag('th')
:wikitext('Category') -- TODO: Rename to Source or Recipe? Category makes sense for recipe categories but not really spells. Source could be the skill that's used for non-spells??
:css('text-align', 'right')
:tag('td'):wikitext(tableData[1].category) -- TODO: Use Icon template for category. This will require adding overrides to the Icons module for each standard recipe category. Icons will (ideally) be required for Alt Magic Recipes as the category will be the spell that is used
-- This value will need to be passed in as a completed link/icon template as the output will vary by recipe (Such as Barrier Dust having both a Spell and 'Special Items' category)
end
if not showRequirements and tableData[1].skill ~= nil and tableData[1].lvl ~= nil then
local reqRow = resultTable:tag('tr')
:tag('th')
:wikitext('Requirements')
:css('text-align', 'right')
local reqData = reqRow:tag('td')
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')
costRow:tag('th')
:wikitext('Inputs')
:css('text-align', 'right')
addCostsRow(costRow, tableData[1])
end
if not showOutputs and tableData[1].qty ~= nil then
resultTable:tag('tr')
:tag('th')
:wikitext('Outputs')
:css('text-align', 'right')
:tag('td'):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 Experience')
:css('text-align', 'right')
:tag('td'):wikitext(Num.formatnum(tableData[1].xp) .. ' ' .. Icons.Icon({tableData[1].skill, notext=true, type='skill'}) .. (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')
timeHeader
:wikitext('Base Creation Time')
:css('text-align', 'right')
local timeData = timeHeader:tag('td')
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
if not showChance and tableData[1].chance ~= nil then
resultTable:tag('tr')
:tag('th')
:wikitext('Base Recipe Chance')
:css('text-align', 'right')
:tag('td'):wikitext(tableData[1].chance)
end
return '==' .. item.name .. '==\n' .. tostring(resultTable) -- TODO: Remove item.name header
end
end


Line 276: Line 492:
table.insert(resultPart, '\r\n|-\r\n!style="text-align: right;"|Requirements')
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)))
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 specialReq ~= nil then table.insert(resultPart, '<br>'..specialReq) end


if req ~= nil then
if req ~= nil then
Line 282: Line 498:
if type(req) == 'table' then
if type(req) == 'table' then
for i, mat in ipairs(req) do
for i, mat in ipairs(req) do
if i > 1 then table.insert(resultPart, '<br/>') end
if i > 1 then table.insert(resultPart, '<br>') end
local matItem = Items.getItemByID(mat.id)
local matItem = Items.getItemByID(mat.id)
if matItem == nil then
if matItem == nil then
Line 743: Line 959:
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/>after finding ' .. Icons.Icon({foundItem.name, type='item'})
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,041:
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/>") .. '</div>')
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