|
|
Line 1: |
Line 1: |
| local p = {}
| |
|
| |
|
| local Shared = require('Module:Shared')
| |
| local Constants = require('Module:Constants')
| |
| local GameData = require('Module:GameData')
| |
| local Items = require('Module:Items')
| |
| local Icons = require('Module:Icons')
| |
|
| |
| -- Overrides for various items, mostly relating to icon overrides
| |
| local purchOverrides = {
| |
| ["Extra Bank Slot"] = { icon = {'Bank Slot', 'upgrade'}, link = 'Bank Slot' },
| |
| -- 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 },
| |
| ["Golbin Crate"] = { icon = {'Golbin Crate', 'upgrade'}, link = nil }
| |
| }
| |
|
| |
| function p.getPurchase(purchaseName)
| |
| local purchList = p.getPurchases(function(purch) return p._getPurchaseName(purch) == purchaseName end)
| |
| if purchList ~= nil and not Shared.tableIsEmpty(purchList) then
| |
| return purchList[1]
| |
| end
| |
| end
| |
|
| |
| function p.getPurchaseByID(id)
| |
| return GameData.getEntityByID('shopPurchases', id)
| |
| end
| |
|
| |
| function p.getPurchases(checkFunc)
| |
| return GameData.getEntities('shopPurchases', checkFunc)
| |
| 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.purchaseRequirements)
| |
| 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)
| |
| elseif stat == 'description' then
| |
| return p._getPurchaseDescription(purchase)
| |
| else
| |
| return purchase[stat]
| |
| end
| |
| end
| |
|
| |
| function p.getPurchaseStat(frame)
| |
| local args = frame.args ~= nil and frame.args or frame
| |
| local purchaseName = Shared.fixPagename(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(purch) return p._getPurchaseName(purch) == purchaseName end)
| |
| else
| |
| purchaseList = {p.getPurchase(purchaseName)}
| |
| end
| |
|
| |
| if Shared.tableIsEmpty(purchaseList) 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._getPurchaseName(purch)
| |
| if purch.customName ~= nil then
| |
| return purch.customName
| |
| elseif purch.contains ~= nil then
| |
| local item = nil
| |
| if purch.contains.items ~= nil and not Shared.tableIsEmpty(purch.contains.items) then
| |
| item = Items.getItemByID(purch.contains.items[1].id)
| |
| elseif purch.contains.itemCharges ~= nil and not Shared.tableIsEmpty(purch.contains.itemCharges) then
| |
| item = Items.getItemByID(purch.contains.itemCharges.id)
| |
| end
| |
| if item ~= nil then
| |
| return item.name
| |
| end
| |
| if purch.contains.petID ~= nil then
| |
| local pet = GameData.getEntityByID('pets', purch.contains.petID)
| |
| if pet ~= nil then
| |
| return pet.name
| |
| end
| |
| end
| |
| end
| |
| return ''
| |
| end
| |
|
| |
| function p._getPurchaseDescription(purch)
| |
| if purch.customDescription ~= nil then
| |
| local templateData = p._getPurchaseTemplateData(purch)
| |
| return Shared.applyTemplateData(purch.customDescription, templateData)
| |
| elseif purch.contains ~= nil then
| |
| local item = nil
| |
| if purch.contains.modifiers ~= nil then
| |
| return Constants.getModifiersText(purch.contains.modifiers, false)
| |
| elseif purch.contains.items ~= nil and Shared.tableCount(purch.contains.items) == 1 then
| |
| item = Items.getItemByID(purch.contains.items[1].id)
| |
| elseif purch.contains.itemCharges ~= nil then
| |
| item = Items.getItemByID(purch.contains.itemCharges.id)
| |
| end
| |
| if item ~= nil then
| |
| if item.customDescription ~= nil then
| |
| return item.customDescription
| |
| elseif item.modifiers ~= nil then
| |
| return Constants.getModifiersText(item.modifiers, false)
| |
| end
| |
| end
| |
| end
| |
| return ''
| |
| end
| |
|
| |
| function p.getCostString(cost, inline)
| |
| local displayInline = (inline ~= nil and inline or false)
| |
| local costArray = {}
| |
| local currencies = {'gp', 'slayerCoins', 'raidCoins'}
| |
| for i, currency in ipairs(currencies) do
| |
| if cost[currency] ~= nil then
| |
| local costStr = p.getCurrencyCostString(cost[currency], currency)
| |
| if costStr ~= nil then
| |
| table.insert(costArray, costStr)
| |
| end
| |
| end
| |
| end
| |
| if cost.items ~= nil and not Shared.tableIsEmpty(cost.items) then
| |
| local itemArray = {}
| |
| for i, itemCost in ipairs(cost.items) do
| |
| local item = Items.getItemByID(itemCost.id)
| |
| if item ~= nil then
| |
| table.insert(itemArray, Icons.Icon({item.name, type="item", notext=(not displayInline and true or nil), qty=itemCost.quantity}))
| |
| end
| |
| end
| |
| if not Shared.tableIsEmpty(itemArray) then
| |
| table.insert(costArray, table.concat(itemArray, ', '))
| |
| end
| |
| end
| |
|
| |
| if not Shared.tableIsEmpty(costArray) then
| |
| 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
| |
| end
| |
|
| |
| -- Generates description template data. See: shop.js, getDescriptionTemplateData()
| |
| function p._getPurchaseTemplateData(purchase)
| |
| -- qty is a static value of 1 for Bank slots
| |
| local templateData = { qty = 1 }
| |
| if purchase.contains ~= nil and purchase.contains.items ~= nil then
| |
| for i, itemDef in ipairs(purchase.contains.items) do
| |
| templateData['qty' .. i] = itemDef.quantity
| |
| end
| |
| end
| |
| return templateData
| |
| end
| |
|
| |
| function p.getCurrencyCostString(cost, currency)
| |
| local decoratorList = {
| |
| ["gp"] = Icons.GP,
| |
| ["slayerCoins"] = Icons.SC,
| |
| ["raidCoins"] = Icons.RC
| |
| }
| |
| local decorator = nil
| |
| if currency ~= nil then
| |
| decorator = decoratorList[currency]
| |
| end
| |
| if decorator == nil then
| |
| decorator = function(cost) return cost end
| |
| end
| |
|
| |
| if cost.type == 'BankSlot' then
| |
| -- Unusual bit of code that basically evaluates wikitext '<math>C_b</math>*'
| |
| return mw.getCurrentFrame():callParserFunction('#tag:math', {'C_b'}) .. '*'
| |
| elseif cost.type == 'Linear' and (cost.initial > 0 or cost.scaling > 0) then
| |
| return decorator(cost.initial) .. '<br/>+' .. decorator(cost.scaling) .. ' for each purchase'
| |
| elseif cost.type == 'Glove' or cost.type == 'Fixed' and cost.cost > 0 then
| |
| -- Type Glove exists in game so the Merchan's Permit cost reduction can be applied,
| |
| -- it makes no difference here
| |
| return decorator(cost.cost)
| |
| end
| |
| end
| |
|
| |
| function p.getRequirementString(reqs)
| |
| if reqs == nil or Shared.tableIsEmpty(reqs) then
| |
| return 'None'
| |
| end
| |
|
| |
| local reqArray = {}
| |
| for i, req in ipairs(reqs) do
| |
| if req.type == 'SkillLevel' then
| |
| local skillName = Constants.getSkillName(req.skillID)
| |
| if skillName ~= nil then
| |
| table.insert(reqArray, Icons._SkillReq(skillName, req.level))
| |
| end
| |
| elseif req.type == 'DungeonCompletion' then
| |
| local dung = GameData.getEntityByID('dungeons', req.dungeonID)
| |
| if dung ~= nil then
| |
| local dungStr = 'Complete ' .. Icons.Icon({dung.name, type='dungeon'})
| |
| if req.count > 1 then
| |
| dungStr = dungStr .. ' ' .. Shared.formatnum(req.count) .. ' times'
| |
| end
| |
| table.insert(reqArray, dungStr)
| |
| end
| |
| elseif req.type == 'SlayerTask' then
| |
| table.insert(reqArray, 'Complete ' .. Shared.formatnum(req.count) .. ' ' .. req.tier .. ' Slayer Tasks')
| |
| elseif req.type == 'TownshipTask' then
| |
| table.insert(reqArray, 'Complete ' .. Shared.formatnum(req.count) .. ' Township Tasks')
| |
| elseif req.type == 'TownshipBuilding' then
| |
| local tsData = GameData.getSkillData('melvorD:Township')
| |
| if tsData ~= nil and tsData.buildings ~= nil then
| |
| local building = GameData.getEntityByID(tsData.buildings, req.buildingID)
| |
| if building ~= nil then
| |
| table.insert(reqArray, 'Have ' .. Shared.formatnum(req.count) .. ' ' .. building.name .. ' actively built in Township')
| |
| end
| |
| end
| |
| elseif req.type == 'ShopPurchase' then
| |
| local shopPurch = p.getPurchaseByID(req.purchaseID)
| |
| if shopPurch ~= nil then
| |
| table.insert(reqArray, p._getPurchaseIcon({shopPurch}) .. ' Purchased')
| |
| end
| |
| elseif req.type == 'Completion' then
| |
| local ns = GameData.getEntityByName('namespaces', req.namespace)
| |
| if ns ~= nil then
| |
| table.insert(reqArray, req.percent .. '% ' .. ns.displayName .. ' Completion')
| |
| end
| |
| elseif req.type == 'AllSkillLevels' then
| |
| local reqText = 'Level ' .. req.level .. ' in all skills'
| |
| if req.exceptions ~= nil and not Shared.tableIsEmpty(req.exceptions) then
| |
| local exceptSkills = {}
| |
| for i, skillID in ipairs(req.exceptions) do
| |
| local skillName = Constants.getSkillName(skillID)
| |
| if skillName ~= nil then
| |
| table.insert(exceptSkills, Icons.Icon({skillName, type='skill'}))
| |
| end
| |
| end
| |
| reqText = reqText .. ' except for ' .. table.concat(exceptSkills, ', ')
| |
| end
| |
| table.insert(reqArray, reqText)
| |
| else
| |
| table.insert(reqArray, 'ERROR: Unknown requirement: ' .. (req.type or 'nil') .. '[[Category:Pages with script errors]]')
| |
| end
| |
| end
| |
|
| |
| if Shared.tableIsEmpty(reqArray) then
| |
| return 'None'
| |
| else
| |
| return table.concat(reqArray, '<br/>')
| |
| end
| |
| end
| |
|
| |
| function p._getPurchaseType(purchase)
| |
| if purchase.contains == nil then
| |
| return 'Unknown'
| |
| elseif purchase.contains.petID ~= nil then
| |
| return 'Pet'
| |
| elseif purchase.contains.itemCharges ~= nil then
| |
| return 'Item'
| |
| 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 ~= nil then
| |
| if purchase.contains.items ~= nil and not Shared.tableIsEmpty(purchase.contains.items) 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 ipairs(purchase.contains.items) do
| |
| local item = Items.getItemByID(itemLine.id)
| |
| local itemQty = itemLine.quantity
| |
| if asList then
| |
| table.insert(containArray, Icons.Icon({item.name, type='item', qty=itemQty}))
| |
| else
| |
| local GPVal = item.sellsFor * itemQty
| |
| 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="' .. itemQty .. '" style="text-align:right" | ' .. Shared.formatnum(itemQty))
| |
| table.insert(containArray, '| data-sort-value="' .. GPVal .. '"| ' .. Icons.GP(GPVal))
| |
| end
| |
| end
| |
| end
| |
| if purchase.contains.itemCharges ~= nil and purchase.contains.itemCharges.quantity > 0 then
| |
| local gloveItem = Items.getItemByID(purchase.contains.itemCharges.id)
| |
| local chargeQty = purchase.contains.itemCharges.quantity
| |
| if gloveItem ~= nil then
| |
| if asList then
| |
| table.insert(containArray, '+'..Shared.formatnum(chargeQty)..' '..Icons.Icon({gloveItem.name, type='item'})..' Charges')
| |
| else
| |
| table.insert(containArray, '|-\r\n| style="min-width:25px"| ' .. Icons.Icon({gloveItem.name, type='item', notext=true, size='25'}))
| |
| table.insert(containArray, '| ' .. Icons.Icon({gloveItem.name, type='item', noicon=true}) .. ' Charges\r\n| data-sort-value="' .. chargeQty .. '" style="text-align:right" | ' .. Shared.formatnum(chargeQty))
| |
| table.insert(containArray, '| data-sort-value="0"| ' .. Icons.GP(0))
| |
| end
| |
| end
| |
| end
| |
| end
| |
| if not asList and not Shared.tableIsEmpty(containArray) 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
| |
| local defaultLimit = (purchase.defaultBuyLimit == 0 and 'Unlimited') or Shared.formatnum(purchase.defaultBuyLimit)
| |
| if purchase.buyLimitOverrides == nil or Shared.tableIsEmpty(purchase.buyLimitOverrides) then
| |
| -- Same limit for all game modes
| |
| return defaultLimit
| |
| else
| |
| -- The limit varies depending on game mode
| |
| local limitTable = {}
| |
| local gamemodeHasIcon = { 'melvorF:Hardcore', 'melvorF:Adventure' }
| |
| for i, buyLimit in ipairs(purchase.buyLimitOverrides) do
| |
| local gamemode = GameData.getEntityByID('gamemodes', buyLimit.gamemodeID)
| |
| if gamemode ~= nil then
| |
| local gamemodeText = nil
| |
| if Shared.contains(gamemodeHasIcon, gamemode.id) then
| |
| gamemodeText = Icons.Icon({gamemode.name, notext=(not asList or nil)})
| |
| else
| |
| gamemodeText = '[[Game Mode#' .. gamemode.name .. '|' .. gamemode.name .. ']]'
| |
| end
| |
| local limitText = (buyLimit.maximum == 0 and 'Unlimited') or Shared.formatnum(buyLimit.maximum)
| |
| table.insert(limitTable, limitText .. (asList and ' for ' or ' ') .. gamemodeText)
| |
| end
| |
| end
| |
| table.insert(limitTable, defaultLimit .. (asList and ' for ' or ' ') .. 'All other game modes')
| |
| return table.concat(limitTable, (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 purchaseName = p._getPurchaseName(purchase)
| |
| local override = purchOverrides[purchaseName]
| |
| local purchType = p._getPurchaseType(purchase)
| |
| -- Amend iconArgs before passing to Icons.Icon()
| |
| iconArgs[1] = ((override ~= nil and override.icon[1]) or purchaseName)
| |
| 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 = Shared.fixPagename(args[1])
| |
| local purchase = p.getPurchase(purchaseName)
| |
|
| |
| if purchase == nil then
| |
| return "ERROR: Couldn't find purchase with name '" .. tostring(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.type == 'BankSlot' then
| |
| return -1
| |
| elseif costAmt.type == 'Linear' then
| |
| return costAmt.initial
| |
| elseif costAmt.type == 'Glove' or costAmt.type == 'Fixed' and costAmt.cost > 0 then
| |
| return costAmt.cost
| |
| 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, stickyHeader = {}, 'Purchase', nil, {}, true
| |
|
| |
| -- 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
| |
| -- Sticky header class
| |
| if options.stickyHeader ~= nil then
| |
| if type(options.stickyHeader) == 'boolean' then
| |
| stickyHeader = options.stickyHeader
| |
| elseif type(options.stickyHeader) == 'string' and string.lower(options.stickyHeader) == 'false' then
| |
| stickyHeader = false
| |
| end
| |
| 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 and ' stickyHeader' or '') .. '"')
| |
| 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
| |
|
| |
| if sortOrder == nil then
| |
| Purchases = GameData.sortByOrderTable(Purchases, GameData.rawData.shopDisplayOrder, true)
| |
| else
| |
| table.sort(Purchases, sortOrder)
| |
| end
| |
| for i, purchase in ipairs(Purchases) do
| |
| local purchName = p._getPurchaseName(purchase)
| |
| local purchOverride = nil
| |
| if purchOverrides ~= nil then
| |
| purchOverride = purchOverrides[purchName]
| |
| 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
| |
| end
| |
|
| |
| 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, '| ' .. p._getPurchaseDescription(purchase))
| |
| 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.purchaseRequirements))
| |
| 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'
| |
| -- stickyHeader: Specifies if the table will have a sticky header or not
| |
| 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.stickyHeader ~= nil then options.stickyHeader = frame.args.stickyHeader 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 = GameData.getEntityByName('shopCategories', cat)
| |
| if shopCat == nil then
| |
| return 'ERROR: Invalid category '..cat..'[[Category:Pages with script errors]]'
| |
| else
| |
| local catPurchases = p.getPurchases(function(purch) return purch.category == shopCat.id end)
| |
| return p._getShopTable(catPurchases, options)
| |
| end
| |
| end
| |
|
| |
| function p.getItemCostArray(itemID)
| |
| local purchaseArray = {}
| |
| for i, purchase in ipairs(GameData.rawData.shopPurchases) do
| |
| if purchase.cost ~= nil and purchase.cost.items ~= nil then
| |
| for j, itemCost in ipairs(purchase.cost.items) do
| |
| if itemCost.id == itemID then
| |
| table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemCost.quantity })
| |
| break
| |
| end
| |
| end
| |
| end
| |
| end
| |
| return purchaseArray
| |
| end
| |
|
| |
| function p.getItemSourceArray(itemID)
| |
| local purchaseArray = {}
| |
| for i, purchase in ipairs(GameData.rawData.shopPurchases) do
| |
| if purchase.contains ~= nil then
| |
| if purchase.contains.items ~= nil then
| |
| for j, itemContains in ipairs(purchase.contains.items) do
| |
| if itemContains.id == itemID then
| |
| table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemContains.quantity })
| |
| break
| |
| end
| |
| end
| |
| end
| |
| if purchase.contains.itemCharges ~= nil and purchase.contains.itemCharges.id == itemID then
| |
| table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = 1 })
| |
| end
| |
| end
| |
| end
| |
| return purchaseArray
| |
| 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({p._getPurchaseName(purchase), 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.purchaseRequirements)
| |
|
| |
| 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 ipairs(purchaseArray) do
| |
| table.insert(tableArray, p._getPurchaseTable(purchase.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(purch) return (purch.category == 'melvorD:General' and string.find(purch.id, '^melvorD:Auto_Eat') == nil) or Shared.contains({'melvorTotH:SignOfTheStars', 'melvorTotH:SummonersAltar'}, purch.id) end)
| |
|
| |
| return p._getShopTable(purchList, { columns = { 'Purchase', 'Description', 'Cost', 'Requirements' }, purchaseHeader = 'Upgrade' })
| |
| end
| |
|
| |
| function p._getShopSkillcapeTable(showSuperior)
| |
| local categoryID = (showSuperior and 'melvorTotH:SuperiorSkillcapes') or 'melvorD:Skillcapes'
| |
| local capeList = p.getPurchases(function(purch) return purch.category == categoryID end)
| |
| local sortOrderFunc =
| |
| function(a, b)
| |
| local costA, costB = p._getPurchaseSortValue(a), p._getPurchaseSortValue(b)
| |
| if costA == costB then
| |
| return p._getPurchaseName(a) < p._getPurchaseName(b)
| |
| else
| |
| return costA < costB
| |
| end
| |
| end
| |
| return p._getShopTable(capeList, {
| |
| columns = { 'Purchase', 'Description', 'Cost' },
| |
| purchaseHeader = 'Cape',
| |
| sortOrder = sortOrderFunc,
| |
| stickyHeader = false,
| |
| headerProps = {["Purchase"] = 'colspan="2" style="width:200px;"', ["Cost"] = 'style=width:120px;'}
| |
| })
| |
| end
| |
|
| |
| function p.getShopSkillcapeTable(frame)
| |
| local capeCategory = frame.args ~= nil and frame.args[1] or frame
| |
| local showSuperior = string.lower(capeCategory) == 'superior'
| |
|
| |
| return p._getShopSkillcapeTable(showSuperior)
| |
| end
| |
|
| |
| function p.getSkillcapeTable(frame)
| |
| local skillName = frame.args ~= nil and frame.args[1] or frame
| |
| local capeList = p.getPurchases(function(purch) return Shared.contains({'melvorD:Skillcapes', 'melvorTotH:SuperiorSkillcapes'}, purch.category) and string.find(p._getPurchaseName(purch), skillName) end)
| |
| if Shared.tableIsEmpty(capeList) then
| |
| return ''
| |
| else
| |
| local resultPart = {}
| |
| table.insert(resultPart, '{| class="wikitable"\r\n')
| |
| table.insert(resultPart, '!Skillcape!!Name!!Requirements!!Effect')
| |
| for i, cape in ipairs(capeList) do
| |
| local capeItem = Items.getItemByID(cape.contains.items[1].id)
| |
| if capeItem ~= nil then
| |
| table.insert(resultPart, '\r\n|-\r\n| ' .. Icons.Icon({capeItem.name, type='item', size='60', notext=true}))
| |
| table.insert(resultPart, '\r\n| ' .. Icons.Icon({capeItem.name, type='item', noicon=true}))
| |
| table.insert(resultPart, '\r\n| ' .. p.getRequirementString(cape.purchaseRequirements))
| |
| table.insert(resultPart, '\r\n| ' .. p._getPurchaseDescription(cape))
| |
| end
| |
| end
| |
|
| |
| table.insert(resultPart, '\r\n|}')
| |
| return table.concat(resultPart)
| |
| end
| |
| end
| |
|
| |
| function p.getAutoEatTable()
| |
| local resultPart = {}
| |
| local purchasesAE = p.getPurchases(function(purch) return purch.category == 'melvorD:General' and string.find(purch.id, '^melvorD: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
| |
| local purchaseName = p._getPurchaseName(purchase)
| |
| -- 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
| |
|
| |
| table.insert(resultPart, '|-\r\n|style="min-width:25px; text-align:center;" data-sort-value="' .. purchaseName .. '"| ' .. Icons.Icon({purchaseName, type='upgrade', size=50, notext=true}))
| |
| table.insert(resultPart, '| ' .. Icons.Icon({purchaseName, 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="' .. p._getPurchaseSortValue(purchase) .. '" | ' .. p.getCostString(purchase.cost, false))
| |
| 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)
| |
| for i, req in ipairs(reqs) do
| |
| if req.type == 'DungeonCompletion' and string.find(req.dungeonID, 'God_Dungeon$') ~= nil then
| |
| return GameData.getEntityByID('dungeons', req.dungeonID)
| |
| end
| |
| end
| |
| end
| |
|
| |
| local upgradeList = p.getPurchases(
| |
| function(purch)
| |
| if purch.category == 'melvorD:SkillUpgrades' and purch.purchaseRequirements ~= nil then
| |
| return getGodDungeon(purch.purchaseRequirements) ~= nil
| |
| end
| |
| return false
| |
| end)
| |
| if Shared.tableIsEmpty(upgradeList) 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 upgradeName = p._getPurchaseName(upgrade)
| |
| local dung = getGodDungeon(upgrade.purchaseRequirements)
| |
| local costSortValue = p._getPurchaseSortValue(upgrade)
| |
| table.insert(resultPart, '|-\r\n|style="min-width:25px; text-align:center;" data-sort-value="' .. upgradeName .. '"| ' .. Icons.Icon({upgradeName, type='upgrade', size=50, notext=true}))
| |
| table.insert(resultPart, '| ' .. Icons.Icon({upgradeName, type='upgrade', noicon=true}))
| |
| table.insert(resultPart, '| ' .. p._getPurchaseDescription(upgrade))
| |
| 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(purch) return purch.category == 'melvorD:SkillUpgrades' and string.find(p._getPurchaseName(purch), 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
| |
| local utilityName = p._getPurchaseName(utility)
| |
| -- 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
| |
|
| |
| table.insert(resultPart, '|-')
| |
| table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({utilityName, type='upgrade', size='50', notext=true}))
| |
| table.insert(resultPart, '|' .. utilityName)
| |
| table.insert(resultPart, '|style="text-align:right"|' .. p.getRequirementString(utility.purchaseRequirements))
| |
| 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
| |