Difference between revisions of "Module:Items/UseTables"
From Melvor Idle
(_getItemUses: Classify items with special attacks as used in combat) |
Falterfire (talk | contribs) (Fixed indenting) |
||
Line 17: | Line 17: | ||
--Brute forcing some item uses to make things easier | --Brute forcing some item uses to make things easier | ||
local itemUseArray = { | local itemUseArray = { | ||
− | + | Agility = {}, | |
− | + | Astrology = {'Stardust', 'Golden Stardust'}, | |
− | + | Attack = {}, | |
− | + | Combat = {'Gold Emerald Ring'}, | |
− | + | Cooking = {'Cooking Gloves', 'Crown of Rhaelyx'}, | |
− | + | Crafting = {'Crown of Rhaelyx'}, | |
− | + | Defence = {}, | |
− | + | Farming = {'Compost', 'Weird Gloop', 'Bob's Rake'}, | |
− | + | Firemaking = {'Crown of Rhaelyx'}, | |
− | + | Fishing = {'Amulet of Fishing', 'Message in a Bottle'}, | |
− | + | Fletching = {'Crown of Rhaelyx'}, | |
− | + | Herblore = {'Crown of Rhaelyx'}, | |
− | + | Hitpoints = {}, | |
− | + | Magic = {}, | |
− | + | Mining = {'Mining Gloves', 'Gem Gloves'}, | |
− | + | Prayer = {}, | |
− | + | Ranged = {}, | |
− | + | Runecrafting = {'Crown of Rhaelyx'}, | |
− | + | Slayer = {}, | |
− | + | Smithing = {'Smithing Gloves', 'Crown of Rhaelyx'}, | |
− | + | Strength = {}, | |
− | + | Summoning = {'Crown of Rhaelyx'}, | |
− | + | Thieving = {'Chapeau Noir', 'Thieving Gloves', 'Gloves of Silence'}, | |
− | + | Woodcutting = {}, | |
− | + | } | |
local potionUseArray = { | 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' | |
} | } | ||
function p._getItemUses(item, asList, addCategories) | function p._getItemUses(item, asList, addCategories) | ||
− | + | local useArray = {} | |
− | + | local categoryArray = {} | |
− | + | local chr = asList and '* ' or '' | |
− | + | --Another fun one. This time getting all the different possible ways an item can be used | |
− | + | --Before anything else, if this is a potion add it to the appropriate override section | |
− | + | if item.masteryID ~= nil and item.masteryID[1] == 19 then | |
− | + | if potionUseArray[item.masteryID[2]] ~= nil then | |
− | + | table.insert(itemUseArray[potionUseArray[item.masteryID[2]]], item.name) | |
− | + | else | |
− | + | table.insert(itemUseArray["Combat"], item.name) | |
+ | end | ||
end | end | ||
− | |||
− | + | --If the item has any modifiers that affect a given skill, add it to those lists | |
− | + | --Added an exception for Mastery Tokens since they were being incorrectly flagged as usable for all skills | |
− | + | 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 | |
− | + | --First things added to the list are non-skill things that are easy to check | |
− | + | if Items.hasCombatStats(item) or item.specialAttacks ~= nil or Shared.contains(itemUseArray.Combat, item.name) then | |
− | + | table.insert(useArray, chr..Icons.Icon({'Combat'})) | |
− | + | end | |
− | + | if item.healsFor ~= nil then | |
− | + | table.insert(categoryArray, '[[Category:Food Items]]') | |
− | + | table.insert(useArray, chr..'[[Food]]') | |
− | + | end | |
− | + | if item.dropTable ~= nil then | |
− | + | table.insert(categoryArray, '[[Category:Openable Items]]') | |
− | + | table.insert(useArray, chr..'[[Chest Drop Tables|Can Be Opened]]') | |
− | + | end | |
− | + | -- Check if the item is an entry requirement for any Slayer area | |
− | + | local isSlayerAreaReq = false | |
− | + | if item.isEquipment then | |
− | + | local slayerAreas = Areas.getAreas(function(area) return area.type == 'slayer' end) | |
− | + | for i, area in pairs(slayerAreas) do | |
− | + | if area.entryRequirements ~= nil and type(area.entryRequirements) == 'table' then | |
− | + | for j, req in pairs(area.entryRequirements) do | |
− | + | if req.type == "SlayerItem" and req.itemID == item.id then | |
− | + | isSlayerAreaReq = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | if isSlayerAreaReq then break end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | --Next, upgrading, crafting, herblore, fletching, and runecrafting since we have to sift through other items for these | |
− | + | local canUpgrade = false | |
− | + | local canCraft = false | |
− | + | local canFletch = false | |
− | + | local canRunecraft = false | |
− | + | local canHerblore = false | |
− | + | local canAgile = false | |
− | + | local canSummon = false | |
− | + | local canCook = false | |
− | + | if item.trimmedItemID ~= nil then | |
− | + | canUpgrade = true | |
− | + | end | |
− | + | for i, item2 in pairs(ItemData.Items) do | |
− | + | if item2.itemsRequired ~= nil then | |
− | + | for j, req in pairs(item2.itemsRequired) do | |
− | + | if req[1] == item.id then | |
− | + | canUpgrade = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.craftReq ~= nil then | |
− | + | for j, req in pairs(item2.craftReq) do | |
− | + | if req.id == item.id then | |
− | + | canCraft = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.fletchReq ~= nil then | |
− | + | for j, req in pairs(item2.fletchReq) do | |
− | + | if req.id == item.id then | |
− | + | canFletch = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.runecraftReq ~= nil then | |
− | + | for j, req in pairs(item2.runecraftReq) do | |
− | + | if req.id == item.id then | |
− | + | canRunecraft = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.herbloreReq ~= nil then | |
− | + | for j, req in pairs(item2.herbloreReq) do | |
− | + | if req.id == item.id then | |
− | + | canHerblore = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.summoningReq ~= nil then | |
− | + | for j, reqSet in pairs(item2.summoningReq) do | |
− | + | for k, req in pairs(reqSet) do | |
− | + | if req.id == item.id then | |
− | + | canSummon = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | ||
− | + | --Handling for new Cooking method | |
− | + | if item2.recipeRequirements ~= nil and item2.recipeRequirements[1] ~= nil then | |
− | + | for j, reqSet in pairs(item2.recipeRequirements) do | |
− | + | for k, req in pairs(reqSet) do | |
− | + | if req.id == item.id then | |
− | + | canCook = true | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | --Check if Agility applies here | |
− | + | canAgile = Shared.tableCount(Agility.getObstaclesForItem(item.id)) > 0 | |
− | + | --Agility | |
− | + | if canAgile or Shared.contains(itemUseArray.Agility, item.name) then | |
− | + | table.insert(useArray, chr..Icons.Icon({'Agility', type='skill'})) | |
− | + | end | |
− | + | --Astrology | |
− | + | if Shared.contains(itemUseArray.Astrology, item.name) then | |
− | + | table.insert(useArray, chr..Icons.Icon({'Astrology', type='skill'})) | |
− | + | end | |
− | + | --Cooking | |
− | + | if canCook or Shared.contains(itemUseArray.Cooking, item.name) then | |
− | + | table.insert(useArray, chr..Icons.Icon({'Cooking', type='skill'})) | |
− | + | 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 item.firemakingID ~= nil 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 item.type == 'Bar' or item.type == 'Ore' 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 | |
− | + | --Other odds and ends: | |
− | + | --Mastery Tokens are tied to 'Mastery' | |
− | + | if item.isToken and item.skill ~= nil then | |
− | + | table.insert(useArray, chr..Icons.Icon({'Mastery'})) | |
− | + | end | |
− | + | --Skillcapes are tied to the appropriate skill | |
− | + | --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'} | |
− | + | if Shared.contains({'Maximum Skillcape', 'Aorpheat's Signet Ring', 'Cape of Completion'}, item.name) then | |
− | + | table.insert(useArray, chr..'All skills') | |
− | + | elseif item.name == 'Magic Skillcape' then | |
− | + | table.insert(useArray, chr..Icons.Icon({'Magic', type='skill'})) | |
− | + | table.insert(useArray, chr..Icons.Icon({'Alt. Magic', type='skill'})) | |
− | + | elseif Shared.contains(item.name, 'Skillcape') and not Shared.contains(ignoreCapes, item.name) then | |
− | + | local skillName = Shared.splitString(item.name, ' ')[1] | |
− | + | --Avoiding double-listing the same skill twice | |
− | + | if not Shared.contains(itemUseArray[skillName], item.name) then | |
− | + | table.insert(useArray, chr..Icons.Icon({skillName, type='skill'})) | |
− | + | 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 | |
− | + | if item.name == 'Charge Stone of Rhaelyx' then | |
− | + | table.insert(useArray, chr..'Powering '..Icons.Icon({'Crown of Rhaelyx', type='item'})) | |
− | + | end | |
− | + | --Some items are needed to make shop purchases | |
− | + | local shopArray = Shop.getItemCostArray(item.id) | |
− | + | if Shared.tableCount(shopArray) > 0 then | |
− | + | table.insert(useArray, chr..Icons.Icon({'Shop'})) | |
− | + | end | |
− | + | if canUpgrade then | |
− | + | if item.canUpgrade or (item.type == 'Armour' and item.canUpgrade == nil) then | |
− | + | table.insert(categoryArray, '[[Category:Upgradeable Items]]') | |
− | + | end | |
− | + | table.insert(useArray, chr..'[[Upgrading Items]]') | |
− | + | end | |
− | + | local resultPart = {} | |
− | + | 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 | ||
function p.getItemUses(frame) | function p.getItemUses(frame) | ||
− | + | local itemName = frame.args ~= nil and frame.args[1] or frame | |
− | + | local item = Items.getItem(itemName) | |
− | + | local addCategories = false | |
− | + | local asList = true | |
− | + | if frame.args ~= nil then | |
− | + | addCategories = frame.args.addCategories ~= nil and frame.args.addCategories ~= '' and frame.args.addCategories ~= 'false' | |
− | + | asList = frame.args.addCategories == nil or frame.args.addCategories == '' or frame.args.addCategories == 'true' | |
− | + | end | |
− | + | if item == nil then | |
− | + | return "ERROR: No item named "..itemName.." exists in the data module" | |
− | + | end | |
− | + | return p._getItemUses(item, asList, addCategories) | |
end | end | ||
function p._getItemUseTable(item) | function p._getItemUseTable(item) | ||
− | + | 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 | |
− | + | for i, item2 in pairs(ItemData.Items) do | |
− | + | if item2.itemsRequired ~= nil then | |
− | + | for j, req in pairs(item2.itemsRequired) do | |
− | + | if req[1] == item.id then | |
− | + | local mat = item2.itemsRequired | |
− | + | local xp = 'N/A' | |
− | + | local rowReq = 'None' | |
− | + | --Potions do have upgrade requirements though | |
− | + | if item2.potionTier ~= nil then | |
− | + | rowReq = Icons._MasteryReq(item2.name, potTierMastery[item2.potionTier]) | |
− | + | end | |
− | + | table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Upgrade', req = rowReq, xp = xp, gp = item2.trimmedGPCost}) | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.craftReq ~= nil then | |
− | + | 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 | |
− | + | if item2.smithReq ~= nil then | |
− | + | for j, req in pairs(item2.smithReq) do | |
− | + | if req.id == item.id then | |
− | + | local mat = item2.smithReq | |
− | + | local xp = item2.smithingXP | |
− | + | local rowReq = item2.smithingLevel | |
− | + | local qty = item2.smithingQty | |
− | + | table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Smithing', 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 | |
− | + | local perfectItem = Items.getItemByID(item2.perfectItem) | |
− | + | table.insert(useArray, {item = perfectItem, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp}) | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.runecraftReq ~= nil then | |
− | + | for j, req in pairs(item2.runecraftReq) do | |
− | + | if req.id == item.id then | |
− | + | local mat = item2.runecraftReq | |
− | + | local xp = item2.runecraftingXP | |
− | + | local rowReq = item2.runecraftingLevel | |
− | + | local qty = item2.runecraftQty | |
− | + | table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Runecrafting', req = rowReq, xp = xp}) | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.herbloreReq ~= nil then | |
− | + | for j, req in pairs(item2.herbloreReq) do | |
− | + | if req.id == item.id then | |
− | + | local potionData = SkillData.Herblore.ItemData[item2.masteryID[2] + 1] | |
− | + | local mat = item2.herbloreReq | |
− | + | local xp = potionData.herbloreXP | |
− | + | --Potions do have upgrade requirements though | |
− | + | local rowReq = Icons._SkillReq('Herblore', potionData.level) | |
− | + | local masteryLvl = potTierMastery[item2.potionTier] | |
− | + | if masteryLvl > 0 then | |
− | + | rowReq = rowReq..'<br/>'..Icons._MasteryReq(item2.name, masteryLvl) | |
− | + | end | |
− | + | local reqVal = potionData.level + (masteryLvl * 0.01) | |
− | + | table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Herblore', reqVal = reqVal, req = rowReq, xp = xp}) | |
− | + | break | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item2.summoningReq ~= nil then | |
− | + | for j, reqSet in pairs(item2.summoningReq) do | |
− | + | for k, req in pairs(reqSet) do | |
− | + | if req.id == item.id then | |
− | + | local mat = Shared.clone(reqSet) | |
− | + | mat[k].qty = math.max(math.floor(1000 / math.max(item.sellsFor, 20)), 1) | |
− | + | local xp = 5 + 2 * math.floor(item2.summoningLevel * 0.2) | |
− | + | local rowReq = item2.summoningLevel | |
− | + | table.insert(useArray, {item = item2, qty = 25, mats = mat, skill = 'Summoning', req = rowReq, xp = xp}) | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | end | |
− | + | if item.grownItemID ~= nil then | |
− | + | local item2 = Items.getItemByID(item.grownItemID) | |
− | + | 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 | |
− | + | --Handle shop purchases using Module:Shop | |
− | + | local shopUses = Shop.getItemCostArray(item.id) | |
− | + | for i, purchase in Shared.skpairs(shopUses) do | |
− | + | local rowReq = Shop.getRequirementString(purchase.unlockRequirements) | |
− | + | local iconType = (purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0) and 'item' or 'upgrade' | |
− | + | 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}) | |
− | + | end | |
− | + | --Finally build the table using what we've learned | |
− | + | table.sort(useArray, function(a, b) | |
− | + | local aReqVal = a.reqVal ~= nil and a.reqVal or a.req | |
− | + | local bReqVal = b.reqVal ~= nil and b.reqVal or b.req | |
− | + | if a.skill ~= b.skill then | |
− | + | return a.skill < b.skill | |
− | + | elseif type(aReqVal) ~= type(bReqVal) then | |
− | + | return tostring(aReqVal) < tostring(bReqVal) | |
− | + | elseif aReqVal ~= bReqVal then | |
− | + | return aReqVal < bReqVal | |
− | + | else | |
− | + | return a.item.name < b.item.name | |
− | + | end end) | |
− | + | local obstacles = Agility.getObstaclesForItem(item.id) | |
− | + | local spellUseTable = p._getSpellUseTable(item) | |
− | + | local resultPart = {} | |
− | + | if Shared.tableCount(useArray) == 0 and Shared.tableCount(obstacles) == 0 then | |
− | + | if string.len(spellUseTable) > 0 then | |
− | + | return '==Uses==\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable | |
− | + | else | |
− | + | return '' | |
− | + | end | |
− | + | end | |
− | + | table.insert(resultPart, '{| class="wikitable sortable"') | |
− | + | table.insert(resultPart, '\r\n!colspan=2|Item Created!!Type!!Requirements!!XP!!Ingredients') | |
− | + | for i, row in pairs(useArray) do | |
− | + | 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 | |
− | + | if matID >= 0 then | |
− | + | -- Item | |
− | + | local matItem = Items.getItemByID(matID) | |
− | + | if matItem == nil then | |
− | + | matText = 'ERROR: Failed to find item with ID ' .. matID .. '[[Category:Pages with Script Errors]]' | |
− | + | else | |
− | + | matText = Icons.Icon({matItem.name, type='item', qty=matQty}) | |
− | + | end | |
− | + | elseif matID == -4 then | |
− | + | -- GP | |
− | + | matText = Icons.GP(SkillData.Summoning.Settings.recipeGPCost) | |
− | + | elseif matID == -5 then | |
− | + | -- Slayer Coins | |
− | + | matText = Icons.SC(SkillData.Summoning.Settings.recipeGPCost) | |
− | + | else | |
− | + | matText = 'ERROR: Unknown item ID: ' .. matID .. ' [[Category:Pages with Script Errors]]' | |
− | + | end | |
− | + | table.insert(resultPart, matText) | |
− | + | end | |
− | + | if row.gp ~= nil then table.insert(resultPart, '<br/>'..Icons.GP(row.gp)) end | |
− | + | end | |
− | + | --Agility obstacles are weird and get their own section | |
− | + | for i, obst in Shared.skpairs(obstacles) do | |
− | + | 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 | |
− | + | table.insert(resultPart, '\r\n|}') | |
− | + | if string.len(spellUseTable) > 0 then | |
− | + | table.insert(resultPart, '\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable) | |
− | + | end | |
− | + | return '==Uses==\r\n'..table.concat(resultPart) | |
end | end | ||
function p.getItemUseTable(frame) | function p.getItemUseTable(frame) | ||
− | + | local itemName = frame.args ~= nil and frame.args[1] or frame | |
− | + | local item = Items.getItem(itemName) | |
− | + | if item == nil then | |
− | + | return "ERROR: No item named "..itemName.." exists in the data module" | |
− | + | end | |
− | + | return p._getItemUseTable(item) | |
end | end | ||
function p._getSpellUseTable(item) | function p._getSpellUseTable(item) | ||
− | + | local spellList = Magic.getSpellsForRune(item.id) | |
− | + | --Bail immediately if no spells are found | |
− | + | if Shared.tableCount(spellList) == 0 then | |
− | + | return '' | |
− | + | end | |
− | + | local resultPart = {} | |
− | + | table.insert(resultPart, '{|class="wikitable sortable"\r\n!colspan="2"|Spell') | |
− | + | table.insert(resultPart, '!!Requirements') | |
− | + | table.insert(resultPart, '!!Type!!style="width:275px"|Description') | |
− | + | table.insert(resultPart, '!!Runes') | |
− | + | for i, spell in pairs(spellList) do | |
− | + | local rowPart = {} | |
− | + | 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' | |
− | + | 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, '||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level)) | |
− | + | --Handle required items/dungeon clears | |
− | + | if spell.requiredItem ~= nil and spell.requiredItem >= 0 then | |
− | + | 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, '||style="text-align:center"|') | |
− | + | table.insert(rowPart, Magic._getSpellRunes(spell)) | |
− | + | table.insert(resultPart, table.concat(rowPart)) | |
− | + | end | |
− | + | --Add the table end and add the table to the result string | |
− | + | table.insert(resultPart, '\r\n|}') | |
− | + | return table.concat(resultPart) | |
end | end | ||
function p.getSpellUseTable(frame) | function p.getSpellUseTable(frame) | ||
− | + | local itemName = frame.args ~= nil and frame.args[1] or frame | |
− | + | local item = Items.getItem(itemName) | |
− | + | if item == nil then | |
− | + | return "ERROR: No item named "..itemName.." exists in the data module" | |
− | + | end | |
− | + | return p._getSpellUseTable(item) | |
end | end | ||
return p | return p |
Revision as of 19:16, 8 December 2021
Documentation for this module may be created at Module:Items/UseTables/doc
local p = {} local MonsterData = mw.loadData('Module:Monsters/data') local ItemData = mw.loadData('Module:Items/data') local SkillData = mw.loadData('Module:Skills/data') local Constants = require('Module:Constants') local Shared = require('Module:Shared') local Magic = require('Module:Magic') local Areas = require('Module:CombatAreas') local Items = require('Module:Items') local Icons = require('Module:Icons') local Agility = require('Module:Skills/Agility') local Shop = require('Module:Shop') --Brute forcing some item uses to make things easier local itemUseArray = { Agility = {}, Astrology = {'Stardust', 'Golden Stardust'}, Attack = {}, Combat = {'Gold Emerald Ring'}, Cooking = {'Cooking Gloves', 'Crown of Rhaelyx'}, Crafting = {'Crown of Rhaelyx'}, Defence = {}, Farming = {'Compost', 'Weird Gloop', 'Bob's Rake'}, Firemaking = {'Crown of Rhaelyx'}, Fishing = {'Amulet of Fishing', 'Message in a Bottle'}, Fletching = {'Crown of Rhaelyx'}, Herblore = {'Crown of Rhaelyx'}, Hitpoints = {}, Magic = {}, Mining = {'Mining Gloves', 'Gem Gloves'}, Prayer = {}, Ranged = {}, Runecrafting = {'Crown of Rhaelyx'}, Slayer = {}, Smithing = {'Smithing Gloves', 'Crown of Rhaelyx'}, Strength = {}, Summoning = {'Crown of Rhaelyx'}, Thieving = {'Chapeau Noir', 'Thieving Gloves', 'Gloves of Silence'}, 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' } function p._getItemUses(item, asList, addCategories) local useArray = {} local categoryArray = {} local chr = asList and '* ' or '' --Another fun one. This time getting all the different possible ways an item can be used --Before anything else, if this is a potion add it to the appropriate override section if item.masteryID ~= nil and item.masteryID[1] == 19 then if potionUseArray[item.masteryID[2]] ~= nil then table.insert(itemUseArray[potionUseArray[item.masteryID[2]]], item.name) else table.insert(itemUseArray["Combat"], item.name) end end --If the item has any modifiers that affect a given skill, add it to those lists --Added an exception for Mastery Tokens since they were being incorrectly flagged as usable for all skills 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 --First things added to the list are non-skill things that are easy to check if Items.hasCombatStats(item) or item.specialAttacks ~= nil or Shared.contains(itemUseArray.Combat, item.name) then table.insert(useArray, chr..Icons.Icon({'Combat'})) end if item.healsFor ~= nil then table.insert(categoryArray, '[[Category:Food Items]]') table.insert(useArray, chr..'[[Food]]') end if item.dropTable ~= nil then table.insert(categoryArray, '[[Category:Openable Items]]') table.insert(useArray, chr..'[[Chest Drop Tables|Can Be Opened]]') end -- Check if the item is an entry requirement for any Slayer area local isSlayerAreaReq = false if item.isEquipment then local slayerAreas = Areas.getAreas(function(area) return area.type == 'slayer' end) for i, area in pairs(slayerAreas) do if area.entryRequirements ~= nil and type(area.entryRequirements) == 'table' then for j, req in pairs(area.entryRequirements) do if req.type == "SlayerItem" and req.itemID == item.id then isSlayerAreaReq = true break end end if isSlayerAreaReq then break end end end end --Next, upgrading, crafting, herblore, fletching, and runecrafting since we have to sift through other items for these local canUpgrade = false local canCraft = false local canFletch = false local canRunecraft = false local canHerblore = false local canAgile = false local canSummon = false local canCook = false if item.trimmedItemID ~= nil then canUpgrade = true end for i, item2 in pairs(ItemData.Items) do if item2.itemsRequired ~= nil then for j, req in pairs(item2.itemsRequired) do if req[1] == item.id then canUpgrade = true break end end end if item2.craftReq ~= nil then for j, req in pairs(item2.craftReq) do if req.id == item.id then canCraft = true break end end end if item2.fletchReq ~= nil then for j, req in pairs(item2.fletchReq) do if req.id == item.id then canFletch = true break end end end if item2.runecraftReq ~= nil then for j, req in pairs(item2.runecraftReq) do if req.id == item.id then canRunecraft = true break end end end if item2.herbloreReq ~= nil then for j, req in pairs(item2.herbloreReq) do if req.id == item.id then canHerblore = true break end end end if item2.summoningReq ~= nil then for j, reqSet in pairs(item2.summoningReq) do for k, req in pairs(reqSet) do if req.id == item.id then canSummon = true break end end end end --Handling for new Cooking method if item2.recipeRequirements ~= nil and item2.recipeRequirements[1] ~= nil then for j, reqSet in pairs(item2.recipeRequirements) do for k, req in pairs(reqSet) do if req.id == item.id then canCook = true break end end end end end --Check if Agility applies here canAgile = Shared.tableCount(Agility.getObstaclesForItem(item.id)) > 0 --Agility if canAgile or Shared.contains(itemUseArray.Agility, item.name) then table.insert(useArray, chr..Icons.Icon({'Agility', type='skill'})) end --Astrology if Shared.contains(itemUseArray.Astrology, item.name) then table.insert(useArray, chr..Icons.Icon({'Astrology', type='skill'})) end --Cooking if canCook or Shared.contains(itemUseArray.Cooking, item.name) then table.insert(useArray, chr..Icons.Icon({'Cooking', type='skill'})) 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 item.firemakingID ~= nil 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 item.type == 'Bar' or item.type == 'Ore' 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 --Other odds and ends: --Mastery Tokens are tied to 'Mastery' if item.isToken and item.skill ~= nil then table.insert(useArray, chr..Icons.Icon({'Mastery'})) end --Skillcapes are tied to the appropriate skill --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'} if Shared.contains({'Maximum Skillcape', 'Aorpheat's Signet Ring', 'Cape of Completion'}, item.name) then table.insert(useArray, chr..'All skills') elseif item.name == 'Magic Skillcape' then table.insert(useArray, chr..Icons.Icon({'Magic', type='skill'})) table.insert(useArray, chr..Icons.Icon({'Alt. Magic', type='skill'})) elseif Shared.contains(item.name, 'Skillcape') and not Shared.contains(ignoreCapes, item.name) then local skillName = Shared.splitString(item.name, ' ')[1] --Avoiding double-listing the same skill twice if not Shared.contains(itemUseArray[skillName], item.name) then table.insert(useArray, chr..Icons.Icon({skillName, type='skill'})) 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 if item.name == 'Charge Stone of Rhaelyx' then table.insert(useArray, chr..'Powering '..Icons.Icon({'Crown of Rhaelyx', type='item'})) end --Some items are needed to make shop purchases local shopArray = Shop.getItemCostArray(item.id) if Shared.tableCount(shopArray) > 0 then table.insert(useArray, chr..Icons.Icon({'Shop'})) end if canUpgrade then if item.canUpgrade or (item.type == 'Armour' and item.canUpgrade == nil) then table.insert(categoryArray, '[[Category:Upgradeable Items]]') end table.insert(useArray, chr..'[[Upgrading Items]]') end local resultPart = {} 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 function p.getItemUses(frame) local itemName = frame.args ~= nil and frame.args[1] or frame local item = Items.getItem(itemName) local addCategories = false local asList = true if frame.args ~= nil then addCategories = frame.args.addCategories ~= nil and frame.args.addCategories ~= '' and frame.args.addCategories ~= 'false' asList = frame.args.addCategories == nil or frame.args.addCategories == '' or frame.args.addCategories == 'true' end if item == nil then return "ERROR: No item named "..itemName.." exists in the data module" end return p._getItemUses(item, asList, addCategories) end function p._getItemUseTable(item) 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 for i, item2 in pairs(ItemData.Items) do if item2.itemsRequired ~= nil then for j, req in pairs(item2.itemsRequired) do if req[1] == item.id then local mat = item2.itemsRequired local xp = 'N/A' local rowReq = 'None' --Potions do have upgrade requirements though if item2.potionTier ~= nil then rowReq = Icons._MasteryReq(item2.name, potTierMastery[item2.potionTier]) end table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Upgrade', req = rowReq, xp = xp, gp = item2.trimmedGPCost}) break end end end if item2.craftReq ~= nil then 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 if item2.smithReq ~= nil then for j, req in pairs(item2.smithReq) do if req.id == item.id then local mat = item2.smithReq local xp = item2.smithingXP local rowReq = item2.smithingLevel local qty = item2.smithingQty table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Smithing', 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 local perfectItem = Items.getItemByID(item2.perfectItem) table.insert(useArray, {item = perfectItem, qty = qty, mats = mat, skill = 'Cooking', req = rowReq, xp = xp}) end end end end end if item2.runecraftReq ~= nil then for j, req in pairs(item2.runecraftReq) do if req.id == item.id then local mat = item2.runecraftReq local xp = item2.runecraftingXP local rowReq = item2.runecraftingLevel local qty = item2.runecraftQty table.insert(useArray, {item = item2, qty = qty, mats = mat, skill = 'Runecrafting', req = rowReq, xp = xp}) break end end end if item2.herbloreReq ~= nil then for j, req in pairs(item2.herbloreReq) do if req.id == item.id then local potionData = SkillData.Herblore.ItemData[item2.masteryID[2] + 1] local mat = item2.herbloreReq local xp = potionData.herbloreXP --Potions do have upgrade requirements though local rowReq = Icons._SkillReq('Herblore', potionData.level) local masteryLvl = potTierMastery[item2.potionTier] if masteryLvl > 0 then rowReq = rowReq..'<br/>'..Icons._MasteryReq(item2.name, masteryLvl) end local reqVal = potionData.level + (masteryLvl * 0.01) table.insert(useArray, {item = item2, qty = 1, mats = mat, skill = 'Herblore', reqVal = reqVal, req = rowReq, xp = xp}) break end end end if item2.summoningReq ~= nil then for j, reqSet in pairs(item2.summoningReq) do for k, req in pairs(reqSet) do if req.id == item.id then local mat = Shared.clone(reqSet) mat[k].qty = math.max(math.floor(1000 / math.max(item.sellsFor, 20)), 1) local xp = 5 + 2 * math.floor(item2.summoningLevel * 0.2) local rowReq = item2.summoningLevel table.insert(useArray, {item = item2, qty = 25, mats = mat, skill = 'Summoning', req = rowReq, xp = xp}) end end end end end if item.grownItemID ~= nil then local item2 = Items.getItemByID(item.grownItemID) 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 --Handle shop purchases using Module:Shop local shopUses = Shop.getItemCostArray(item.id) for i, purchase in Shared.skpairs(shopUses) do local rowReq = Shop.getRequirementString(purchase.unlockRequirements) local iconType = (purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0) and 'item' or 'upgrade' 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}) end --Finally build the table using what we've learned table.sort(useArray, function(a, b) local aReqVal = a.reqVal ~= nil and a.reqVal or a.req local bReqVal = b.reqVal ~= nil and b.reqVal or b.req if a.skill ~= b.skill then return a.skill < b.skill elseif type(aReqVal) ~= type(bReqVal) then return tostring(aReqVal) < tostring(bReqVal) elseif aReqVal ~= bReqVal then return aReqVal < bReqVal else return a.item.name < b.item.name end end) local obstacles = Agility.getObstaclesForItem(item.id) local spellUseTable = p._getSpellUseTable(item) local resultPart = {} if Shared.tableCount(useArray) == 0 and Shared.tableCount(obstacles) == 0 then if string.len(spellUseTable) > 0 then return '==Uses==\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable else return '' end end table.insert(resultPart, '{| class="wikitable sortable"') table.insert(resultPart, '\r\n!colspan=2|Item Created!!Type!!Requirements!!XP!!Ingredients') for i, row in pairs(useArray) do 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 if matID >= 0 then -- Item local matItem = Items.getItemByID(matID) if matItem == nil then matText = 'ERROR: Failed to find item with ID ' .. matID .. '[[Category:Pages with Script Errors]]' else matText = Icons.Icon({matItem.name, type='item', qty=matQty}) end elseif matID == -4 then -- GP matText = Icons.GP(SkillData.Summoning.Settings.recipeGPCost) elseif matID == -5 then -- Slayer Coins matText = Icons.SC(SkillData.Summoning.Settings.recipeGPCost) else matText = 'ERROR: Unknown item ID: ' .. matID .. ' [[Category:Pages with Script Errors]]' end table.insert(resultPart, matText) end if row.gp ~= nil then table.insert(resultPart, '<br/>'..Icons.GP(row.gp)) end end --Agility obstacles are weird and get their own section for i, obst in Shared.skpairs(obstacles) do 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 table.insert(resultPart, '\r\n|}') if string.len(spellUseTable) > 0 then table.insert(resultPart, '\r\n==='..Icons.Icon({'Magic', type='skill', size='30'})..'===\r\n'..spellUseTable) end return '==Uses==\r\n'..table.concat(resultPart) end function p.getItemUseTable(frame) local itemName = frame.args ~= nil and frame.args[1] or frame local item = Items.getItem(itemName) if item == nil then return "ERROR: No item named "..itemName.." exists in the data module" end return p._getItemUseTable(item) end function p._getSpellUseTable(item) local spellList = Magic.getSpellsForRune(item.id) --Bail immediately if no spells are found if Shared.tableCount(spellList) == 0 then return '' end local resultPart = {} table.insert(resultPart, '{|class="wikitable sortable"\r\n!colspan="2"|Spell') table.insert(resultPart, '!!Requirements') table.insert(resultPart, '!!Type!!style="width:275px"|Description') table.insert(resultPart, '!!Runes') for i, spell in pairs(spellList) do local rowPart = {} 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' 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, '||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level)) --Handle required items/dungeon clears if spell.requiredItem ~= nil and spell.requiredItem >= 0 then 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, '||style="text-align:center"|') table.insert(rowPart, Magic._getSpellRunes(spell)) table.insert(resultPart, table.concat(rowPart)) end --Add the table end and add the table to the result string table.insert(resultPart, '\r\n|}') return table.concat(resultPart) end function p.getSpellUseTable(frame) local itemName = frame.args ~= nil and frame.args[1] or frame local item = Items.getItem(itemName) if item == nil then return "ERROR: No item named "..itemName.." exists in the data module" end return p._getSpellUseTable(item) end return p