Anonymous

Module:Items/SourceTables: Difference between revisions

From Melvor Idle
Alt Magic -> Alt. Magic for consistency
(_getItemSources: Support Golbin Raid exclusive items)
(Alt Magic -> Alt. Magic for consistency)
(8 intermediate revisions by 2 users not shown)
Line 4: Line 4:
local ItemData = mw.loadData('Module:Items/data')
local ItemData = mw.loadData('Module:Items/data')
local SkillData = mw.loadData('Module:Skills/data')
local SkillData = mw.loadData('Module:Skills/data')
local MagicData = mw.loadData('Module:Magic/data')


local Constants = require('Module:Constants')
local Constants = require('Module:Constants')
Line 13: Line 14:
local Shop = require('Module:Shop')
local Shop = require('Module:Shop')
local Monsters = require('Module:Monsters')
local Monsters = require('Module:Monsters')
local GatheringSkills = require('Module:Skills/Gathering')
local Skills = require('Module:Skills')


local SkillEnum = mw.loadData('Module:Constants/data').skill
-- Implements overrides for sources which cannot be obtained from game data
-- Implements overrides for sources which cannot be obtained from game data
-- Currently only overrides for dungeon sources are implemented here
-- Currently only overrides for dungeon sources are implemented here
Line 24: Line 26:
}
}
}
}
local SkillEnum = {}
for i, skill in pairs(SkillData.Skills) do
SkillEnum[skill.name] = Constants.getSkillID(skill.name)
end


function p._getCreationTable(item)
function p._getCreationTable(item)
Line 47: Line 44:
if skillID == SkillEnum.Fishing then
if skillID == SkillEnum.Fishing then
-- Fishing
-- Fishing
lvl = item.fishingLevel
local fish = SkillData.Fishing.Fish[masteryID + 1]
xp = item.fishingXP
if fish ~= nil and fish.itemID == item.id then
qty = 1
lvl = fish.level
time = item.minFishingInterval / 1000
xp = fish.baseXP
maxTime = item.maxFishingInterval / 1000
qty = 1
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime))
time = fish.baseMinInterval / 1000
elseif skillID == SkillEnum.Cooking then
maxTime = fish.baseMaxInterval / 1000
-- Cooking
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime))
for i, reqSet in pairs(item.recipeRequirements) do
lvl = item.cookingLevel
xp = item.cookingXP
req = reqSet
qty = item.cookingQty
time = item.cookingInterval / 1000
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
end
end
elseif skillID == SkillEnum.Mining then
elseif skillID == SkillEnum.Mining then
Line 76: Line 66:
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, nil, specialReq))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, nil, specialReq))
end
end
elseif skillID == SkillEnum.Smithing then
elseif Shared.contains({SkillEnum.Smithing, SkillEnum.Fletching, SkillEnum.Crafting,
-- Smithing
SkillEnum.Runecrafting, SkillEnum.Herblore}, skillID) then
local recipe = SkillData.Smithing.Recipes[masteryID + 1]
-- Smithing, Fletching, Crafting, Runecrafting, Herblore
-- All have somewhat consistent recipe data structures
local recipeKey = (skillID == SkillEnum.Herblore and 'Potions') or 'Recipes'
local recipe = SkillData[skill][recipeKey][masteryID + 1]
if recipe ~= nil then
if recipe ~= nil then
local masteryReq = nil
local itemMatch = (recipe.itemID == item.id)
if skillID == SkillEnum.Herblore then
-- For Herblore, we need to check a table of potion IDs & determine the mastery requirement
for i, potionID in ipairs(recipe.potionIDs) do
if potionID == item.id then
itemMatch = true
masteryReq = SkillData.Herblore.TierMasteryLevels[i]
break
end
end
end
if itemMatch then
local baseTime = {
[SkillEnum.Smithing] = 2,
[SkillEnum.Fletching] = 2,
[SkillEnum.Crafting] = 3,
[SkillEnum.Runecrafting] = 2,
[SkillEnum.Herblore] = 2
}
local baseQty = recipe.baseQuantity or 1
lvl = recipe.level
xp = recipe.baseXP
time = baseTime[skillID]
if masteryReq ~= nil and masteryReq > 1 then
specialReq = Icons._MasteryReq(item.name, masteryReq, false)
end
-- Some items (such as Arrow shafts) have multiple recipes
if type(recipe.alternativeCosts) == 'table' then
local reqPart, qtyPart = {}, {}
for i, altCost in ipairs(recipe.alternativeCosts) do
local reqSubPart = {}
for j, itemCost in ipairs(altCost.itemCosts) do
local reqItem = Items.getItemByID(itemCost.id)
if reqItem == nil then
table.insert(reqSubPart, itemCost.qty .. 'x ?????')
else
table.insert(reqSubPart, Icons.Icon({reqItem.name, type='item', qty=itemCost.qty}))
end
end
if recipe.gpCost ~= nil and recipe.gpCost > 0 then
table.insert(reqSubPart, Icons.GP(recipe.gpCost))
end
if recipe.scCost ~= nil and recipe.scCost > 0 then
table.insert(reqSubPart, Icons.GP(recipe.scCost))
end
table.insert(reqPart, table.concat(reqSubPart, ', '))
table.insert(qtyPart, Shared.formatnum(baseQty * altCost.quantityMultiplier))
end
local sep = "<br/>'''OR''' "
req = table.concat(reqPart, sep)
qty = table.concat(qtyPart, sep)
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime, specialReq))
elseif type(recipe.itemCosts) == 'table' and Shared.tableCount(recipe.itemCosts) > 0 then
req = recipe.itemCosts
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, baseQty, time, maxTime, specialReq, recipe.gpCost, recipe.scCost))
end
end
end
elseif skillID == SkillEnum.Summoning then
-- Summoning
local recipe = SkillData.Summoning.Marks[masteryID + 1]
if recipe ~= nil and recipe.itemID == item.id then
lvl = recipe.level
lvl = recipe.level
xp = recipe.baseXP
xp = recipe.baseXP
req = recipe.itemCosts
qty = recipe.baseQuantity
qty = recipe.baseQuantity
time = 2
time = 5
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
-- Create item requirements text
end
local ShardCostArray, OtherCostArray = {}, {}
elseif skillID == SkillEnum.Fletching then
-- Shards
-- Fletching
for j, cost in ipairs(recipe.itemCosts) do
lvl = item.fletchingLevel
local shard = Items.getItemByID(cost.id)
xp = item.fletchingXP
if shard ~= nil then
if item.name == 'Arrow Shafts' then
table.insert(ShardCostArray, Icons.Icon({shard.name, type='item', notext=true, qty=cost.qty}))
--Arrow Shafts get special (weird) treatment
req = '1 of any [[Log]]'
qty = '15 - 135'
else
req = item.fletchReq
qty = item.fletchQty
end
time = 2
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
elseif skillID == SkillEnum.Crafting then
-- Crafting
lvl = item.craftingLevel
xp = item.craftingXP
req = item.craftReq
qty = item.craftQty
time = 3
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
elseif skillID == SkillEnum.Runecrafting then
-- Runecrafting
lvl = item.runecraftingLevel
xp = item.runecraftingXP
req = item.runecraftReq
qty = item.runecraftQty
time = 2
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
elseif skillID == SkillEnum.Herblore then
-- Herblore
local potion = SkillData.Herblore.Potions[masteryID + 1]
if potion ~= nil then
lvl = potion.level
xp = potion.baseXP
req = potion.itemCosts
qty = 1
time = 2
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
end
elseif skillID == SkillEnum.Summoning then
-- Summoning
lvl = item.summoningLevel
--Summoning uses a formula to calculate XP for creation instead of referring to the item's XP data directly
xp = (5 + 2 * math.floor(item.summoningLevel / 5))
local ShardCostArray = {}
for j, cost in Shared.skpairs(item.summoningReq[1]) do
if cost.id >= 0 then
local item = Items.getItemByID(cost.id)
if item.type == 'Shard' then
table.insert(ShardCostArray, Icons.Icon({item.name, type='item', notext=true, qty=cost.qty}))
end
end
end
end
end
-- Other costs
req = table.concat(ShardCostArray, ', ')
local recipeGPCost = SkillData.Summoning.RecipeGPCost
req = req..'<br/>\r\nand one of the following<br/>\r\n'
if recipe.gpCost > 0 then
local OtherCostArray = {}
table.insert(OtherCostArray, Icons.GP(recipe.gpCost))
local recipeGPCost = SkillData.Summoning.Settings.recipeGPCost
end
for j, altCost in Shared.skpairs(item.summoningReq) do
if recipe.scCost > 0 then
local nonShardArray = {}
table.insert(OtherCostArray, Icons.SC(recipe.scCost))
for k, cost in Shared.skpairs(altCost) do
end
if cost.id >= 0 then
for j, nonShardID in ipairs(recipe.nonShardItemCosts) do
local item = Items.getItemByID(cost.id)
local nonShard = Items.getItemByID(nonShardID)
if item.type ~= 'Shard' then
if nonShard ~= nil then
local sellPrice = math.max(item.sellsFor, 20)
local itemValue = math.max(nonShard.sellsFor, 20)
table.insert(nonShardArray, Icons.Icon({item.name, type='item', notext=true, qty=math.max(1, math.floor(recipeGPCost / sellPrice))}))
local nonShardQty = math.max(1, math.floor(recipeGPCost / itemValue))
end
table.insert(OtherCostArray, Icons.Icon({nonShard.name, type='item', notext=true, qty=nonShardQty}))
elseif cost.id == -4 then
table.insert(nonShardArray, Icons.GP(recipeGPCost))
elseif cost.id == -5 then
table.insert(nonShardArray, Icons.SC(recipeGPCost))
end
end
end
end
table.insert(OtherCostArray, table.concat(nonShardArray, ', '))
req = table.concat(ShardCostArray, ', ')
if #OtherCostArray > 0 then
req = req .. '<br/>and one of the following:<br/>' .. table.concat(OtherCostArray, "<br/>'''OR''' ")
end
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
end
end
req = req..table.concat(OtherCostArray, "<br/>'''OR''' ")
qty = item.summoningQty
time = 5
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
end
end
end
end


-- Woodcutting
-- Woodcutting
if item.type == "Logs" then
if item.type == 'Logs' then
-- Determine which tree (if any) the log is from
-- Determine which tree (if any) the log is from
for i, tree in ipairs(SkillData.Woodcutting.Trees) do
for i, tree in ipairs(SkillData.Woodcutting.Trees) do
Line 184: Line 188:
end
end
end
end
 
-- Cooking
--had to add cooking to the list of valid categories here to account for cherries/apples
if item.canEat then
if item.category == 'Cooking' or item.type == "Harvest" or item.type == "Herb" or item.type == "Logs" or Shared.contains(item.name, '(Perfect)') then
for i, recipe in ipairs(SkillData.Cooking.Recipes) do
--Harvest/Herb means farming
if recipe.itemID == item.id or recipe.perfectCookID == item.id then
--Logs might mean farming or might not. Depends on the logs
skill = 'Cooking'
for i, item2 in pairs(ItemData.Items) do
lvl = recipe.level
if item2.grownItemID == item.id then
xp = recipe.baseXP
req = recipe.itemCosts
qty = recipe.baseQuantity
time = recipe.baseInterval / 1000
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
break
end
end
end
-- Farming
if item.type == 'Herb' or item.type == 'Logs' or (item.type == 'Food' and item.category ~= 'Cooking') then
-- Herb means farming
-- Logs/Food might mean farming or might not. Depends on the item
for i, seed in ipairs(ItemData.Items) do
if seed.grownItemID ~= nil and seed.grownItemID == item.id then
skill = 'Farming'
skill = 'Farming'
lvl = item2.farmingLevel
lvl = seed.farmingLevel
xp = item2.farmingXP
xp = seed.farmingXP
time = item2.timeToGrow
time = seed.timeToGrow
if item.type == 'Logs' then
if item.type == 'Logs' then
qty = 35
qty = 35
Line 200: Line 218:
qty = 15
qty = 15
end
end
req = {{id = i - 1, qty = (item2.seedsRequired ~= nil and item2.seedsRequired or 1)}}
req = {{id = seed.id, qty = (seed.seedsRequired ~= nil and seed.seedsRequired or 1)}}
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
break
break
end
--If this is a perfect item, need to find the original
if item2.perfectItem == item.id and item2.recipeRequirements ~= nil then
for j, reqSet in pairs(item2.recipeRequirements) do
skill = 'Cooking'
lvl = item2.cookingLevel
xp = item2.cookingXP
req = reqSet
qty = item2.cookingQty
time = item2.cookingInterval / 1000
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
end
end
end
end
end
Line 223: Line 228:
-- Bars are handled by getItemSuperheatTable()
-- Bars are handled by getItemSuperheatTable()
-- Gems are handled by _getItemLootSourceTable()
-- Gems are handled by _getItemLootSourceTable()
-- TODO Should be able to iterate AltMagic.spells, checking the produces property
for i, altSpell in ipairs(MagicData.AltMagic) do
if item.name == 'Rune Essence' then
if type(altSpell.produces) == 'number' and altSpell.produces == item.id then
table.insert(tables, p.buildAltMagicTable('Just Learning'))
table.insert(tables, p._buildAltMagicTable(altSpell))
elseif item.name == 'Bones' then
end
table.insert(tables, p.buildAltMagicTable('Bone Offering'))
elseif item.name == 'Holy Dust' then
table.insert(tables, p.buildAltMagicTable('Blessed Offering'))
end
end


Line 239: Line 241:
end
end


function p.buildAltMagicTable(spellName)
function p.getAltMagicTable(frame)
local spellName = frame.args ~= nil and frame.args[1] or frame
local spell = Magic.getSpell(spellName, 'AltMagic')
local spell = Magic.getSpell(spellName, 'AltMagic')
if spell == nil then
return 'ERROR: Could not find Alt. Magic spell "' .. spellName .. '"[[Category:Pages with script errors]]'
else
return p._buildAltMagicTable(spell)
end
end
function p._buildAltMagicTable(spell)
local resultPart = {}
local resultPart = {}
table.insert(resultPart, '{|class="wikitable"\r\n|-')
table.insert(resultPart, '{|class="wikitable"\r\n|-')
Line 247: Line 258:
table.insert(resultPart, '\r\n|'..Icons._SkillReq('Magic', spell.level))
table.insert(resultPart, '\r\n|'..Icons._SkillReq('Magic', spell.level))


-- The produces property of Alt magic spells is as follows:
-- The produces property of Alt. Magic spells is as follows:
-- -3 = A random gem, using the same weights as Mining
-- -3 = A random gem, using the same weights as Mining
-- -2 = A bar of the type being created (Superheat)
-- -2 = A bar of the type being created (Superheat)
Line 255: Line 266:
-- The amount produced is determined by the productionRatio property
-- The amount produced is determined by the productionRatio property


-- The consumes property of Alt Magic spells is as follows:
-- The consumes property of Alt. Magic spells is as follows:
-- 0 = Any item
-- 0 = Any item
-- 1 = Junk item
-- 1 = Junk item
Line 263: Line 274:
-- 5 = Coal ore
-- 5 = Coal ore
-- Superheat (2, 3) is handled by _getItemSuperheatTable()
-- Superheat (2, 3) is handled by _getItemSuperheatTable()
--
if spell.consumes ~= nil then
if spell.consumes ~= nil then
local consumeText = {
local consumeText = {
Line 281: Line 291:


--Add runes
--Add runes
local formatRuneList = function(runes)
local runeList = {}
for i, req in ipairs(runes) do
local rune = Items.getItemByID(req.id)
if rune ~= nil then
table.insert(runeList, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
end
end
return table.concat(runeList, ', ')
end
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Runes\r\n| ' .. Magic._getSpellRunes(spell))
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)
--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 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;"|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|-\r\n!style="text-align:right;"|Cast Time\r\n|2s')
table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')
Line 302: Line 301:
end
end


function p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime, specialReq, gpCost)
function p.buildCreationTable(skill, lvl, xp, req, qty, time, maxTime, specialReq, gpCost, scCost)
if qty == nil then qty = 1 end
if qty == nil then qty = 1 end
local resultPart = {}
local resultPart = {}
Line 330: Line 329:
table.insert(resultPart, '<br/>')
table.insert(resultPart, '<br/>')
table.insert(resultPart, Icons.GP(gpCost))
table.insert(resultPart, Icons.GP(gpCost))
end
if scCost ~= nil and scCost > 0 then
table.insert(resultPart, '<br/>')
table.insert(resultPart, Icons.SC(scCost))
end
end
else
else
Line 341: Line 344:
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Creation Time')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"|Base Creation Time')
table.insert(resultPart, '\r\n|'..Shared.formatnum(Shared.round(time, 2, 0))..'s')
table.insert(resultPart, '\r\n|'..Shared.formatnum(Shared.round(time, 2, 0))..'s')
if maxTime ~= nil then table.insert(resultPart, ' - '..Shared.formatnum(Shared.round(maxTime, 2, 0))..'s') end
if maxTime ~= nil and maxTime > time then table.insert(resultPart, ' - '..Shared.formatnum(Shared.round(maxTime, 2, 0))..'s') end
table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\r\n|}')


Line 415: Line 418:


--Next: Can we find it in a box?
--Next: Can we find it in a box?
--While we're here, check for upgrades, originals (for perfect items), and growing
--While we're here, check for upgrades, and growing
local lootStr = ''
local lootPart, upgradePart, growPart = {}, {}, {}
local upgradeStr = ''
local cookStr = ''
local growStr = ''
local count1 = 0
local count2 = 0
for i, item2 in pairs(ItemData.Items) do
for i, item2 in pairs(ItemData.Items) do
if item2.dropTable ~= nil then
if item2.dropTable ~= nil then
for j, loot in pairs(item2.dropTable) do
for j, loot in ipairs(item2.dropTable) do
if loot[1] == item.id then
if loot[1] == item.id then
count1 = count1 + 1
table.insert(lootPart, Icons.Icon({item2.name, type='item', notext=true}))
if string.len(lootStr) > 0 then
break
lootStr = lootStr..','
--if count1 % 3 == 1 and count1 > 1 then lootStr = lootStr..'<br/>' end
lootStr = lootStr..Icons.Icon({item2.name, type="item", notext="true"})
else
lootStr = lootStr..'Opening: '..Icons.Icon({item2.name, type="item", notext="true"})
end
end
end
end
end
end
end
if item2.trimmedItemID == item.id then
if item2.trimmedItemID ~= nil and item2.trimmedItemID == item.id then
count2 = count2 + 1
table.insert(upgradePart, Icons.Icon({item2.name, type='item', notext=true}))
if string.len(upgradeStr) > 0 then
upgradeStr = upgradeStr..','
--if count2 % 3 == 1 and count2 > 1 then upgradeStr = upgradeStr..'<br/>' end
upgradeStr = upgradeStr..Icons.Icon({item2.name, type="item", notext="true"})
else
table.insert(categoryArray, '[[Category:Upgraded Items]]')
upgradeStr = upgradeStr..'Upgrading: '..Icons.Icon({item2.name, type="item", notext="true"})
end
end
end
if item2.grownItemID == item.id then
if item2.grownItemID == item.id then
-- Farming
-- Farming
if string.len(growStr) > 0 then
table.insert(growPart, Icons.Icon({item2.name, type='item', notext=true}))
growStr = growStr..','..Icons.Icon({item2.name, type="item", notext="true"})
else
table.insert(categoryArray, '[[Category:Harvestable Items]]')
growStr = growStr..'Growing: '..Icons.Icon({item2.name, type="item", notext="true"})
end
end
if item2.perfectItem == item.id and item2.cookingLevel ~= nil then
-- Cooking (Perfect items)
table.insert(lineArray, Icons._SkillReq('Cooking', item2.cookingLevel))
end
end
end
end
if string.len(lootStr) > 0 then table.insert(lineArray, lootStr) end
if #lootPart > 0 then
if string.len(upgradeStr) > 0 then table.insert(lineArray, upgradeStr) end
table.insert(lineArray, 'Opening: ' .. table.concat(lootPart, ','))
if string.len(cookStr) > 0 then table.insert(lineArray, cookStr) end
end
if string.len(growStr) > 0 then table.insert(lineArray, growStr) end
if #upgradePart > 0 then
table.insert(categoryArray, '[[Category:Upgraded Items]]')
table.insert(lineArray, 'Upgrading: ' .. table.concat(upgradePart, ','))
end
if #growPart > 0 then
table.insert(categoryArray, '[[Category:Harvestable Items]]')
table.insert(lineArray, 'Growing: ' .. table.concat(growPart, ','))
end


--Next: Can we take it from somebody else -without- killing them?
--Next: Can we take it from somebody else -without- killing them?
local thiefItems = GatheringSkills.getThievingSourcesForItem(item.id)
local thiefItems = Skills.getThievingSourcesForItem(item.id)
local thiefStr = ''
if type(thiefItems) == 'table' then
if Shared.tableCount(thiefItems) > 0 then
local thiefPart = {}
thiefStr = 'Pickpocketing: '
for i, thiefRow in ipairs(thiefItems) do
for i, thiefRow in pairs(thiefItems) do
if thiefRow.npc == 'all' then
if thiefRow.npc == 'all' then
--if 'any' is the npc, this is a rare item so just say 'Thieving level 1'
--if 'all' is the npc, this is a rare item so just say 'Thieving level 1'
thiefStr = Icons._SkillReq('Thieving', 1)
table.insert(lineArray, Icons._SkillReq('Thieving', 1))
else
else
if i > 1 then thiefStr = thiefStr..', ' end
table.insert(thiefPart, Icons.Icon({thiefRow.npc, type='thieving', notext=true}))
thiefStr = thiefStr..Icons.Icon({thiefRow.npc, type='thieving', notext='true'})
end
end
end
if #thiefPart > 0 then
table.insert(lineArray, 'Pickpocketing: ' .. table.concat(thiefPart, ','))
end
end
end
end
if string.len(thiefStr) > 0 then table.insert(lineArray, thiefStr) end


--If all else fails, I guess we should check if we can make it ourselves
--Check if we can make it ourselves
--AstrologyCheck
--AstrologyCheck (Just a brute force for now because only two items)
--(Just a brute force for now because only two items and I'm lazy)
if Shared.contains({'Stardust', 'Golden Stardust'}, item.name) then
if item.name == 'Stardust' or item.name == 'Golden Stardust' then
table.insert(lineArray, Icons.Icon({'Astrology', type='skill'}))
table.insert(lineArray, Icons.Icon({"Astrology", type="skill"}))
end
end


-- Sources discoverable through mastery IDs
-- Sources discoverable through mastery IDs
-- Does _not_ handle:
-- Fishing: Junk, special items
-- Cooking: perfect items
if type(item.masteryID) == 'table' then
if type(item.masteryID) == 'table' then
local skillID, masteryID = item.masteryID[1], item.masteryID[2]
local skillID, masteryID = item.masteryID[1], item.masteryID[2]
local skill, levelReq = Constants.getSkillName(skillID), nil
local skill = Constants.getSkillName(skillID)
if skillID == SkillEnum.Fishing then
local keyData = {
-- Fishing (less Junk & Special items)
[SkillEnum.Fishing] = { ["recipe"] = 'Fish' },
levelReq = item.fishingLevel
[SkillEnum.Mining] = { ["recipe"] = 'Rocks', ["level"] = 'levelRequired', ["item"] = 'oreID' },
elseif skillID == SkillEnum.Cooking then
[SkillEnum.Smithing] = {},
-- Cooking (less Perfect items)
[SkillEnum.Fletching] = {},
levelReq = item.cookingLevel
[SkillEnum.Crafting] = {},
elseif skillID == SkillEnum.Mining then
[SkillEnum.Runecrafting] = {},
-- Mining
[SkillEnum.Herblore] = { ["recipe"] = 'Potions', ["item"] = 'potionIDs', ["isItemList"] = true },
local rock = SkillData.Mining.Rocks[masteryID + 1]
[SkillEnum.Summoning] = { ["recipe"] = 'Marks' }
if rock ~= nil then
}
levelReq = rock.levelRequired
local keys = keyData[skillID]
if type(keys) == 'table' then
if keys.recipe == nil then
keys.recipe = 'Recipes'
end
if keys.level == nil then
keys.level = 'level'
end
if keys.item == nil then
keys.item = 'itemID'
end
end
elseif skillID == SkillEnum.Smithing then
if keys.isItemList == nil then
-- Smithing
keys.isItemList = false
local recipe = SkillData.Smithing.Recipes[masteryID + 1]
if recipe ~= nil then
levelReq = recipe.level
end
end
elseif skillID == SkillEnum.Fletching then
 
-- Fletching
local recipe = SkillData[skill][keys.recipe][masteryID + 1]
levelReq = item.fletchingLevel
if recipe ~= nil and (
elseif skillID == SkillEnum.Crafting then
(not keys.isItemList and recipe[keys.item] == item.id) or
-- Crafting
(keys.isItemList and Shared.contains(recipe[keys.item], item.id))) then
levelReq = item.craftingLevel
local levelReq = recipe[keys.level]
elseif skillID == SkillEnum.Runecrafting then
if levelReq ~= nil then
-- Runecrafting
table.insert(lineArray, Icons._SkillReq(skill, levelReq))
levelReq = item.runecraftingLevel
end
elseif skillID == SkillEnum.Herblore then
-- Herblore
local potion = SkillData.Herblore.Potions[masteryID + 1]
if potion ~= nil then
levelReq = potion.level
end
end
elseif skillID == SkillEnum.Summoning then
-- Summoning
levelReq = item.summoningLevel
end
if levelReq ~= nil then
table.insert(lineArray, Icons._SkillReq(skill, levelReq))
end
end
end
end
Line 545: Line 524:
end
end


-- Woodcutting (Nests)
-- Woodcutting: Nests
if item.name == 'Bird Nest' then
if item.name == 'Bird Nest' then
table.insert(lineArray, Icons._SkillReq('Woodcutting', 1))
table.insert(lineArray, Icons._SkillReq('Woodcutting', 1))
end
end


-- Fishing (Junk & Special items)
-- Fishing: Junk & Specials
if (item.category == "Fishing" and (item.type == "Junk" or item.type == "Special")) then
if Shared.contains(SkillData.Fishing.JunkItems, item.id) then
table.insert(lineArray, Icons.Icon({"Fishing", type='skill', notext=true})..' [[Fishing#'..item.type..'|'..item.type..']]')
table.insert(lineArray, Icons.Icon({'Fishing', type='skill', notext=true}) .. ' [[Fishing#Junk|Junk]]')
else
for i, specialItem in ipairs(SkillData.Fishing.SpecialItems) do
if specialItem[1] == item.id then
table.insert(lineArray, Icons.Icon({'Fishing', type='skill', notext=true}) .. ' [[Fishing#Special|Special]]')
break
end
end
end
 
-- Cooking
if item.canEat then
for i, recipe in ipairs(SkillData.Cooking.Recipes) do
if recipe.itemID == item.id or recipe.perfectCookID == item.id then
table.insert(lineArray, Icons._SkillReq('Cooking', recipe.level))
break
end
end
end
 
-- Alt. Magic
for i, altSpell in ipairs(MagicData.AltMagic) do
if type(altSpell.produces) == 'number' and
((altSpell.produces == -3 and item.type == 'Gem' and item.name ~= 'Jadestone')
or (altSpell.produces == -2 and item.type == 'Bar')
    or (altSpell.produces > 0 and altSpell.produces == item.id)) then
table.insert(lineArray, Icons.Icon({"Alt. Magic", type='skill'}))
break
end
end
end


Line 561: Line 568:
end
end


--Gems can be acquired from mining, fishing, and alt. magic
--Gems can be acquired from Mining
if item.type == 'Gem' and item.name ~= 'Jadestone' then
if item.type == 'Gem' and item.name ~= 'Jadestone' then
table.insert(lineArray, Icons.Icon({"Fishing", type='skill', notext=true})..' [[Fishing#Special|Special]]')
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]]')
table.insert(lineArray, Icons.Icon({"Alt. Magic", type='skill'}))
end
--Bars and some other stuff can also be acquired via Alt. Magic
if item.type == 'Bar' or Shared.contains(Items.AltMagicProducts, item.name) then
table.insert(lineArray, Icons.Icon({"Alt. Magic", type='skill'}))
end
end


Line 579: Line 579:
Jewel = {'Firemaking', 'Cooking', 'Smithing', 'Fletching', 'Crafting', 'Runecrafting', 'Herblore', 'Summoning'}
Jewel = {'Firemaking', 'Cooking', 'Smithing', 'Fletching', 'Crafting', 'Runecrafting', 'Herblore', 'Summoning'}
}
}
local rhaSkList = {}
local rhaSkList, subText = nil, ''
if item.name == 'Circlet of Rhaelyx' then
if item.name == 'Circlet of Rhaelyx' then
rhaSkList = rhaSkills.Circlet
rhaSkList = {rhaSkills.Circlet}
elseif item.name == 'Jewel of Rhaelyx' then
elseif item.name == 'Jewel of Rhaelyx' then
rhaSkList = rhaSkills.Jewel
rhaSkList = {rhaSkills.Jewel}
elseif item.name == 'Mysterious Stone' then
elseif item.name == 'Mysterious Stone' then
rhaSkList = rhaSkills.Jewel
rhaSkList = {rhaSkills.Jewel, rhaSkills.Circlet}
for i, v in ipairs(rhaSkills.Circlet) do
subText = '<br/>after finding ' .. Icons.Icon({'Crown of Rhaelyx', type='item'})
table.insert(rhaSkList, v)
end
end
end


local rhaStrPart = {}
local rhaStrPart = {}
for i, skillName in ipairs(rhaSkList) do
for i, skillList in ipairs(rhaSkList) do
table.insert(rhaStrPart, Icons.Icon({skillName, type='skill', notext=true}))
for j, skillName in ipairs(skillList) do
table.insert(rhaStrPart, Icons.Icon({skillName, type='skill', notext=true}))
end
end
end
local rhaStr = 'Any action in: ' .. table.concat(rhaStrPart, ', ')
table.insert(lineArray, 'Any action in: ' .. table.concat(rhaStrPart, ', ') .. subText)
if item.name == 'Mysterious Stone' then rhaStr = rhaStr .. '<br/>after finding ' .. Icons.Icon({'Crown of Rhaelyx', type='item'}) end
table.insert(lineArray, rhaStr)
end
end


Line 604: Line 602:
table.insert(lineArray, Icons._SkillReq(Constants.getSkillName(item.skill), 1))
table.insert(lineArray, Icons._SkillReq(Constants.getSkillName(item.skill), 1))
end
end
 
-- Golbin Raid exclusive items
-- Golbin Raid exclusive items
if item.golbinRaidExclusive then
if item.golbinRaidExclusive then
Line 676: Line 674:
table.insert(rowPart, '\r\n|style="text-align: left;"|'..type)
table.insert(rowPart, '\r\n|style="text-align: left;"|'..type)


table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="'..qty..'"|'..minqty)
table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="'..qty..'"|'..Shared.formatnum(minqty))
if qty ~= minqty then table.insert(rowPart, ' - '..qty) end
if qty ~= minqty then table.insert(rowPart, ' - '..Shared.formatnum(qty)) end
local chance = weight / totalWeight * 100
local chance = weight / totalWeight * 100
-- If chance is less than 0.10% then show 2 significant figures, otherwise 2 decimal places
-- If chance is less than 0.10% then show 2 significant figures, otherwise 2 decimal places
Line 762: Line 760:


--Next: Can we find it by rummaging around in another item?
--Next: Can we find it by rummaging around in another item?
for i, item2 in pairs(ItemData.Items) do
for i, item2 in ipairs(ItemData.Items) do
if item2.dropTable ~= nil then
if item2.dropTable ~= nil then
local qty = 1
local qty = 1
Line 784: Line 782:
--Finally, let's try just stealing it
--Finally, let's try just stealing it
local thiefType = Icons.Icon({"Thieving", type='skill'})
local thiefType = Icons.Icon({"Thieving", type='skill'})
local thiefItems = GatheringSkills.getThievingSourcesForItem(item.id)
local thiefItems = Skills.getThievingSourcesForItem(item.id)
for i, thiefRow in pairs(thiefItems) do
for i, thiefRow in ipairs(thiefItems) do
local sourceTxt = ''
local sourceTxt = ''
if thiefRow.npc == 'all' then
if thiefRow.npc == 'all' then
Line 796: Line 794:


--Bonus overtime: Special Fishing table & mining gem table. Also Rags to Riches
--Bonus overtime: Special Fishing table & mining gem table. Also Rags to Riches
if Shared.contains(SkillData.Fishing.JunkItems, item.id) then
local fishSource = '[[Fishing#Junk|Junk]]'
local fishType = Icons.Icon({'Fishing', type='skill'})
local fishTotWeight = Shared.tableCount(SkillData.Fishing.JunkItems)
table.insert(dropRows, {source = fishSource, type = fishType, minqty = 1, qty = 1, weight = 1, totalWeight = fishTotWeight})
else
local fishTotWeight, fishItem = 0, nil
for i, specialItem in ipairs(SkillData.Fishing.SpecialItems) do
if specialItem[1] == item.id then
fishItem = specialItem
end
fishTotWeight = fishTotWeight + specialItem[2]
end
if fishItem ~= nil then
local fishSource = '[[Fishing#Special|Special]]'
local fishType = Icons.Icon({'Fishing', type='skill'})
table.insert(dropRows, {source = fishSource, type = fishType, minqty = fishItem[3], qty = fishItem[3], weight = fishItem[2], totalWeight = fishTotWeight})
end
end
--Jadestone is special and doesn't count
--Jadestone is special and doesn't count
if item.type == 'Gem' and item.name ~= 'Jadestone' then
if item.type == 'Gem' and item.name ~= 'Jadestone' then
Line 806: Line 823:
table.insert(dropRows, {source = '[[Mining#Gems|Gem]]', type = mineType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
table.insert(dropRows, {source = '[[Mining#Gems|Gem]]', type = mineType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
local magicType = Icons.Icon({'Magic', type = 'skill'})
local magicType = Icons.Icon({'Magic', type = 'skill'})
table.insert(dropRows, {source = Icons.Icon({"Rags to Riches I", type="spell"}), type = magicType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
for i, altSpell in ipairs(MagicData.AltMagic) do
table.insert(dropRows, {source = Icons.Icon({"Rags to Riches II", type="spell"}), type = magicType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
if type(altSpell.produces) == 'number' and altSpell.produces == -3 then
end
table.insert(dropRows, {source = Icons.Icon({altSpell.name, type='spell'}), type = magicType, minqty = 1, qty = 1, weight = thisGemChance, totalWeight = totalGemChance})
 
end
if item.fishingCatchWeight ~= nil then
end
local fishSource = '[[Fishing#Special|Special]]'
local fishType = Icons.Icon({'Fishing', type='skill'})
table.insert(dropRows, {source = fishSource, type = fishType, minqty = 1, qty = 1, weight = item.fishingCatchWeight, totalWeight = Items.specialFishWt})
end
 
if item.type == 'Junk' then
local fishSource = '[[Fishing#Junk|Junk]]'
local fishType = Icons.Icon({'Fishing', type='skill'})
table.insert(dropRows, {source = fishSource, type = fishType, minqty = 1, qty = 1, weight = 1, totalWeight = Items.junkCount})
end
end


Line 827: Line 835:
table.sort(dropRows, function(a, b)
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
return a.minqty + a.qty > b.minqty + b.qty
if a.minqty + a.qty == b.minqty + b.qty then
return (a.type == b.type and a.source < b.source) or a.type < b.type
else
return a.minqty + a.qty > b.minqty + b.qty
end
else
else
return a.weight / a.totalWeight > b.weight / b.totalWeight
return a.weight / a.totalWeight > b.weight / b.totalWeight
Line 864: Line 876:
table.insert(materials, Icons.Icon({mat.name, type='item', qty=row[2]}))
table.insert(materials, Icons.Icon({mat.name, type='item', qty=row[2]}))
end
end
if item.trimmedGPCost ~= nil then
if type(item.trimmedGPCost) == 'number' and item.trimmedGPCost > 0 then
table.insert(materials, Icons.GP(item.trimmedGPCost))
table.insert(materials, Icons.GP(item.trimmedGPCost))
end
end
Line 931: Line 943:
table.insert(superheatTable, '||style="text-align:right;"|'..spell.productionRatio)
table.insert(superheatTable, '||style="text-align:right;"|'..spell.productionRatio)
table.insert(superheatTable, '|| '..table.concat(oreStringPart, ', '))
table.insert(superheatTable, '|| '..table.concat(oreStringPart, ', '))
if spell.consumes == 2 then
if spell.consumes == 2 and coalString ~= '' then
-- 2 = Superheat with coal, 3 = Superheat without coal
-- 2 = Superheat with coal, 3 = Superheat without coal
table.insert(superheatTable, (Shared.tableCount(oreStringPart) > 0 and ', ' or '') .. coalString)
table.insert(superheatTable, (Shared.tableCount(oreStringPart) > 0 and ', ' or '') .. coalString)
Line 975: Line 987:
local recipe = SkillData.Smithing.Recipes[item.masteryID[2] + 1]
local recipe = SkillData.Smithing.Recipes[item.masteryID[2] + 1]
if recipe ~= nil and recipe.category == 0 then
if recipe ~= nil and recipe.category == 0 then
table.insert(resultPart, '\r\n==='..Icons.Icon({'Alt Magic', type='skill'})..'===\r\n'..p._getItemSuperheatTable(item))
table.insert(resultPart, '\r\n==='..Icons.Icon({'Alt. Magic', type='skill'})..'===\r\n'..p._getItemSuperheatTable(item))
end
end
end
end
Line 1,038: Line 1,050:
--  - A monster before the boss, which doesn't drop anything except shards (checked above)
--  - A monster before the boss, which doesn't drop anything except shards (checked above)
--  - A boss monster, whose drops are accounted for in data from Areas instead
--  - A boss monster, whose drops are accounted for in data from Areas instead
local monsterWeight
for j, loot in ipairs(monster.lootTable) do
for j, loot in ipairs(monster.lootTable) do
weight = weight + loot[2]
weight = weight + loot[2]
Line 1,063: Line 1,074:
return p._getItemMonsterSources(item)
return p._getItemMonsterSources(item)
end
end
--[==[
-- Uncomment this block and execute 'p.test()' within the debug console
-- to test after making changes
function p.test()
local checkItems = {
'Gold Bar',
'Raw Shrimp',
'Coal Ore',
'Rune Platebody',
'Arrow Shafts',
'Yew Longbow',
'Water Rune',
'Steam Rune',
'Controlled Heat Potion II',
'Wolf',
'Cyclops',
'Leprechaun',
'Redwood Logs',
'Carrot Cake',
'Carrot Cake (Perfect)',
'Mantalyme Herb',
'Carrot',
'Topaz',
'Rune Essence',
'Sanguine Blade',
'Ring of Power',
'Infernal Claw',
'Chapeau Noir',
'Stardust',
'Rope',
'Ancient Ring of Mastery',
'Mysterious Stone',
'Mastery Token (Cooking)',
'Gem Gloves',
"Thief's Moneysack"
}
local checkFuncs = {
p.getItemSourceTables,
--p.getCreationTable,
p.getItemSources,
--p.getItemLootSourceTable,
}
local errCount = 0
for i, item in ipairs(checkItems) do
local param = {args={item}}
mw.log('==' .. item .. '==')
for j, func in ipairs(checkFuncs) do
local callSuccess, retVal = pcall(func, param)
if not callSuccess then
errCount = errCount + 1
mw.log('Error with item "' .. item .. '": ' .. retVal)
else
mw.log(retVal)
end
end
end
if errCount == 0 then
mw.log('Test successful')
else
mw.log('Test failed with ' .. errCount .. ' failures')
end
end
--]==]


return p
return p