Module:Items/UseTables: Difference between revisions

_getItemUseTable: Amend to show XP harvested per quantity for Farming
(_getSpellUseTable: Include Alt. Magic spells for items which said spells consume (e.g. Junk/Coal))
(_getItemUseTable: Amend to show XP harvested per quantity for Farming)
(20 intermediate revisions by 3 users not shown)
Line 1: Line 1:
local p = {}
local p = {}
local ItemData = mw.loadData('Module:Items/data')
local SkillData = mw.loadData('Module:Skills/data')


local Constants = require('Module:Constants')
local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Shared = require('Module:Shared')
local GameData = require('Module:GameData')
local SkillData = GameData.skillData
local Magic = require('Module:Magic')
local Magic = require('Module:Magic')
local Areas = require('Module:CombatAreas')
local Areas = require('Module:CombatAreas')
Line 16: Line 15:
local itemUseArray = {
local itemUseArray = {
Agility = {},
Agility = {},
Astrology = {'Stardust', 'Golden Stardust'},
Astrology = {'melvorF:Stardust', 'melvorF:Golden_Stardust'},
Attack = {},
Attack = {},
Combat = {'Gold Emerald Ring'},
Cartography = {'melvorD:Crown_of_Rhaelyx'},
Cooking = {'Cooking Gloves', 'Crown of Rhaelyx'},
Combat = {'melvorF:Gold_Emerald_Ring', 'melvorD:Obsidian_Cape', 'melvorF:Throwing_Power_Gloves'},
Crafting = {'Crown of Rhaelyx'},
Cooking = {'melvorD:Cooking_Gloves', 'melvorD:Crown_of_Rhaelyx'},
Crafting = {'melvorD:Crown_of_Rhaelyx'},
Defence = {},
Defence = {},
Farming = {'Compost', 'Weird Gloop', 'Bob's Rake'},
Farming = {'melvorD:Compost', 'melvorD:Weird_Gloop', 'melvorD:Bobs_Rake'},
Firemaking = {'Crown of Rhaelyx'},
Firemaking = {'melvorD:Crown_of_Rhaelyx'},
Fishing = {'Amulet of Fishing', 'Message in a Bottle'},
Fishing = {'melvorD:Amulet_of_Fishing', 'melvorD:Message_In_A_Bottle', 'melvorD:Barbarian_Gloves'},
Fletching = {'Crown of Rhaelyx'},
Fletching = {'melvorD:Crown_of_Rhaelyx'},
Herblore = {'Crown of Rhaelyx'},
Herblore = {'melvorD:Crown_of_Rhaelyx'},
Hitpoints = {},
Hitpoints = {},
Magic = {},
Magic = {},
Mining = {'Mining Gloves', 'Gem Gloves'},
Mining = {'melvorD:Mining_Gloves', 'melvorD:Gem_Gloves'},
Prayer = {},
Prayer = {},
Ranged = {},
Ranged = {},
Runecrafting = {'Crown of Rhaelyx'},
Runecrafting = {'melvorD:Crown_of_Rhaelyx'},
Slayer = {},
Slayer = {},
Smithing = {'Smithing Gloves', 'Crown of Rhaelyx'},
Smithing = {'melvorD:Smithing_Gloves', 'melvorD:Crown_of_Rhaelyx'},
Strength = {},
Strength = {},
Summoning = {'Crown of Rhaelyx'},
Summoning = {'melvorD:Crown_of_Rhaelyx'},
Thieving = {'Chapeau Noir', 'Thieving Gloves', 'Gloves of Silence'},
Thieving = {'melvorF:Chapeau_Noir', 'melvorF:Thieving_Gloves', 'melvorF:Gloves_of_Silence'},
Township = {},
Woodcutting = {},
Woodcutting = {},
}
}
local potionUseArray = {
[0] = 'Combat',
[1] = 'Combat',
[2] = 'Combat',
[3] = 'Combat',
[4] = 'Combat',
[5] = 'Combat',
[6] = 'Combat',
[7] = 'Woodcutting',
[8] = 'Fishing',
[9] = 'Firemaking',
[10] = 'Cooking',
[11] = 'Mining',
[12] = 'Smithing',
[13] = 'Thieving',
[14] = 'Farming',
[15] = 'Fletching',
[16] = 'Crafting',
[17] = 'Runecrafting',
[18] = 'Herblore',
[19] = 'Combat',
[20] = 'Combat',
[21] = 'Combat',
[22] = 'Combat',
[23] = 'Combat',
[24] = 'Agility',
[25] = 'Summoning',
[26] = 'Combat',
[27] = 'Combat',
[28] = 'Combat',
[29] = 'Astrology'
}
local SkillEnum = {}
for i, skill in pairs(SkillData.Skills) do
SkillEnum[skill.name] = Constants.getSkillID(skill.name)
end


function p._getItemUses(item, asList, addCategories)
function p._getItemUses(item, asList, addCategories)
local useArray = {}
-- Another fun one. This time getting all the different possible ways an item can be used
local categoryArray = {}
local categoryArray = {}
local chr = asList and '* ' or ''
local skillUses = {}
--Another fun one. This time getting all the different possible ways an item can be used
local otherUses = {}
local otherUseText = {
["Combat"] = Icons.Icon({'Combat'}),
["Upgrade"] = '[[Upgrading Items]]',
["Food"] = '[[Food]]',
["Chest"] = '[[Chest Drop Tables|Can Be Opened]]',
["Mastery"] = Icons.Icon({'Mastery'}),
["AllSkills"] = 'All skills',
["AltMagic"] = Icons.Icon({'Alt. Magic', type='skill'}),
["ChargeStone"] = 'Powering ' .. Icons.Icon({'Crown of Rhaelyx', type='item'}),
["Shop"] = Icons.Icon({'Shop'}),
["TownshipTask"] = Icons.Icon({'Tasks', type='township'})
}


--Before anything else, if this is a potion add it to the appropriate override section
local addUse = function(useName)
if item.masteryID ~= nil and item.masteryID[1] == SkillEnum.Herblore then
local skillID = Constants.getSkillID(useName)
if potionUseArray[item.masteryID[2]] ~= nil then
if skillID == nil then
table.insert(itemUseArray[potionUseArray[item.masteryID[2]]], item.name)
-- May have been passed a skill ID instead
local skillName = Constants.getSkillName(useName)
if skillName ~= nil then
skillID = useName
skillUses[skillID] = skillName
end
else
else
table.insert(itemUseArray["Combat"], item.name)
skillUses[skillID] = useName
end
end
end


--If the item has any modifiers that affect a given skill, add it to those lists
if skillID == nil and not otherUses[useName] then
--Added an exception for Mastery Tokens since they were being incorrectly flagged as usable for all skills
otherUses[useName] = true
if item.modifiers ~= nil and (item.isToken == nil or not item.isToken) then
local skillArray = Constants.getModifierSkills(item.modifiers)
for i, skillName in Shared.skpairs(skillArray) do
table.insert(itemUseArray[skillName], item.name)
end
end
end
end
 
local hasUse = function(useName)
--First things added to the list are non-skill things that are easy to check
local skillID = Constants.getSkillID(useName) or (Constants.getSkillName(useName) ~= nil and useName)
if Items.hasCombatStats(item) or item.specialAttacks ~= nil or Shared.contains(itemUseArray.Combat, item.name) then
if skillID ~= nil then
table.insert(useArray, chr..Icons.Icon({'Combat'}))
return (skillUses[skillID] ~= nil) or false
else
return otherUses[useName] or false
end
end
end


if item.healsFor ~= nil then
-- Check for any overrides within itemUseArray
table.insert(categoryArray, '[[Category:Food Items]]')
for useName, itemList in pairs(itemUseArray) do
table.insert(useArray, chr..'[[Food]]')
if Shared.contains(itemList, item.id) then
addUse(useName)
end
end
end


if item.dropTable ~= nil then
-- If the item has any modifiers that affect a given skill, add it to those tables
table.insert(categoryArray, '[[Category:Openable Items]]')
-- Added special handling for Mastery Tokens since they were being incorrectly flagged as usable for all skills
table.insert(useArray, chr..'[[Chest Drop Tables|Can Be Opened]]')
if item.modifiers ~= nil then
end
if item.modifiers.masteryToken ~= nil then
 
-- Mastery tokens
-- Check if the item is an entry requirement for any Slayer area
addUse('Mastery')
local isSlayerAreaReq = false
else
if item.isEquipment then
local globalMods = {
local slayerAreas = Areas.getAreas(function(area) return area.type == 'slayer' end)
'increasedChanceToDoubleItemsGlobal',
for i, area in pairs(slayerAreas) do
'decreasedChanceToDoubleItemsGlobal',
if area.entryRequirements ~= nil and type(area.entryRequirements) == 'table' then
'increasedGlobalSkillIntervalPercent',
for j, req in pairs(area.entryRequirements) do
'decreasedGlobalSkillIntervalPercent',
if req.type == "SlayerItem" and req.itemID == item.id then
'increasedGlobalSkillXP',
isSlayerAreaReq = true
'decreasedGlobalSkillXP'
break
}
end
for i, globalMod in ipairs(globalMods) do
if item.modifiers[globalMod] ~= nil then
addUse('AllSkills')
break
end
end
if not hasUse('AllSkills') then
local skillArray = Constants.getModifierSkills(item.modifiers)
for i, skillName in ipairs(skillArray) do
addUse(skillName)
end
end
if isSlayerAreaReq then break end
end
end
end
end
end
end


--Next, upgrading, crafting, herblore, fletching, and runecrafting since we have to sift through other items for these
--First things added to the list are non-skill things that are easy to check
local canUpgrade = false
if not hasUse('Combat') and (Items.hasCombatStats(item) or item.specialAttacks ~= nil) then
local canCraft = false
addUse('Combat')
local canFletch = false
local canRunecraft = false
local canHerblore = false
local canAgile = false
local canSummon = false
local canCook = false
local canSmith = false
 
if item.trimmedItemID ~= nil then
canUpgrade = true
end
end


for i, item2 in pairs(ItemData.Items) do
-- Check if the item is an entry requirement for any Slayer area
if not canUpgrade and item2.itemsRequired ~= nil then
if not hasUse('Slayer') and (item.validSlots ~= nil or item.occupiesSlots ~= nil or item.equipmentStats ~= nil) then
for j, req in pairs(item2.itemsRequired) do
local slayerAreas = Areas.getAreas(function(area) return area.type == 'slayerArea' and type(area.entryRequirements) == 'table' end)
if req[1] == item.id then
for i, area in ipairs(slayerAreas) do
canUpgrade = true
for j, req in ipairs(area.entryRequirements) do
if req.type == "SlayerItem" and req.itemID == item.id then
addUse('Slayer')
break
break
end
end
end
end
end
if hasUse('Slayer') then
if not canCraft and item2.craftReq ~= nil then
break
for j, req in pairs(item2.craftReq) do
if req.id == item.id then
canCraft = true
break
end
end
end
end
end
if not canFletch and item2.fletchReq ~= nil then
end
for j, req in pairs(item2.fletchReq) do
 
if req.id == item.id then
-- Is the item a cost in an upgrade?
canFletch = true
for i, upgrade in ipairs(GameData.rawData.itemUpgrades) do
break
for j, itemCost in ipairs(upgrade.itemCosts) do
end
if itemCost.id == item.id then
addUse('Upgrade')
table.insert(categoryArray, '[[Category:Upgradeable Items]]')
break
end
end
end
end
if not canRunecraft and item2.runecraftReq ~= nil then
if hasUse('Upgrade') then
for j, req in pairs(item2.runecraftReq) do
break
if req.id == item.id then
canRunecraft = true
break
end
end
end
end
if not canSummon and item2.summoningReq ~= nil then
end
for j, reqSet in pairs(item2.summoningReq) do
 
for k, req in pairs(reqSet) do
if item.healsFor ~= nil then
if req.id == item.id then
table.insert(categoryArray, '[[Category:Food Items]]')
canSummon = true
addUse('Food')
end
 
if item.dropTable ~= nil then
table.insert(categoryArray, '[[Category:Openable Items]]')
addUse('Chest')
end
 
-- Cooking, Smithing, Fletching, Crafting, Runecrafting, Herblore
-- All have somewhat consistent recipe data structures
local recipeSkillIDs = {
'melvorD:Cooking',
'melvorD:Smithing',
'melvorD:Fletching',
'melvorD:Crafting',
'melvorD:Runecrafting',
'melvorD:Herblore'
}
for i, recipeSkillID in ipairs(recipeSkillIDs) do
if not hasUse(recipeSkillID) then
local _, localSkillID = GameData.getLocalID(recipeSkillID)
-- Iterate over all recipes for the current skill
for j, recipe in ipairs(SkillData[localSkillID].recipes) do
for k, itemCost in ipairs(recipe.itemCosts) do
if itemCost.id == item.id then
addUse(recipeSkillID)
break
break
end
end
end
end
if canSummon then
-- Some items (such as Arrow shafts) have multiple recipes
break
if not hasUse(recipeSkillID) and type(recipe.alternativeCosts) == 'table' then
end
for k, altCost in ipairs(recipe.alternativeCosts) do
end
for m, itemCost in ipairs(altCost.itemCosts) do
end
if itemCost.id == item.id then
--Handling for new Cooking method
addUse(recipeSkillID)
if not canCook and item2.recipeRequirements ~= nil and item2.recipeRequirements[1] ~= nil then
break
for j, reqSet in pairs(item2.recipeRequirements) do
end
for k, req in pairs(reqSet) do
end
if req.id == item.id then
if hasUse(recipeSkillID) then
canCook = true
break
break
end
end
end
end
end
if canCook then
if hasUse(recipeSkillID) then
break
break
end
end
Line 211: Line 210:
end
end


-- Check potions for Herblore
-- Firemaking
for i, potion in ipairs(SkillData.Herblore.Potions) do
if not hasUse('melvorD:Firemaking') then
for j, itemCost in ipairs(potion.itemCosts) do
for i, recipe in ipairs(SkillData.Firemaking.logs) do
if itemCost.id == item.id then
if recipe.logID == item.id then
canHerblore = true
addUse('melvorD:Firemaking')
break
break
end
end
end
if canHerblore then
break
end
end
end
end


-- Check recipes for Smithing
-- Farming
for i, recipe in ipairs(SkillData.Smithing.Recipes) do
if not hasUse('melvorD:Farming') then
for j, itemCost in ipairs(recipe.itemCosts) do
for i, recipe in ipairs(SkillData.Farming.recipes) do
if itemCost.id == item.id then
if recipe.seedCost.id == item.id then
canSmith = true
addUse('melvorD:Farming')
break
break
end
end
end
if canSmith then
break
end
end
end
end


--Check if Agility applies here
-- Agility
canAgile = Shared.tableCount(Agility.getObstaclesForItem(item.id)) > 0
if not hasUse('melvorD:Agility') and not Shared.tableIsEmpty(Agility.getObstaclesForItem(item.id)) then
addUse('melvorD:Agility')
end


--Agility
-- Summoning
if canAgile or Shared.contains(itemUseArray.Agility, item.name) then
if not hasUse('melvorD:Summoning') then
table.insert(useArray, chr..Icons.Icon({'Agility', type='skill'}))
for i, recipe in ipairs(SkillData.Summoning.recipes) do
-- Tablets & Non-shard items
if recipe.productID == item.id or Shared.contains(recipe.nonShardItemCosts, item.id) then
addUse('melvorD:Summoning')
break
else
-- Shards
for j, itemCost in ipairs(recipe.itemCosts) do
if itemCost.id == item.id then
addUse('melvorD:Summoning')
break
end
end
end
end
end
end
--Astrology
 
if Shared.contains(itemUseArray.Astrology, item.name) then
-- Prayer
table.insert(useArray, chr..Icons.Icon({'Astrology', type='skill'}))
if item.prayerPoints ~= nil then
end
table.insert(categoryArray, '[[Category:Buriable Items]]')
--Cooking
if not hasUse('melvorD:Prayer') then
if canCook or Shared.contains(itemUseArray.Cooking, item.name) then
addUse('melvorD:Prayer')
table.insert(useArray, chr..Icons.Icon({'Cooking', type='skill'}))
end
end
--Crafting
if canCraft or Shared.contains(itemUseArray.Crafting, item.name) then
table.insert(useArray, chr..Icons.Icon({'Crafting', type='skill'}))
end
--Farming
if item.grownItemID ~= nil or Shared.contains(itemUseArray.Farming, item.name) then
table.insert(useArray, chr..Icons.Icon({'Farming', type='skill'}))
end
--Firemaking
if (type(item.masteryID) == 'table' and item.masteryID[1] == SkillEnum.Firemaking) or Shared.contains(itemUseArray.Firemaking, item.name) then
table.insert(useArray, chr..Icons.Icon({'Firemaking', type='skill'}))
end
--Fishing
if Shared.contains(itemUseArray.Fishing, item.name) then
table.insert(useArray, chr..Icons.Icon({'Fishing', type='skill'}))
end
--Fletching
if canFletch or Shared.contains(itemUseArray.Fletching, item.name) then
table.insert(useArray, chr..Icons.Icon({'Fletching', type='skill'}))
end
--Herblore
if canHerblore or Shared.contains(itemUseArray.Herblore, item.name) then
table.insert(useArray, chr..Icons.Icon({'Herblore', type='skill'}))
end
--Mining
if Shared.contains(itemUseArray.Mining, item.name) then
table.insert(useArray, chr..Icons.Icon({'Mining', type='skill'}))
end
--Prayer
if item.prayerPoints ~= nil or (Shared.contains(itemUseArray.Prayer, item.name) and not Shared.contains(itemUseArray.Combat, item.name)) then
if item.prayerPoints ~= nil then table.insert(categoryArray, '[[Category:Buriable Items]]') end
table.insert(useArray, chr..Icons.Icon({'Prayer', type='skill'}))
end
--Runecrafting
if canRunecraft or Shared.contains(itemUseArray.Runecrafting, item.name) then
table.insert(useArray, chr..Icons.Icon({'Runecrafting', type='skill'}))
end
--Slayer
if isSlayerAreaReq or Shared.contains(itemUseArray.Slayer, item.name) then
table.insert(useArray, chr..Icons.Icon({'Slayer', type='skill'}))
end
--Smithing
if canSmith or Shared.contains(itemUseArray.Smithing, item.name) then
table.insert(useArray, chr..Icons.Icon({'Smithing', type='skill'}))
end
--Summoning
if canSummon or (item.type == 'Shard' and item.category == 'Summoning') or item.type == 'Familiar' or Shared.contains(itemUseArray.Summoning, item.name) then
table.insert(useArray, chr..Icons.Icon({'Summoning', type='skill'}))
end
--Thieving
if Shared.contains(itemUseArray.Thieving, item.name) then
table.insert(useArray, chr..Icons.Icon({'Thieving', type='skill'}))
end
--Woodcutting
if Shared.contains(itemUseArray.Woodcutting, item.name) then
table.insert(useArray, chr..Icons.Icon({'Woodcutting', type='skill'}))
end
end


--Other odds and ends:
-- Magic
 
if not (hasUse('Magic') and hasUse('AltMagic')) then
--Mastery Tokens are tied to 'Mastery'
-- First check if the item its self is used in any spells
if item.isToken and item.skill ~= nil then
local spellList = Magic.getSpellsUsingItem(item.id, true)
table.insert(useArray, chr..Icons.Icon({'Mastery'}))
for i, spell in ipairs(spellList) do
local useKey = (spell.type == 'altMagic' and 'AltMagic' or 'Magic')
if not hasUse(useKey) then
addUse(useKey)
end
end
-- Check if the item provides runes, if it does check where they are used also
if item.providedRunes ~= nil then
for i, rune in ipairs(item.providedRunes) do
if hasUse('Magic') and hasUse('AltMagic') then
break
else
local spellList = Magic.getSpellsUsingItem(rune.id, false)
for j, spell in ipairs(spellList) do
local useKey = (spell.type == 'altMagic' and 'AltMagic' or 'Magic')
if not hasUse(useKey) then
addUse(useKey)
end
end
end
end
end
end
end


--Skillcapes are tied to the appropriate skill
-- Other odds and ends:
--Except Maximum Skillcape, which is tied to all skills. (And so is the Signet Ring)
--And combat skillcapes, since combat skills don't get special treatment


local ignoreCapes = {'Ranged Skillcape', 'Attack Skillcape', 'Strength Skillcape', 'HP Skillcape', 'Defence Skillcape'}
-- Skillcapes are tied to the appropriate skill
if Shared.contains({'Maximum Skillcape', 'Aorpheat's Signet Ring', 'Cape of Completion'}, item.name) then
-- Except Maximum Skillcape, which is tied to all skills. (And so is the Signet Ring)
table.insert(useArray, chr..'All skills')
-- And combat skillcapes, since combat skills don't get special treatment
elseif item.name == 'Magic Skillcape' then
if item.tier == 'Skillcape' then
table.insert(useArray, chr..Icons.Icon({'Magic', type='skill'}))
local ignoreCapes = {
table.insert(useArray, chr..Icons.Icon({'Alt. Magic', type='skill'}))
'melvorD:Attack_Skillcape',
elseif Shared.contains(item.name, 'Skillcape') and not Shared.contains(ignoreCapes, item.name) then
'melvorD:Strength_Skillcape',
local skillName = Shared.splitString(item.name, ' ')[1]
'melvorD:Defence_Skillcape',
--Avoiding double-listing the same skill twice
'melvorD:Hitpoints_Skillcape',
if not Shared.contains(itemUseArray[skillName], item.name) then
'melvorF:Ranged_Skillcape',
table.insert(useArray, chr..Icons.Icon({skillName, type='skill'}))
'melvorTotH:Superior_Attack_Skillcape',
'melvorTotH:Superior_Strength_Skillcape',
'melvorTotH:Superior_Defence_Skillcape',
'melvorTotH:Superior_Hitpoints_Skillcape',
'melvorTotH:Superior_Ranged_Skillcape',
}
local allCapes = {
'melvorF:Max_Skillcape',
'melvorF:Cape_of_Completion',
'melvorTotH:Superior_Max_Skillcape',
'melvorTotH:Superior_Cape_Of_Completion'
}
if Shared.contains(allCapes, item.id) then
addUse('AllSkills')
elseif Shared.contains({'melvorF:Magic_Skillcape', 'melvorTotH:Superior_Magic_Skillcape'}, item.id) then
addUse('melvorD:Magic')
addUse('AltMagic')
elseif not Shared.contains(ignoreCapes, item.id) then
local splitName = Shared.splitString(item.name, ' ')
local skillName = (splitName[1] == 'Superior' and splitName[2]) or splitName[1]
addUse(skillName)
end
end
table.insert(categoryArray, '[[Category:Skillcapes]]')
end
end
if Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion' then table.insert(categoryArray, '[[Category:Skillcapes]]') end


--Special note for Charge Stone of Rhaelyx
--Special note for Charge Stone of Rhaelyx
if item.name == 'Charge Stone of Rhaelyx' then
if item.id == 'melvorD:Charge_Stone_of_Rhaelyx' then
table.insert(useArray, chr..'Powering '..Icons.Icon({'Crown of Rhaelyx', type='item'}))
addUse('ChargeStone')
end
end


--Some items are needed to make shop purchases
--Some items are needed to make shop purchases
local shopArray = Shop.getItemCostArray(item.id)
local shopArray = Shop.getItemCostArray(item.id)
if Shared.tableCount(shopArray) > 0 then
if not Shared.tableIsEmpty(shopArray) then
table.insert(useArray, chr..Icons.Icon({'Shop'}))
addUse('Shop')
end
end


if canUpgrade then
-- Township Tasks
if item.canUpgrade or (item.type == 'Armour' and item.canUpgrade == nil) then
for _, task in ipairs(SkillData.Township.tasks) do
table.insert(categoryArray, '[[Category:Upgradeable Items]]')
if task.goals.items[1] ~= nil then -- Skip tasks with no items
if GameData.getEntityByID(task.goals.items, item.id) then
addUse('TownshipTask')
break
end
end
end
table.insert(useArray, chr..'[[Upgrading Items]]')
end
-- Generate result text
local useArray = {}
local prefix, delim = asList and '* ' or '', asList and '\r\n' or '<br/>'
for skillID, skillName in Shared.spairs(skillUses, function(t, a, b) return t[a] < t[b] end) do
table.insert(useArray, prefix .. Icons.Icon({skillName, type='skill'}))
end
for use, _ in Shared.skpairs(otherUses) do
table.insert(useArray, prefix .. (otherUseText[use] or use))
end
end


local resultPart = {}
return table.concat(useArray, delim) .. (addCategories and table.concat(categoryArray, '') or '')
table.insert(resultPart, asList and table.concat(useArray,'\r\n') or table.concat(useArray, '<br/>'))
if addCategories then table.insert(resultPart, table.concat(categoryArray, '')) end
return table.concat(resultPart)
end
end


Line 371: Line 371:
end
end
if item == nil then
if item == nil then
return "ERROR: No item named "..itemName.." exists in the data module"
return Shared.printError('No item named "' .. itemName .. '" exists in the data module')
end
end


Line 379: Line 379:
function p._getItemUseTable(item)
function p._getItemUseTable(item)
local useArray = {}
local useArray = {}
local potTierMastery = {[0] = 0, [1] = 20, [2] = 50, [3] = 90}


--First, loop through all items to find anything that can be made or upgraded into using our source
-- Loop through all upgrades to find anything that can be upgraded using our source
for i, item2 in pairs(ItemData.Items) do
for i, upgrade in ipairs(GameData.rawData.itemUpgrades) do
if item2.itemsRequired ~= nil then
for j, itemCost in ipairs(upgrade.itemCosts) do
for j, req in pairs(item2.itemsRequired) do
if itemCost.id == item.id then
if req[1] == item.id then
local rowReq = nil
local mat = item2.itemsRequired
-- Potions do have upgrade requirements though
local xp = 'N/A'
local upgradeItem = Items.getItemByID(upgrade.upgradedItemID)
local rowReq = 'None'
if upgradeItem ~= nil and upgradeItem.charges ~= nil and upgradeItem.tier ~= nil then
--Potions do have upgrade requirements though
local levelUnlock = GameData.getEntityByProperty(SkillData.Herblore.masteryLevelUnlocks, 'descriptionID', upgradeItem.tier + 1)
if item2.potionTier ~= nil then
if levelUnlock ~= nil then
rowReq = Icons._MasteryReq(item2.name, potTierMastery[item2.potionTier])
rowReq = Icons._MasteryReq(upgradeItem.name, levelUnlock.level)
end
end
table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Upgrade', req = rowReq, xp = xp, gp = item2.trimmedGPCost})
break
end
end
table.insert(useArray, {item = {id = upgradeItem.id, name = upgradeItem.name}, qty = 1, mats = upgrade.itemCosts, skill = 'Upgrade', req = rowReq, xp = 'N/A', gp = upgrade.gpCost, sc = upgrade.scCost})
end
end
end
end
if item2.craftReq ~= nil then
end
for j, req in pairs(item2.craftReq) do
if req.id == item.id then
local mat = item2.craftReq
local xp = item2.craftingXP
local rowReq = item2.craftingLevel
local qty = item2.craftQty
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Crafting', req = rowReq, xp = xp, gp = item2.craftGPCost})
break
end
end
end
if item2.fletchReq ~= nil then
for j, req in pairs(item2.fletchReq) do
if req.id == item.id then
local xp = item2.fletchingXP
local rowReq = item2.fletchingLevel
--Arrow Shafts are special and have to be treated specially
local qty = item2.fletchQty
local mat = item2.fletchReq
if item2.name == 'Arrow Shafts' then
mat = {{id = item.id, qty = 1}}
qty =  qty + (qty * item.id)
end
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Fletching', req = rowReq, xp = xp})
break
end
end
end
--Handling for new Cooking method
if item2.recipeRequirements ~= nil then
for j, reqSet in pairs(item2.recipeRequirements) do
for k, req in pairs(reqSet) do
if req.id == item.id then
local mat = reqSet
local xp = item2.cookingXP
local rowReq = item2.cookingLevel
local qty = item2.cookingQty
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})


if item2.perfectItem ~= nil then
-- Cooking, Smithing, Fletching, Crafting, Runecrafting, Herblore
local perfectItem = Items.getItemByID(item2.perfectItem)
-- All have somewhat consistent recipe data structures
table.insert(useArray, {item = perfectItem, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp})
local recipeSkillIDs = {
'melvorD:Cooking',
'melvorD:Smithing',
'melvorD:Fletching',
'melvorD:Crafting',
'melvorD:Runecrafting',
'melvorD:Herblore'
}
for i, recipeSkillID in ipairs(recipeSkillIDs) do
local skillName = Constants.getSkillName(recipeSkillID)
local _, localSkillID = GameData.getLocalID(recipeSkillID)
-- Iterate over all recipes for the current skill
for j, recipe in ipairs(SkillData[localSkillID].recipes) do
local costLists = {recipe.alternativeCosts or {}, {{["itemCosts"] = recipe.itemCosts}}}
for k, costList in pairs(costLists) do
for m, costDef in pairs(costList) do
for n, itemCost in ipairs(costDef.itemCosts) do
if itemCost.id == item.id then
local recipeItemIDs = nil
if recipeSkillID == 'melvorD:Herblore' then
recipeItemIDs = recipe.potionIDs
elseif recipeSkillID == 'melvorD:Cooking' then
recipeItemIDs = {recipe.productID, recipe.perfectCookID}
else
recipeItemIDs = {recipe.productID}
end
for o, recipeItemID in ipairs(recipeItemIDs) do
local recipeItem = Items.getItemByID(recipeItemID)
if recipeItem ~= nil then
local itemDef = {id = recipe.itemID, name = recipeItem.name}
local qty = (recipe.baseQuantity or 1) * (costDef.quantityMultiplier or 1)
local rowReq = recipe.level
local reqVal = nil
if recipeSkillID == 'melvorD:Herblore' then
-- Herblore may also have a mastery requirement
local levelUnlock = GameData.getEntityByProperty(SkillData.Herblore.masteryLevelUnlocks, 'descriptionID', recipeItem.tier + 1)
if levelUnlock ~= nil and levelUnlock.level > 1 then
local masteryReq = Icons._MasteryReq(recipeItem.name, levelUnlock.level)
reqVal = rowReq + levelUnlock.level * 0.01
rowReq = Icons._SkillReq(skillName, rowReq) .. '<br/>' .. masteryReq
end
end
table.insert(useArray, {item = itemDef, qty = qty, mats = costDef.itemCosts, gp = recipe.gpCost, sc = recipe.scCost, skill = skillName, reqVal = reqVal, req = rowReq, xp = recipe.baseExperience})
end
end
break
end
end
end
end
Line 446: Line 452:
end
end
end
end
if item2.runecraftReq ~= nil then
end
for j, req in pairs(item2.runecraftReq) do
 
if req.id == item.id then
-- Farming
local mat = item2.runecraftReq
for i, recipe in ipairs(SkillData.Farming.recipes) do
local xp = item2.runecraftingXP
if recipe.seedCost.id == item.id then
local rowReq = item2.runecraftingLevel
local product = Items.getItemByID(recipe.productId)
local qty = item2.runecraftQty
local mat = {{id = recipe.seedCost.id, quantity = recipe.seedCost.quantity}}
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Runecrafting', req = rowReq, xp = xp})
local rowReq = recipe.level
break
local category = GameData.getEntityByID(SkillData.Farming.categories, recipe.categoryID)
end
local qty = 5 * category.harvestMultiplier
end
local xp = recipe.baseExperience
table.insert(useArray, {item = {id = product.id, name = product.name}, qty = qty, mats = mat, skill = 'Farming', req = rowReq, xp = xp})
end
end
if item2.summoningReq ~= nil then
end
for j, reqSet in pairs(item2.summoningReq) do
 
for k, req in pairs(reqSet) do
-- Agility
if req.id == item.id then
local obstacles = Agility.getObstaclesForItem(item.id)
local mat = Shared.clone(reqSet)
for i, obstacle in ipairs(obstacles) do
mat[k].qty = math.max(math.floor(1000 / math.max(item.sellsFor, 20)), 1)
local itemCosts = {}
local xp = 5 + 2 * math.floor(item2.summoningLevel * 0.2)
for j, itemDef in ipairs(obstacle.itemCosts) do
local rowReq = item2.summoningLevel
table.insert(itemCosts, {id = itemDef.id, quantity = itemDef.quantity})
table.insert(useArray, {item = item2, qty = 25, mats = mat, skill = 'Summoning', req = rowReq, xp = xp})
end
end
end
end
end
end
local req = Agility._getObstacleRequirements(obstacle)
if item.grownItemID ~= nil then
--local objType = (obstacle.category == nil and 'Pillar') or 'Obstacle'
local item2 = Items.getItemByID(item.grownItemID)
table.insert(useArray, {item = {id = obstacle.id, name = obstacle.name}, qty = 1, mats = itemCosts, gp = obstacle.gpCost, sc = obstacle.scCost, skill = 'Agility', req = req, type = 'skill'})
local mat = {{id = item.id, qty = item.seedsRequired}}
local xp = item.farmingXP
local rowReq = item.farmingLevel
local qty = (item.tier ~= nil and item.tier == 'Tree' and 35 or 15)
table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Farming', req = rowReq, xp = xp})
end
end


-- Check potions for Herblore
-- Summoning
for i, potion in ipairs(SkillData.Herblore.Potions) do
for i, recipe in ipairs(SkillData.Summoning.recipes) do
for j, itemCost in ipairs(potion.itemCosts) do
local recipeGPCost = SkillData.Summoning.recipeGPCost
local useShards = false
local recipeItem = nil
for j, itemCost in ipairs(recipe.itemCosts) do
if itemCost.id == item.id then
if itemCost.id == item.id then
local mat = potion.itemCosts
useShards = true
local xp = potion.baseXP
local baseRowReq = Icons._SkillReq('Herblore', potion.level)
-- Iterate over each potion tier
for k, potItemID in ipairs(potion.potionIDs) do
local potItem = Items.getItemByID(potItemID)
if potItem ~= nil then
local rowReq = baseRowReq
local masteryLvl = potTierMastery[potItem.potionTier]
if masteryLvl > 0 then
rowReq = rowReq .. '<br/>' .. Icons._MasteryReq(potItem.name, masteryLvl)
end
local reqVal = potion.level + masteryLvl * 0.01
table.insert(useArray, {item = potItem, qty = 1, mats = mat, skill = 'Herblore', reqVal = reqVal, req = rowReq, xp = xp})
end
end
break
break
end
end
end
end
end
-- Non-shard items
 
-- Familiar recipes may also have a currency cost without any non-shard
-- Check recipes for Smithing
-- items, so account for this with a dummy ID such that one iteration
for i, recipe in ipairs(SkillData.Smithing.Recipes) do
-- of the below loop always occurs
for j, itemCost in ipairs(recipe.itemCosts) do
local nonShardItemIDs = (Shared.tableIsEmpty(recipe.nonShardItemCosts) and {''} or recipe.nonShardItemCosts)
if itemCost.id == item.id then
for j, nonShardItemID in ipairs(nonShardItemIDs) do
local smithItem = Items.getItemByID(recipe.itemID)
if useShards or nonShardItemID == item.id then
if smithItem ~= nil then
-- Item is used in this particular synergy recipe
local mat = recipe.itemCosts
if recipeItem == nil then
local xp = recipe.baseXP
recipeItem = Items.getItemByID(recipe.productID)
local rowReq = recipe.level
end
local qty = recipe.baseQuantity
local nonShardItem = Items.getItemByID(nonShardItemID)
table.insert(useArray, {item = smithItem, qty = qty, mats = mat, skill = 'Smithing', req = rowReq, xp = xp})
local recipeCosts = Shared.clone(recipe.itemCosts)
break
local recipeCosts = {}
for k, itemCost in ipairs(recipe.itemCosts) do
table.insert(recipeCosts, {id = itemCost.id, quantity = itemCost.quantity})
end
if nonShardItem ~= nil then
-- Item ID can be nil for recipes such as Leprechaun or Cyclops
local itemValue = math.max(nonShardItem.sellsFor, 20)
local nonShardQty = math.max(1, math.floor(recipeGPCost / itemValue))
table.insert(recipeCosts, {id = nonShardItemID, quantity = nonShardQty})
end
end
table.insert(useArray, {item = {id = recipeItem.id, name = recipeItem.name}, qty = recipe.baseQuantity, mats = recipeCosts, gp = recipe.gpCost, sc = recipe.scCost, skill = 'Summoning', req = recipe.level, xp = recipe.baseExperience})
end
end
end
end
Line 525: Line 520:
--Handle shop purchases using Module:Shop
--Handle shop purchases using Module:Shop
local shopUses = Shop.getItemCostArray(item.id)
local shopUses = Shop.getItemCostArray(item.id)
for i, purchase in Shared.skpairs(shopUses) do
for i, shopUse in ipairs(shopUses) do
local rowReq = Shop.getRequirementString(purchase.unlockRequirements)
local purchase = shopUse.purchase
local iconType = (purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0) and 'item' or 'upgrade'
local rowReq = Shop.getRequirementString(purchase.purchaseRequirements)
table.insert(useArray, {item = {name = purchase.name}, qty = 1, mats = purchase.cost.items, skill = 'Shop', req = rowReq, xp = 'N/A', gp = purchase.cost.gp, type = iconType})
local iconType = (purchase.contains.items ~= nil and not Shared.tableIsEmpty(purchase.contains.items) and 'item') or 'upgrade'
local gpCost = Shop.getCurrencyCostString(purchase.cost, 'gp')
local scCost = Shop.getCurrencyCostString(purchase.cost, 'slayerCoins')
local rcCost = Shop.getCurrencyCostString(purchase.cost, 'raidCoins')
table.insert(useArray, {item = {name = Shop._getPurchaseName(purchase)}, qty = 1, mats = purchase.cost.items, skill = 'Shop', req = rowReq, xp = 'N/A', gp = gpCost, sc = scCost, rc = rcCost, type = iconType})
end
end


--Finally build the table using what we've learned
--Finally build the table using what we've learned
table.sort(useArray, function(a, b)
table.sort(useArray, function(a, b)
          local aReqVal = a.reqVal ~= nil and a.reqVal or a.req
local aReqVal = a.reqVal ~= nil and a.reqVal or a.req
          local bReqVal = b.reqVal ~= nil and b.reqVal or b.req
local bReqVal = b.reqVal ~= nil and b.reqVal or b.req
          if a.skill ~= b.skill then
if a.skill ~= b.skill then
            return a.skill < b.skill
return a.skill < b.skill
          elseif type(aReqVal) ~= type(bReqVal) then
elseif type(aReqVal) ~= type(bReqVal) then
            return tostring(aReqVal) < tostring(bReqVal)
return tostring(aReqVal) < tostring(bReqVal)
          elseif aReqVal ~= bReqVal then
elseif aReqVal ~= bReqVal then
            return aReqVal < bReqVal
return aReqVal < bReqVal
          else
else
            return a.item.name < b.item.name
return a.item.name < b.item.name
          end end)
end
end)


local obstacles = Agility.getObstaclesForItem(item.id)


local spellUseTable = p._getSpellUseTable(item)
local resultPart = {}
local resultPart = {}
if Shared.tableCount(useArray) == 0 and Shared.tableCount(obstacles) == 0 then
if not Shared.tableIsEmpty(useArray) then
if string.len(spellUseTable) > 0 then
local typeTextList = {
return '==Uses==\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable
["Shop"] = Icons.Icon({'Shop'}),
else
["Upgrade"] = '[[Upgrading Items|Upgrade]]'
return ''
}
end
 
end
-- Header
table.insert(resultPart, '{| class="wikitable sortable"')
table.insert(resultPart, '{| class="wikitable stickyHeader sortable"')
table.insert(resultPart, '\r\n!colspan=2|Item Created!!Type!!Requirements!!XP!!Ingredients')
table.insert(resultPart, '\r\n|- class="headerRow-0"')
for i, row in pairs(useArray) do
table.insert(resultPart, '\r\n!colspan=2|Item Created!!Type!!Requirements!!XP!!Ingredients')
local qty = row.qty ~= nil and row.qty or 1
local iconType = row.type ~= nil and row.type or 'item'
table.insert(resultPart, '\r\n|-\r\n|data-sort-value="'..row.item.name..'"|')
table.insert(resultPart, Icons.Icon({row.item.name, type=iconType, notext=true, size=50})..'||')
if qty > 1 then table.insert(resultPart, "'''"..qty.."x''' ") end
table.insert(resultPart, Icons.Icon({row.item.name, type='item', noicon=true}))
if row.skill == 'Upgrade' then
table.insert(resultPart, '||data-sort-value="Upgrade"|[[Upgrading Items|Upgrade]]')
elseif row.skill == 'Shop' then
table.insert(resultPart, '||data-sort-value="Shop"|'..Icons.Icon({'Shop'}))
else
table.insert(resultPart, '||data-sort-value="'..row.skill..'"|'..Icons.Icon({row.skill, type='skill'}))
end
if type(row.req) == 'number' then
table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.req..'"|'..Icons._SkillReq(row.skill, row.req))
elseif row.reqVal ~= nil then
table.insert(resultPart, '|| style="text-align:right" data-sort-value="'..row.reqVal..'"|'..row.req)
else
table.insert(resultPart, '||'..row.req)
end
if type(row.xp) == 'string' then
table.insert(resultPart, '||style="text-align:right" data-sort-value="0"|'..row.xp)
else
table.insert(resultPart, '||style="text-align:right" data-sort-value="'..row.xp..'"|'..row.xp..' '..Icons.Icon({row.skill, type='skill', notext=true})..' XP')
end
table.insert(resultPart, '||')
for i, mat in Shared.skpairs(row.mats) do
local matID = mat.id ~= nil and mat.id or mat[1]
local matQty = mat.qty ~= nil and mat.qty or mat[2]
local matText = ''


if i > 1 then table.insert(resultPart, '<br/>') end
-- Rows
if matID >= 0 then
for i, row in ipairs(useArray) do
-- Item
local qty = row.qty ~= nil and row.qty or 1
local matItem = Items.getItemByID(matID)
local iconType = row.type ~= nil and row.type or 'item'
if matItem == nil then
local iconName = row.item.name
matText = 'ERROR: Failed to find item with ID ' .. matID .. '[[Category:Pages with Script Errors]]'
if row.skill == 'Agility' then
else
iconName = 'Agility'
matText = Icons.Icon({matItem.name, type='item', qty=matQty})
end
local typeName = row.skill ~= nil and row.skill or ''
local typeText = typeTextList[typeName] or Icons.Icon({typeName, type='skill'}) or ''
local reqVal, reqText = row.reqVal, 'None'
if type(row.req) == 'number' then
reqVal = row.req
reqText = Icons._SkillReq(typeName, row.req)
elseif type(row.req) == 'string' then
reqText = row.req
end
local xpVal, xpText = 0, 'N/A'
if type(row.xp) == 'string' then
xpText = row.xp
elseif type(row.xp) == 'number' then
xpVal = row.xp
xpText = Shared.formatnum(row.xp) .. ' ' .. Icons.Icon({typeName, type='skill', notext=true}) .. ' XP'
end
local matRow = {}
if type(row.mats) == 'table' then
for j, itemCost in ipairs(row.mats) do
local matItemID = itemCost.id or itemCost[1] or -1
local matItem = Items.getItemByID(matItemID)
local matQty = itemCost.quantity or itemCost[2] or 1
if matItem == nil then
table.insert(matRow, Shared.printError('Failed to find item with ID "' .. itemCost.id .. '"'))
elseif type(matQty) == 'number' then
table.insert(matRow, Icons.Icon({matItem.name, type='item', qty=matQty}))
else
table.insert(matRow, Icons.Icon({matItem.name, type='item'}))
end
end
end
if row.gp ~= nil then
local gpText = nil
if type(row.gp) == 'number' and row.gp > 0 then
gpText = Icons.GP(row.gp)
elseif type(row.gp) == 'string' then
gpText = row.gp
end
table.insert(matRow, gpText)
end
if row.sc ~= nil then
local scText = nil
if type(row.sc) == 'number' and row.sc > 0 then
scText = Icons.SC(row.sc)
elseif type(row.sc) == 'string' then
scText = row.sc
end
table.insert(matRow, scText)
end
if row.rc ~= nil then
local rcText = nil
if type(row.rc) == 'number' and row.rc > 0 then
rcText = Icons.RC(row.rc)
elseif type(row.rc) == 'string' then
rcText = row.rc
end
end
elseif matID == -4 then
table.insert(matRow, rcText)
-- GP
end
matText = Icons.GP(SkillData.Summoning.Settings.recipeGPCost)
-- Item created
elseif matID == -5 then
table.insert(resultPart, '\r\n|-\r\n|data-sort-value="' .. row.item.name .. '"| ')
-- Slayer Coins
table.insert(resultPart, Icons.Icon({iconName, row.item.name, type=iconType, notext=true, size=50}))
matText = Icons.SC(SkillData.Summoning.Settings.recipeGPCost)
table.insert(resultPart, '\r\n| ')
else
if qty > 1 then
matText = 'ERROR: Unknown item ID: ' .. matID .. ' [[Category:Pages with Script Errors]]'
table.insert(resultPart, "'''" .. Shared.formatnum(qty) .. "x''' ")
end
table.insert(resultPart, Icons.Icon({iconName, row.item.name, type=iconType, noicon=true}))
-- Type
table.insert(resultPart, '\r\n|data-sort-value="' .. typeName .. '"| ' .. typeText)
-- Requirements
table.insert(resultPart, '\r\n|style="text-align:right;"')
if row.reqVal ~= nil then
table.insert(resultPart, ' data-sort-value="' .. reqVal .. '"')
end
end
table.insert(resultPart, matText)
table.insert(resultPart, '| ' .. reqText)
-- XP
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. xpVal .. '"| ' .. xpText)
-- Ingredients
table.insert(resultPart, '\r\n| ' .. table.concat(matRow, '<br/>'))
end
end
if row.gp ~= nil then table.insert(resultPart, '<br/>'..Icons.GP(row.gp)) end
table.insert(resultPart, '\r\n|}')
end
end
 
local spellUseTable = p._getSpellUseTable(item)
--Agility obstacles are weird and get their own section
if spellUseTable ~= nil and spellUseTable ~= '' then
for i, obst in Shared.skpairs(obstacles) do
table.insert(resultPart, '\r\n===' .. Icons.Icon({'Magic', type='skill', size=30}) .. '===\r\n' .. spellUseTable)
table.insert(resultPart, '\r\n|-\r\n|')
table.insert(resultPart, Icons.Icon({"Agility", type="skill", size="50", notext=true}))
table.insert(resultPart, '||[[Agility#Obstacles|'..obst.name..']]')
table.insert(resultPart, '||'..Icons.Icon({"Agility", type="skill"}))
 
--Adding the requirements for the Agility Obstacle
local reqArray = {}
if obst.category == nil then --nil category means this is a passive pillar
table.insert(reqArray, Icons._SkillReq('Agility', 99))
elseif obst.category > 0 then --Otherwise it's category * 10
table.insert(reqArray, Icons._SkillReq('Agility', obst.category * 10))
end
--Then the other skill levels if any are added
if obst.requirements ~= nil and obst.requirements.skillLevel ~= nil then
for j, req in Shared.skpairs(obst.requirements.skillLevel) do
table.insert(reqArray, Icons._SkillReq(Constants.getSkillName(req[1]), req[2]))
end
end
table.insert(resultPart, '||style="text-align:right"|'..table.concat(reqArray, '<br/>'))
 
--Just including 'N/A' for XP since it doesn't really apply for Agility Obstacles
table.insert(resultPart, '||style="text-align:right"|N/A')
 
--Finally the cost
local cost = obst.cost
local costArray = {}
if cost.gp ~= nil and cost.gp > 0 then
table.insert(costArray, Icons.GP(cost.gp))
end
if cost.slayerCoins ~= nil and cost.slayerCoins > 0 then
table.insert(costArray, Icons.SC(cost.slayerCoins))
end
for j, mat in Shared.skpairs(cost.items) do
local item = Items.getItemByID(mat[1])
table.insert(costArray, Icons.Icon({item.name, type="item", qty=mat[2]}))
end
 
table.insert(resultPart, '||'..table.concat(costArray, '<br/>'))
 
end
end
 
if Shared.tableIsEmpty(resultPart) then
table.insert(resultPart, '\r\n|}')
return ''
if string.len(spellUseTable) > 0 then
else
table.insert(resultPart, '\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable)
return '==Uses==\r\n' .. table.concat(resultPart)
end
end
return '==Uses==\r\n'..table.concat(resultPart)
end
end


Line 667: Line 662:
local item = Items.getItem(itemName)
local item = Items.getItem(itemName)
if item == nil then
if item == nil then
return "ERROR: No item named "..itemName.." exists in the data module"
return Shared.printError('No item named "' .. itemName .. '" exists in the data module')
end
end


Line 674: Line 669:


function p._getSpellUseTable(item)
function p._getSpellUseTable(item)
local spellList = Magic.getSpellsForItem(item.id, true)
local spellList = Magic.getSpellsUsingItem(item.id, true)
--Bail immediately if no spells are found
--Bail immediately if no spells are found
if Shared.tableCount(spellList) == 0 then
if Shared.tableIsEmpty(spellList) then
return ''
return ''
end
--Adding a check for if the Items column is needed
local hasItems = false
for i, spell in pairs(spellList) do
if Magic._getSpellItems(spell) ~= '' then
hasItems = true
break
end
end
end


Line 685: Line 689:
table.insert(resultPart, '!!Type!!style="width:275px"|Description')
table.insert(resultPart, '!!Type!!style="width:275px"|Description')
table.insert(resultPart, '!!Runes')
table.insert(resultPart, '!!Runes')
if hasItems then
table.insert(resultPart, '!!Item Cost')
end
for i, spell in pairs(spellList) do
for i, spell in pairs(spellList) do
local rowPart = {}
local rowPart = {}
table.insert(rowPart, '\r\n|-\r\n|data-sort-value="'..spell.name..'"|')
table.insert(rowPart, '\r\n|-\r\n|data-sort-value="'..spell.name..'"|')
local iconType = (spell.type == 'Auroras' and 'aurora') or (spell.type == 'Curses' and 'curse') or 'spell'
local iconType = Magic._getSpellIconType(spell)
table.insert(rowPart, Icons.Icon({spell.name, type=iconType, notext=true, size=50}))
table.insert(rowPart, Icons.Icon({spell.name, type=iconType, notext=true, size=50}))
table.insert(rowPart, '||'..Icons.Icon({spell.name, type=iconType, noicon=true}))
table.insert(rowPart, '||'..Icons.Icon({spell.name, type=iconType, noicon=true}))
table.insert(rowPart, '||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level))
table.insert(rowPart, '||data-sort-value="'..spell.level..'"|'..Magic._getSpellRequirements(spell))
--Handle required items/dungeon clears
table.insert(rowPart, '||data-sort-value="'.. spell.spellBook ..'"|')
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
table.insert(rowPart, Magic.getSpellTypeLink(spell.spellBook))
local reqItem = Items.getItemByID(spell.requiredItem)
table.insert(rowPart, '<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped')
end
if spell.requiredDungeonCompletion ~= nil then
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
table.insert(rowPart, '<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears')
end
table.insert(rowPart, '||data-sort-value="'..Magic.getSpellTypeIndex(spell.type)..'"|')
table.insert(rowPart, Magic.getSpellTypeLink(spell.type))
table.insert(rowPart, '||'..Magic._getSpellStat(spell, 'description'))
table.insert(rowPart, '||'..Magic._getSpellStat(spell, 'description'))
table.insert(rowPart, '||style="text-align:center"|')
table.insert(rowPart, '||style="text-align:center"|')
table.insert(rowPart, Magic._getSpellRunes(spell))
table.insert(rowPart, Magic._getSpellRunes(spell))
if hasItems then
table.insert(rowPart, '||style="text-align:right"|')
table.insert(rowPart, Magic._getSpellItems(spell))
end
table.insert(resultPart, table.concat(rowPart))
table.insert(resultPart, table.concat(rowPart))
end
end
Line 717: Line 721:
local item = Items.getItem(itemName)
local item = Items.getItem(itemName)
if item == nil then
if item == nil then
return "ERROR: No item named "..itemName.." exists in the data module"
return Shared.printError('No item named "' .. itemName .. '" exists in the data module')
end
end


return p._getSpellUseTable(item)
return p._getSpellUseTable(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',
'Garum Seeds',
'Rune Essence',
'Runite Bar',
'Water Rune',
'Steam Rune',
'Controlled Heat Potion II',
'Wolf',
'Cyclops',
'Leprechaun',
'Redwood Logs',
'Carrot Cake',
'Carrot Cake (Perfect)',
'Mantalyme Herb',
'Carrot',
'Topaz',
'Rune Essence',
'Infernal Claw',
'Chapeau Noir',
'Stardust',
'Rope',
'Ancient Ring of Mastery',
'Mysterious Stone',
'Mastery Token (Cooking)',
'Gem Gloves',
'Basic Bag',
'Bird Nest'
}
local checkFuncs = {
p.getItemUses,
p.getItemUseTable
}
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