Module:Shop
From Melvor Idle
Documentation for this module may be created at Module:Shop/doc
local p = {} local ShopData = mw.loadData('Module:Shop/data') local ConstantData = mw.loadData('Module:Constants/data') -- Data instead of Module:CombatAreas to avoid loop when that module attempts to require Module:Shop local AreaData = require('Module:CombatAreas/data') local Shared = require('Module:Shared') local Items = require('Module:Items') local Icons = require('Module:Icons') local Constants = require('Module:Constants') -- Overrides for various items, mostly relating to icon overrides local purchOverrides = { ["Extra Bank Slot"] = { icon = {'Bank Slot', 'upgrade'}, link = 'Bank Slot', cost = Icons.Icon({'Coins', size = 25, notext = true}) .. ' <span style="font-size:127%; font-family: MathJax_Math; font-style: italic;">C<sub>b</sub></span>*' }, -- Golbin Raid items ["Reduce Wave Skip Cost"] = { icon = {'Melvor Logo', nil}, link = nil }, ["Food Bonus"] = { icon = {'Melvor Logo', nil}, link = nil }, ["Ammo Gatherer"] = { icon = {'Melvor Logo', nil}, link = nil }, ["Rune Pouch"] = { icon = {'Melvor Logo', nil}, link = nil }, ["Increase Starting Prayer Points"] = { icon = {'Melvor Logo', nil}, link = nil }, ["Unlock Combat Passive Slot"] = { icon = {'Melvor Logo', nil}, link = nil }, ["Prayer"] = { icon = {'Prayer', 'skill'}, link = nil }, ["Increase Prayer Level"] = { icon = {'Prayer', 'skill'}, link = nil }, ["Increase Prayer Points gained per Wave Completion"] = { icon = {'Prayer', 'skill'}, link = nil }, ["Faster Golbin Spawns"] = { icon = {'Timer', nil}, link = nil, incCost = true}, ["Golbin Crate"] = { icon = {'Golbin Crate', 'upgrade'}, link = nil, incCost = true} } function p.getPurchase(purchaseName) for categoryName, categoryData in pairs(ShopData.Shop) do for i, purchase in ipairs(categoryData) do if purchase.name == purchaseName then return p.processPurchase(categoryName, i - 1) end end end end function p.processPurchase(category, purchaseID) local purchase = Shared.clone(ShopData.Shop[category][purchaseID + 1]) purchase.id = purchaseID purchase.category = category return purchase end function p._getPurchaseStat(purchase, stat, inline) local displayInline = (inline ~= nil and inline or false) if stat == 'cost' then return p.getCostString(purchase.cost, displayInline) elseif stat == 'requirements' then return p.getRequirementString(purchase.unlockRequirements) elseif stat == 'contents' then return p._getPurchaseContents(purchase, true) elseif stat == 'type' then return p._getPurchaseType(purchase) elseif stat == 'buyLimit' then return p._getPurchaseBuyLimit(purchase, not displayInline) else return purchase[stat] end end function p.getPurchaseStat(frame) local args = frame.args ~= nil and frame.args or frame local purchaseName = args[1] local statName = args[2] local displayInline = (args['inline'] ~= nil and string.lower(args['inline']) == 'true' or false) -- Hack for some purchases existing twice with varying costs (e.g. 'Extra Equipment Set') local purchaseList = {} if statName == 'cost' then purchaseList = p.getPurchases(function(cat, purch) return purch.name == purchaseName end) else purchaseList = {p.getPurchase(purchaseName)} end if Shared.tableCount(purchaseList) == 0 then return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]" else local resultPart = {} for i, purchase in ipairs(purchaseList) do table.insert(resultPart, p._getPurchaseStat(purchase, statName, displayInline)) end return table.concat(resultPart, ' or ') end end function p.getCostString(cost, inline) local displayInline = (inline ~= nil and inline or false) 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 if cost.raidCoins ~= nil and cost.raidCoins > 0 then table.insert(costArray, Icons.RC(cost.raidCoins)) end local itemArray = {} if cost.items ~= nil then for i, itemCost in Shared.skpairs(cost.items) do local item = Items.getItemByID(itemCost[1]) table.insert(itemArray, Icons.Icon({item.name, type="item", notext=(not displayInline and true or nil), qty=itemCost[2]})) end if Shared.tableCount(itemArray) > 0 then table.insert(costArray, table.concat(itemArray, ", ")) end end local sep, lastSep = '<br/>', '<br/>' if displayInline then sep = ', ' lastSep = Shared.tableCount(costArray) > 2 and ', and ' or ' and ' end return mw.text.listToText(costArray, sep, lastSep) end function p.getRequirementString(reqs) if reqs == nil or Shared.tableCount(reqs) == 0 then return "None" end local reqArray = {} if reqs.slayerTaskCompletion ~= nil then for i, taskReq in Shared.skpairs(reqs.slayerTaskCompletion) do local tierName = Constants.getSlayerTierName(taskReq[1]) table.insert(reqArray, 'Complete '..taskReq[2]..' '..tierName..' Slayer Tasks') end end if reqs.dungeonCompletion ~= nil then for i, dungReq in Shared.skpairs(reqs.dungeonCompletion) do local dung = AreaData['dungeons'][dungReq[1] + 1] local dungStr = 'Complete '..Icons.Icon({dung.name, type='dungeon'}) if dungReq[2] > 1 then dungStr = dungStr..' '..dungReq[2]..' times' end table.insert(reqArray, dungStr) end end if reqs.skillLevel ~= nil then for i, skillReq in Shared.skpairs(reqs.skillLevel) do local skillName = Constants.getSkillName(skillReq[1]) table.insert(reqArray, Icons._SkillReq(skillName, skillReq[2])) end end if reqs.shopItemPurchased ~= nil then for i, shopReq in Shared.skpairs(reqs.shopItemPurchased) do local purchase = ShopData.Shop[shopReq[1]][shopReq[2] + 1] local isUpgrade = purchase.contains.items == nil or Shared.tableCount(purchase.contains.items) == 0 table.insert(reqArray, Icons.Icon({purchase.name, type=(isUpgrade and 'upgrade' or 'item')})..' Purchased') end end if reqs.completionPercentage ~= nil then table.insert(reqArray, tostring(reqs.completionPercentage) .. '% Completion Log') end if reqs.text ~= nil then table.insert(reqArray, reqs.text) end return table.concat(reqArray, '<br/>') end function p._getPurchaseType(purchase) if purchase.contains == nil then return 'Unknown' elseif purchase.contains.pet ~= nil then return 'Pet' elseif purchase.contains.modifiers ~= nil or purchase.contains.items == nil or Shared.tableCount(purchase.contains.items) == 0 then return 'Upgrade' elseif purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 1 then return 'Item Bundle' else return 'Item' end end function p._getPurchaseContents(purchase, asList) if asList == nil then asList = true end local containArray = {} local GPTotal = 0 if purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0 then if not asList then table.insert(containArray, '{| class="wikitable sortable stickyHeader"') table.insert(containArray, '|- class="headerRow-0"') table.insert(containArray, '! colspan="2" | Item !! Quantity !! Price') end for i, itemLine in Shared.skpairs(purchase.contains.items) do local item = Items.getItemByID(itemLine[1]) if asList then table.insert(containArray, Icons.Icon({item.name, type='item', qty=itemLine[2]})) else local GPVal = item.sellsFor * itemLine[2] GPTotal = GPTotal + GPVal table.insert(containArray, '|-\r\n| style="min-width:25px"| ' .. Icons.Icon({item.name, type='item', notext=true, size='25'})) table.insert(containArray, '| ' .. Icons.Icon({item.name, type='item', noicon=true}) .. '\r\n| data-sort-value="' .. itemLine[2] .. '" style="text-align:right" | ' .. Shared.formatnum(itemLine[2])) table.insert(containArray, '| data-sort-value="' .. GPVal .. '"| ' .. Icons.GP(GPVal)) end end end if purchase.charges ~= nil and purchase.charges > 0 then if asList then table.insert(containArray, '+'..purchase.charges..' '..Icons.Icon({purchase.name, type='item'})..' Charges') else table.insert(containArray, '|-\r\n| style="min-width:25px"| ' .. Icons.Icon({purchase.name, type='item', notext=true, size='25'})) table.insert(containArray, '| ' .. Icons.Icon({purchase.name, type='item', noicon=true}) .. ' Charges\r\n| data-sort-value="' .. purchase.charges .. '" style="text-align:right" | ' .. Shared.formatnum(purchase.charges)) table.insert(containArray, '| data-sort-value="0"| ' .. Icons.GP(0)) end end if not asList and Shared.tableCount(containArray) > 0 then table.insert(containArray, '|- class="sortbottom"\r\n! colspan="3"| Total\r\n| ' .. Icons.GP(GPTotal) .. '\r\n|}') end local delim = (asList and '<br/>' or '\r\n') return table.concat(containArray, delim) end function p.getPurchaseContents(frame) local args = frame.args ~= nil and frame.args or frame local purchaseName = args[1] local asList = (args[2] ~= nil and string.upper(args[2]) == 'TRUE') local purchase = p.getPurchase(purchaseName) if purchase == nil then return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]" else return p._getPurchaseContents(purchase, asList) end end function p._getPurchaseBuyLimit(purchase, asList) if asList == nil then asList = true end if type(purchase.buyLimit) == 'table' then local limitTable = {} local gamemodeHasIcon = { 1, 2 } -- Populate limitTable for each game mode to be included for id, modeName in pairs(ConstantData.gamemode) do if tonumber(id) ~= nil and string.upper(modeName) ~= 'CHAOS' then local buyLimit = tostring(purchase.buyLimit[id + 1]) if limitTable[buyLimit] == nil then limitTable[buyLimit] = {} end local gamemodeText = '[[Game Mode#' .. modeName .. '|' .. modeName .. ']]' if Shared.contains(gamemodeHasIcon, id) then gamemodeText = Icons.Icon({modeName, notext=(not asList or nil)}) end table.insert(limitTable[buyLimit], gamemodeText) end end local numLimits = Shared.tableCount(limitTable) local resultPart = {} for buyLimit, gameModes in Shared.skpairs(limitTable, true) do local limitText = (buyLimit == '0' and 'Unlimited' or tostring(buyLimit)) if numLimits == 1 then -- Buy limit is the same for all game modes return limitText else table.insert(resultPart, limitText .. (asList and ' for ' or ' ') .. mw.text.listToText(gameModes, ', ', (asList and ' and ' or ', '))) end end return table.concat(resultPart, (asList and ' or ' or '<br/>')) end end function p.getPurchaseBuyLimit(frame) local args = frame.args ~= nil and frame.args or frame local purchaseName = args[1] local asList = (args[2] ~= nil and string.upper(args[2]) == 'TRUE') local purchase = p.getPurchase(purchaseName) if purchase == nil then return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]" else return p._getPurchaseBuyLimit(purchase, asList) end end -- Accept similar arguments to Icons.Icon function p._getPurchaseIcon(iconArgs) local purchase = iconArgs[1] local override = purchOverrides[purchase.name] local purchType = p._getPurchaseType(purchase) -- Amend iconArgs before passing to Icons.Icon() iconArgs[1] = ((override ~= nil and override.icon[1]) or purchase.name) if override ~= nil then iconArgs['type'] = override.icon[2] if override.link == nil then iconArgs['nolink'] = true end else iconArgs['type'] = (purchType == 'Item Bundle' and 'item') or string.lower(purchType) end return Icons.Icon(iconArgs) end function p.getPurchaseIcon(frame) local args = frame.args ~= nil and frame.args or frame local purchaseName = args[1] local purchase = p.getPurchase(purchaseName) if purchase == nil then return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]" else args[1] = purchase return p._getPurchaseIcon(args) end end function p._getPurchaseSortValue(purchase) local costCurrencies = {'gp', 'slayerCoins', 'raidCoins'} for j, curr in ipairs(costCurrencies) do local costAmt = purchase.cost[curr] if costAmt ~= nil and costAmt > 0 then return costAmt end end end function p._getShopTable(Purchases, options) local availableColumns = { 'Purchase', 'Type', 'Description', 'Cost', 'Requirements', 'Buy Limit' } local headerPropsDefault = { ["Purchase"] = 'colspan="2"', ["Cost"] = 'style="min-width:100px"' } local usedColumns, purchHeader, sortOrder, headerProps = {}, 'Purchase', nil, {} -- Process options if specified if options ~= nil and type(options) == 'table' then -- Custom columns if options.columns ~= nil and type(options.columns) == 'table' then for i, column in ipairs(options.columns) do if Shared.contains(availableColumns, column) then table.insert(usedColumns, column) end end end -- Purchase column header text if options.purchaseHeader ~= nil and type(options.purchaseHeader) == 'string' then purchHeader = options.purchaseHeader end -- Custom sort order if options.sortOrder ~= nil and type(options.sortOrder) == 'function' then sortOrder = options.sortOrder end -- Header properties if options.headerProps ~= nil and type(options.headerProps) == 'table' then headerProps = options.headerProps end end -- Use default columns if no custom columns specified if Shared.tableCount(usedColumns) == 0 then usedColumns = availableColumns end if Shared.tableCount(headerProps) == 0 then headerProps = headerPropsDefault end -- Begin output generation local resultPart = {} -- Generate header table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') table.insert(resultPart, '|- class="headerRow-0"') for i, column in ipairs(usedColumns) do local prop = headerProps[column] table.insert(resultPart, '!' .. (prop and prop .. '| ' or ' ') .. (column == 'Purchase' and purchHeader or column)) end local purchIterator = nil if sortOrder == nil then purchIterator = Shared.skpairs else table.sort(Purchases, sortOrder) purchIterator = ipairs end for i, purchase in purchIterator(Purchases) do local purchOverride = nil if purchOverrides ~= nil then purchOverride = purchOverrides[purchase.name] end local purchType = p._getPurchaseType(purchase) local iconNoLink = nil local purchLink = '' local costString = p.getCostString(purchase.cost, false) if purchOverride ~= nil then if purchOverride.link == nil then iconNoLink = true else purchLink = purchOverride.link .. '|' end if purchOverride.cost ~= nil then costString = purchOverride.cost end if purchOverride.incCost then costString = costString .. '<br/>+' .. costString .. ' for each purchase' end end local purchName = purchase.name if iconNoLink == nil or iconNoLink ~= true then purchName = '[[' .. purchLink .. purchName .. ']]' end table.insert(resultPart, '|-') for j, column in ipairs(usedColumns) do if column == 'Purchase' then table.insert(resultPart, '|style="min-width:25px"|' .. p._getPurchaseIcon({purchase, notext=true, size='50'})) --table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({iconName, type=iconType, notext=true, nolink=iconNoLink, size='50'})) table.insert(resultPart, '| ' .. purchName) elseif column == 'Type' then table.insert(resultPart, '| ' .. purchType) elseif column == 'Description' then table.insert(resultPart, '| ' .. purchase.description) elseif column == 'Cost' then local cellProp = '|style="text-align:right;"' local sortValue = p._getPurchaseSortValue(purchase) if sortValue ~= nil then cellProp = cellProp .. ' data-sort-value="' .. sortValue .. '"' end table.insert(resultPart, cellProp .. '| ' .. costString) elseif column == 'Requirements' then table.insert(resultPart, '| ' .. p.getRequirementString(purchase.unlockRequirements)) elseif column == 'Buy Limit' then local buyLimit = p._getPurchaseBuyLimit(purchase, false) local sortValue = (tonumber(buyLimit) == nil and -1 or buyLimit) table.insert(resultPart, '| data-sort-value="' .. sortValue .. '"| ' .. buyLimit) else -- Shouldn't be reached, but will prevent the resulting table becoming horribly mis-aligned if it ever happens table.insert(resultPart, '| ') end end end table.insert(resultPart, '|}') return table.concat(resultPart, '\r\n') end -- getShopTable parameter definition: -- columns: Comma separated values indicating which columns are to be included & the order -- in which they are displayed. -- Values can be any of: Purchase, Type, Description, Cost, Requirements -- columnProps: Comma separated values indicating formatting to be applied to each column. Each -- value must be in the format column:property, e.g. Purchase:colspan="2" -- sortOrder: A function determining the order in which table items appear -- purchaseHeader: Specifies header text for the Purchase column if not 'Purchase' function p.getShopTable(frame) local cat = frame.args ~= nil and frame.args[1] or frame local options = {} if frame.args ~= nil then if frame.args.columns ~= nil then options.columns = Shared.splitString(frame.args.columns, ',') end if frame.args.purchaseHeader ~= nil then options.purchaseHeader = frame.args.purchaseHeader end if frame.args.sortOrder ~= nil then options.sortOrder = frame.args.sortOrder end if frame.args.columnProps ~= nil then local columnPropValues = Shared.splitString(frame.args.columnProps, ',') local columnProps = {} for i, prop in pairs(columnPropValues) do local propName, propValue = string.match(prop, '^([^:]+):(.*)$') if propName ~= nil then columnProps[propName] = propValue end end if Shared.tableCount(columnProps) > 0 then options.headerProps = columnProps end end end local shopCat = ShopData.Shop[cat] if shopCat == nil then return 'ERROR: Invalid category '..cat..'[[Category:Pages with script errors]]' else return p._getShopTable(shopCat, options) end end function p.getItemCostArray(itemID) local purchaseArray = {} for catName, cat in Shared.skpairs(ShopData.Shop) do for j, purchase in Shared.skpairs(cat) do if purchase.cost.items ~= nil then for k, costLine in Shared.skpairs(purchase.cost.items) do if costLine[1] == itemID then local temp = p.processPurchase(catName, j - 1) temp.qty = costLine[2] table.insert(purchaseArray, temp) break end end end end end return purchaseArray end function p.getItemSourceArray(itemID) local purchaseArray = {} for catName, cat in Shared.skpairs(ShopData.Shop) do for j, purchase in Shared.skpairs(cat) do if purchase.contains.items ~= nil and purchase.contains.items ~= nil then for k, containsLine in Shared.skpairs(purchase.contains.items) do if containsLine [1] == itemID then local temp = p.processPurchase(catName, j - 1) temp.qty = containsLine[2] table.insert(purchaseArray, temp) break end end end end end return purchaseArray end function p.getPurchases(checkFunc) local purchaseList = {} for category, purchaseArray in Shared.skpairs(ShopData.Shop) do for i, purchase in Shared.skpairs(purchaseArray) do if checkFunc(category, purchase) then table.insert(purchaseList, p.processPurchase(category, i - 1)) end end end return purchaseList end function p._getPurchaseTable(purchase) local result = '{| class="wikitable"\r\n|-' result = result..'\r\n!colspan="2"|'..Icons.Icon({'Shop'})..' Purchase' if purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 1 then result = result..' - '..Icons.Icon({purchase.name, type='item'}) end result = result..'\r\n|-\r\n!style="text-align:right;"|Cost' result = result..'\r\n|'..p.getCostString(purchase.cost, false) result = result..'\r\n|-\r\n!style="text-align:right;"|Requirements' result = result..'\r\n|'..p.getRequirementString(purchase.unlockRequirements) result = result..'\r\n|-\r\n!style="text-align:right;"|Contains' result = result..'\r\n|style="text-align:right;"|'..p._getPurchaseContents(purchase, true) result = result..'\r\n|}' return result end function p._getItemShopTable(item) local tableArray = {} local purchaseArray = p.getItemSourceArray(item.id) for i, purchase in Shared.skpairs(purchaseArray) do table.insert(tableArray, p._getPurchaseTable(purchase)) end return table.concat(tableArray, '\r\n\r\n') end function p.getItemShopTable(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._getItemShopTable(item) end function p.getShopMiscUpgradeTable() local purchList = p.getPurchases(function(cat, purch) return cat == 'General' and string.find(purch.name, '^Auto Eat') == nil end) return p._getShopTable(purchList, { columns = { 'Purchase', 'Description', 'Cost', 'Requirements' }, purchaseHeader = 'Upgrade' }) end function p.getShopSkillcapeTable() local capeList = p.getPurchases(function(cat, purch) return cat == 'Skillcapes' end) local sortOrderFunc = function(a, b) if a.cost.gp == b.cost.gp then return a.name < b.name else return a.cost.gp < b.cost.gp end end return p._getShopTable(capeList, { columns = { 'Purchase', 'Description', 'Cost' }, purchaseHeader = 'Cape', sortOrder = sortOrderFunc, headerProps = {["Purchase"] = 'colspan="2" style="width:200px;"', ["Cost"] = 'style=width:120px;'} }) end function p.getAutoEatTable() local resultPart = {} local purchasesAE = p.getPurchases(function(cat, purch) return string.find(purch.name, '^Auto Eat') ~= nil end) -- Table header table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') table.insert(resultPart, '|- class="headerRow-0"') table.insert(resultPart, '!colspan="2"|Auto Eat Tier!!Minimum Threshold!!Efficiency!!Max Healing!!Cost') -- Rows for each Auto Eat tier local mods = {["increasedAutoEatEfficiency"] = 0, ["increasedAutoEatHPLimit"] = 0, ["increasedAutoEatThreshold"] = 0} for i, purchase in ipairs(purchasesAE) do -- Modifiers must be accumulated as we go for modName, modValue in pairs(mods) do if purchase.contains.modifiers[modName] ~= nil then mods[modName] = mods[modName] + purchase.contains.modifiers[modName] end end local costAmt = p._getPurchaseSortValue(purchase) table.insert(resultPart, '|-\r\n|style="min-width:25px; text-align:center;" data-sort-value="' .. purchase.name .. '"| ' .. Icons.Icon({purchase.name, type='upgrade', size=50, notext=true})) table.insert(resultPart, '| ' .. Icons.Icon({purchase.name, type='upgrade', noicon=true})) table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. mods.increasedAutoEatThreshold .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatThreshold, 0, 0)) .. '%') table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. mods.increasedAutoEatEfficiency .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatEfficiency, 0, 0)) .. '%') table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. mods.increasedAutoEatHPLimit .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatHPLimit, 0, 0)) .. '%') table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. costAmt .. '" | ' .. Icons.GP(costAmt)) end table.insert(resultPart, '|}') return table.concat(resultPart, '\r\n') end function p.getGodUpgradeTable() local resultPart = {} -- Obtain list of God upgrades: look for skill upgrades which have a dungeon completion -- requirement for an area whose name ends with 'God Dungeon' local getGodDungeon = function(reqs) if reqs.dungeonCompletion ~= nil then for i, areaReq in ipairs(reqs.dungeonCompletion) do local dung = AreaData['dungeons'][areaReq[1] + 1] if string.find(dung.name, 'God Dungeon$') ~= nil then return dung end end end end local upgradeList = p.getPurchases( function(cat, purch) if cat == 'SkillUpgrades' and purch.unlockRequirements ~= nil then return getGodDungeon(purch.unlockRequirements) ~= nil end return false end) if Shared.tableCount(upgradeList) == 0 then return '' end -- Table header table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') table.insert(resultPart, '|- class="headerRow-0"') table.insert(resultPart, '!colspan="2"|God Upgrade!!Effect!!Dungeon!!Cost') -- Rows for each God upgrade for i, upgrade in ipairs(upgradeList) do local dung = getGodDungeon(upgrade.unlockRequirements) local costSortValue = p._getPurchaseSortValue(upgrade) table.insert(resultPart, '|-\r\n|style="min-width:25px; text-align:center;" data-sort-value="' .. upgrade.name .. '"| ' .. Icons.Icon({upgrade.name, type='upgrade', size=50, notext=true})) table.insert(resultPart, '| ' .. Icons.Icon({upgrade.name, type='upgrade', noicon=true})) table.insert(resultPart, '| ' .. upgrade.description) table.insert(resultPart, '| data-sort-value="' .. dung.name .. '"| ' .. Icons.Icon({dung.name, type='dungeon'})) table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. costSortValue .. '"| ' .. p.getCostString(upgrade.cost, false)) end table.insert(resultPart, '|}') return table.concat(resultPart, '\r\n') end function p.getCookingUtilityTable(frame) local category = nil if frame ~= nil then category = frame.args ~= nil and frame.args[1] or frame end local validCategories = {'Cooking Fire', 'Furnace', 'Pot'} if category == nil or not Shared.contains({'Cooking Fire', 'Furnace', 'Pot'}, category) then return 'ERROR: Invalid category specified. Must be one of the following: ' .. mw.text.listToText(validCategories, ', ', ' or ') end local categoryShort = string.match(category, '[^%s]+$') local bonusSkillID = Constants.getSkillID('Cooking') local bonusColMod, bonusColName = nil, nil if category == 'Cooking Fire' then bonusColMod = 'increasedSkillXP' bonusColName = 'Bonus ' .. Icons.Icon({'Cooking', type='skill', notext=true}) .. ' XP' else bonusColMod = 'increasedChanceToDoubleItemsSkill' bonusColName = 'Double Items Chance' end local modsPerfectChance = {'increasedChancePerfectCookFire', 'increasedChancePerfectCookFurnace', 'increasedChancePerfectCookPot', 'increasedChancePerfectCookGlobal'} local totalBonusVal, totalPerfectChance = 0, 0 local utilityList = p.getPurchases(function(cat, purch) return cat == 'SkillUpgrades' and string.find(purch.name, category .. '$') ~= nil end) local resultPart = {} -- Table header table.insert(resultPart, '{| class="wikitable stickyHeader"') table.insert(resultPart, '|- class="headerRow-0"') table.insert(resultPart, '!colspan="4"| !!colspan="2"|' .. bonusColName .. '!!colspan="2"|Bonus Perfect Chance') table.insert(resultPart, '|- class="headerRow-1"') table.insert(resultPart, '!colspan="2"|Name!!Level!!Cost' .. string.rep('!!This ' .. categoryShort .. '!!Total', 2)) -- Row for each upgrade for i, utility in ipairs(utilityList) do -- First determine bonus XP/doubling chance and perfect chance local bonusVal, perfectChance = 0, 0 if type(utility.contains) == 'table' then if type(utility.contains.modifiers) == 'table' then for modName, modVal in pairs(utility.contains.modifiers) do if modName == bonusColMod and type(modVal) == 'table' then -- Bonus XP/doubling for skID, skVal in pairs(modVal) do if skVal[1] == bonusSkillID then bonusVal = bonusVal + skVal[2] end end elseif Shared.contains(modsPerfectChance, modName) then -- Perfect chance perfectChance = perfectChance + modVal end end end end totalBonusVal = totalBonusVal + bonusVal totalPerfectChance = totalPerfectChance + perfectChance -- Mangle unlockRequirements so that it only includes skillLevels local unlockReqs = {} if type(utility.unlockRequirements) == 'table' then unlockReqs['skillLevel'] = utility.unlockRequirements.skillLevel end table.insert(resultPart, '|-') table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({utility.name, type='upgrade', size='50', notext=true})) table.insert(resultPart, '|' .. utility.name) table.insert(resultPart, '|style="text-align:right"|' .. p.getRequirementString(unlockReqs)) table.insert(resultPart, '|style="text-align:right"|' .. p.getCostString(utility.cost, false)) table.insert(resultPart, '|style="text-align:right"|' .. '+' .. bonusVal .. '%') table.insert(resultPart, '|style="text-align:right"|' .. '+' .. totalBonusVal .. '%') table.insert(resultPart, '|style="text-align:right"|' .. '+' .. perfectChance .. '%') table.insert(resultPart, '|style="text-align:right"|' .. '+' .. totalPerfectChance .. '%') end table.insert(resultPart, '|}') return table.concat(resultPart, '\r\n') end return p