Module:Shop: Difference between revisions

3,330 bytes added ,  22 October 2022
Update for v1.1
(Generate bank slot cost text in a better supported way)
(Update for v1.1)
Line 1: Line 1:
local p = {}
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 Shared = require('Module:Shared')
local Constants = require('Module:Constants')
local GameData = require('Module:GameData')
local Items = require('Module:Items')
local Items = require('Module:Items')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')
local Constants = require('Module:Constants')


-- Overrides for various items, mostly relating to icon overrides
-- Overrides for various items, mostly relating to icon overrides
local purchOverrides = {
local purchOverrides = {
["Extra Bank Slot"] = { icon = {'Bank Slot', 'upgrade'}, link = 'Bank Slot', cost = Icons.GP(mw.getCurrentFrame():callParserFunction('#tag:math', {'C_b'}) .. '*') },
["Extra Bank Slot"] = { icon = {'Bank Slot', 'upgrade'}, link = 'Bank Slot' },
-- Golbin Raid items
-- Golbin Raid items
["Reduce Wave Skip Cost"] = { icon = {'Melvor Logo', nil}, link = nil },
["Reduce Wave Skip Cost"] = { icon = {'Melvor Logo', nil}, link = nil },
Line 24: Line 20:
["Increase Prayer Level"] = { 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 },
["Increase Prayer Points gained per Wave Completion"] = { icon = {'Prayer', 'skill'}, link = nil },
["Faster Golbin Spawns"] = { icon = {'Timer', nil}, link = nil, incCost = true},
["Faster Golbin Spawns"] = { icon = {'Timer', nil}, link = nil },
["Golbin Crate"] = { icon = {'Golbin Crate', 'upgrade'}, link = nil, incCost = true}
["Golbin Crate"] = { icon = {'Golbin Crate', 'upgrade'}, link = nil }
}
}


function p.getPurchase(purchaseName)
function p.getPurchase(purchaseName)
for categoryName, categoryData in pairs(ShopData.Shop) do
    local purchList = p.getPurchases(function(purch) return p._getPurchaseName(purch) == purchaseName end)
for i, purchase in ipairs(categoryData) do
    if purchList ~= nil and not Shared.tableIsEmpty(purchList) then
if purchase.name == purchaseName then
        return purchList[1]
return p.processPurchase(categoryName, i - 1)
    end
end
end
end
end
end


function p.processPurchase(category, purchaseID)
function p.getPurchases(checkFunc)
local purchase = Shared.clone(ShopData.Shop[category][purchaseID + 1])
    return GameData.getEntities('shopPurchases', checkFunc)
purchase.id = purchaseID
purchase.category = category
return purchase
end
end


Line 70: Line 60:
local purchaseList = {}
local purchaseList = {}
if statName == 'cost' then
if statName == 'cost' then
purchaseList = p.getPurchases(function(cat, purch) return purch.name == purchaseName end)
purchaseList = p.getPurchases(function(purch) return p._getPurchaseName(purch) == purchaseName end)
else
else
purchaseList = {p.getPurchase(purchaseName)}
purchaseList = {p.getPurchase(purchaseName)}
end
end


if Shared.tableCount(purchaseList) == 0 then
if Shared.tableIsEmpty(purchaseList) then
return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]"
return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]"
else
else
Line 84: Line 74:
return table.concat(resultPart, ' or ')
return table.concat(resultPart, ' or ')
end
end
end
function p._getPurchaseName(purch)
    if purch.customName ~= nil then
        return purch.customName
    elseif purch.contains ~= nil then
        if purch.contains.items ~= nil and not Shared.tableIsEmpty(purch.contains.items) then
            local item = Items.getItemByID(purch.contains.items[1].id)
            if item ~= nil then
                return item.name
            end
        elseif 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
end


Line 89: Line 98:
local displayInline = (inline ~= nil and inline or false)
local displayInline = (inline ~= nil and inline or false)
local costArray = {}
local costArray = {}
if cost.gp ~= nil and cost.gp > 0 then
    local currencies = {'gp', 'slayerCoins', 'raidCoins'}
table.insert(costArray, Icons.GP(cost.gp))
    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
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
    if not Shared.tableIsEmpty(costArray) then
table.insert(costArray, table.concat(itemArray, ", "))
        local sep, lastSep = '<br/>', '<br/>'
end
        if displayInline then
end
            sep = ', '
            lastSep = Shared.tableCount(costArray) > 2 and ', and ' or ' and '
        end
        return mw.text.listToText(costArray, sep, lastSep)
    end
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


local sep, lastSep = '<br/>', '<br/>'
    if cost.type == 'BankSlot' then
if displayInline then
        -- Unusual bit of code that basically evaluates wikitext '<math>C_b</math>*'
sep = ', '
        return mw.getCurrentFrame():callParserFunction('#tag:math', {'C_b'}) .. '*'
lastSep = Shared.tableCount(costArray) > 2 and ', and ' or ' and '
    elseif cost.type == 'Linear' and (cost.initial > 0 or cost.scaling > 0) then
end
        return decorator(cost.initial) .. '<br/>+' .. decorator(cost.scaling) .. ' for each purchase'
return mw.text.listToText(costArray, sep, lastSep)
    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
end


function p.getRequirementString(reqs)
function p.getRequirementString(reqs)
if reqs == nil or Shared.tableCount(reqs) == 0 then
if reqs == nil or Shared.tableIsEmpty(reqs) then
return "None"
return 'None'
end
end


local reqArray = {}
local reqArray = {}
if reqs.slayerTaskCompletion ~= nil then
    for i, req in ipairs(reqs) do
for i, taskReq in Shared.skpairs(reqs.slayerTaskCompletion) do
        if req.type == 'SkillLevel' then
local tierName = Constants.getSlayerTierName(taskReq[1])
            local skillName = Constants.getSkillName(req.skillID)
table.insert(reqArray, 'Complete '..taskReq[2]..' '..tierName..' Slayer Tasks')
            if skillName ~= nil then
end
                table.insert(reqArray, Icons._SkillReq(skillName, req.level))
end
            end
 
        elseif req.type == 'DungeonCompletion' then
if reqs.dungeonCompletion ~= nil then
            local dung = GameData.getEntityByID('dungeons', req.dungeonID)
for i, dungReq in Shared.skpairs(reqs.dungeonCompletion) do
            if dung ~= nil then
local dung = AreaData['dungeons'][dungReq[1] + 1]
                local dungStr = 'Complete ' .. Icons.Icon({dung.name, type='dungeon'})
local dungStr = 'Complete '..Icons.Icon({dung.name, type='dungeon'})
                if req.count > 1 then
if dungReq[2] > 1 then
                    dungStr = dungStr .. ' ' .. Shared.formatnum(req.count) .. ' times'
dungStr = dungStr..' '..dungReq[2]..' times'
                end
end
                table.insert(reqArray, dungStr)
table.insert(reqArray, dungStr)
            end
end
        elseif req.type == 'SlayerTask' then
end
            table.insert(reqArray, 'Complete ' .. Shared.formatnum(req.count) .. ' ' .. req.tier .. ' Slayer Tasks')
 
        elseif req.type == 'TownshipTask' then
if reqs.skillLevel ~= nil then
            table.insert(reqArray, 'Complete ' .. Shared.formatnum(req.count) .. ' Township Tasks')
for i, skillReq in Shared.skpairs(reqs.skillLevel) do
        elseif req.type == 'TownshipBuilding' then
local skillName = Constants.getSkillName(skillReq[1])
            local tsData = GameData.getSkillData('melvorD:Township')
table.insert(reqArray, Icons._SkillReq(skillName, skillReq[2]))
            if tsData ~= nil and tsData.buildings ~= nil then
end
                local building = GameData.getEntityByID(tsData.buildings, req.buildingID)
end
                if building ~= nil then
 
                    table.insert(reqArray, 'Have ' .. Shared.formatnum(req.count) .. ' ' .. building.name .. ' actively built in Township')
if reqs.shopItemPurchased ~= nil then
                end
for i, shopReq in Shared.skpairs(reqs.shopItemPurchased) do
            end
local purchase = ShopData.Shop[shopReq[1]][shopReq[2] + 1]
        elseif req.type == 'Completion' then
local isUpgrade = purchase.contains.items == nil or Shared.tableCount(purchase.contains.items) == 0
            local ns = GameData.getEntityByID('namespaces', req.namespace)
table.insert(reqArray, Icons.Icon({purchase.name, type=(isUpgrade and 'upgrade' or 'item')})..' Purchased')
            if ns ~= nil then
end
                table.insert(reqArray, req.percent .. '% ' .. ns.displayName .. ' Completion')
end
            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 reqs.completionPercentage ~= nil then
    if Shared.tableIsEmpty(reqArray) then
table.insert(reqArray, tostring(reqs.completionPercentage) .. '% Completion Log')
        return 'None'
end
    else
 
    return table.concat(reqArray, '<br/>')
if reqs.text ~= nil then
    end
table.insert(reqArray, reqs.text)
end
 
return table.concat(reqArray, '<br/>')
end
end


Line 186: Line 237:
local containArray = {}
local containArray = {}
local GPTotal = 0
local GPTotal = 0
if purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 0 then
if purchase.contains.items ~= nil and not Shared.tableIsEmpty(purchase.contains.items) then
if not asList then
if not asList then
table.insert(containArray, '{| class="wikitable sortable stickyHeader"')
table.insert(containArray, '{| class="wikitable sortable stickyHeader"')
Line 192: Line 243:
table.insert(containArray, '! colspan="2" | Item !! Quantity !! Price')
table.insert(containArray, '! colspan="2" | Item !! Quantity !! Price')
end
end
for i, itemLine in Shared.skpairs(purchase.contains.items) do
for i, itemLine in ipairs(purchase.contains.items) do
local item = Items.getItemByID(itemLine[1])
local item = Items.getItemByID(itemLine.id)
            local itemQty = itemLine.quantity
if asList then
if asList then
table.insert(containArray, Icons.Icon({item.name, type='item', qty=itemLine[2]}))
table.insert(containArray, Icons.Icon({item.name, type='item', qty=itemQty}))
else
else
local GPVal = item.sellsFor * itemLine[2]
local GPVal = item.sellsFor * itemQty
GPTotal = GPTotal + GPVal
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, '|-\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, '| ' .. 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))
table.insert(containArray, '| data-sort-value="' .. GPVal .. '"| ' .. Icons.GP(GPVal))
end
end
end
end
end
end
if purchase.charges ~= nil and purchase.charges > 0 then
if purchase.itemCharges ~= nil and purchase.itemCharges.quantity > 0 then
if asList then
        local gloveItem = Items.getItemByID(purchase.itemCharges.id)
table.insert(containArray, '+'..purchase.charges..' '..Icons.Icon({purchase.name, type='item'})..' Charges')
        local chargeQty = purchase.itemCharges.quantity
else
        if gloveItem ~= nil then
table.insert(containArray, '|-\r\n| style="min-width:25px"| ' .. Icons.Icon({purchase.name, type='item', notext=true, size='25'}))
            if asList then
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, '+'..Shared.formatnum(chargeQty)..' '..Icons.Icon({gloveItem.name, type='item'})..' Charges')
table.insert(containArray, '| data-sort-value="0"| ' .. Icons.GP(0))
            else
end
                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 Shared.tableCount(containArray) > 0 then
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|}')
table.insert(containArray, '|- class="sortbottom"\r\n! colspan="3"| Total\r\n| ' .. Icons.GP(GPTotal) .. '\r\n|}')
end
end
Line 237: Line 293:
function p._getPurchaseBuyLimit(purchase, asList)
function p._getPurchaseBuyLimit(purchase, asList)
if asList == nil then asList = true end
if asList == nil then asList = true end
if type(purchase.buyLimit) == 'table' then
    local defaultLimit = (purchase.defaultBuyLimit == 0 and 'Unlimited') or Shared.formatnum(purchase.defaultBuyLimit)
local limitTable = {}
    if purchase.buyLimitOverrides == nil or Shared.tableIsEmpty(purchase.buyLimitOverrides) then
local gamemodeHasIcon = { 1, 2 }
        -- Same limit for all game modes
-- Populate limitTable for each game mode to be included
        return defaultLimit
for id, modeName in pairs(ConstantData.gamemode) do
    else
if tonumber(id) ~= nil and string.upper(modeName) ~= 'CHAOS' then
        -- The limit varies depending on game mode
local buyLimit = tostring(purchase.buyLimit[id + 1])
        local limitTable = {}
if limitTable[buyLimit] == nil then
        local gamemodeHasIcon = { 'melvorF:Hardcore', 'melvorF:Adventure' }
limitTable[buyLimit] = {}
        for i, buyLimit in ipairs(purchase.buyLimitOverrides) do
end
            local gamemode = GameData.getEntityByID('gamemodes', buyLimit.gamemodeID)
local gamemodeText = '[[Game Mode#' .. modeName .. '|' .. modeName .. ']]'
            if gamemode ~= nil then
if Shared.contains(gamemodeHasIcon, id) then
                local gamemodeText = nil
gamemodeText = Icons.Icon({modeName, notext=(not asList or nil)})
                if Shared.contains(gamemodeHasIcon, gamemode.id) then
end
                    gamemodeText = Icons.Icon({gamemode.name, notext=(not asList or nil)})
table.insert(limitTable[buyLimit], gamemodeText)
                else
end
                    gamemodeText = '[[Game Mode#' .. gamemode.name .. '|' .. gamemode.name .. ']]'
end
                end
                local limitText = (buyLimit.maximum == 0 and 'Unlimited') or Shared.formatnum(buyLimit.maximum)
local numLimits = Shared.tableCount(limitTable)
                table.insert(limitTable, limitText .. (asList and ' for ' or ' ') .. gamemodeText)
local resultPart = {}
            end
for buyLimit, gameModes in Shared.skpairs(limitTable, true) do
        end
local limitText = (buyLimit == '0' and 'Unlimited' or tostring(buyLimit))
        table.insert(limitTable, defaultLimit .. (asList and ' for ' or ' ') .. 'All other game modes')
if numLimits == 1 then
        return table.concat(limitTable, (asList and ' or ' or '<br/>'))
-- Buy limit is the same for all game modes
    end
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
end


Line 286: Line 335:
function p._getPurchaseIcon(iconArgs)
function p._getPurchaseIcon(iconArgs)
local purchase = iconArgs[1]
local purchase = iconArgs[1]
local override = purchOverrides[purchase.name]
    local purchaseName = p._getPurchaseName(purchase)
local override = purchOverrides[purchaseName]
local purchType = p._getPurchaseType(purchase)
local purchType = p._getPurchaseType(purchase)
-- Amend iconArgs before passing to Icons.Icon()
-- Amend iconArgs before passing to Icons.Icon()
iconArgs[1] = ((override ~= nil and override.icon[1]) or purchase.name)
iconArgs[1] = ((override ~= nil and override.icon[1]) or purchaseName)
if override ~= nil then
if override ~= nil then
iconArgs['type'] = override.icon[2]
iconArgs['type'] = override.icon[2]
Line 319: Line 369:
for j, curr in ipairs(costCurrencies) do
for j, curr in ipairs(costCurrencies) do
local costAmt = purchase.cost[curr]
local costAmt = purchase.cost[curr]
if costAmt ~= nil and costAmt > 0 then
        if costAmt.type == 'BankSlot' then
return costAmt
            return -1
end
        elseif costAmt.type == 'Linear' then
end
            return costAmt.initial
        elseif costAmt.type == 'Glove' or costAmt.type == 'Fixed' and costAmt.cost > 0 then
            return costAmt.cost
        end
    end
end
end


Line 382: Line 436:
end
end
for i, purchase in purchIterator(Purchases) do
for i, purchase in purchIterator(Purchases) do
        local purchName = p._getPurchaseName(purchase)
local purchOverride = nil
local purchOverride = nil
if purchOverrides ~= nil then
if purchOverrides ~= nil then
purchOverride = purchOverrides[purchase.name]
purchOverride = purchOverrides[purchName]
end
end


Line 396: Line 451:
else
else
purchLink = purchOverride.link .. '|'
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
end
end


local purchName = purchase.name
if iconNoLink == nil or iconNoLink ~= true then purchName = '[[' .. purchLink .. purchName .. ']]' end
if iconNoLink == nil or iconNoLink ~= true then purchName = '[[' .. purchLink .. purchName .. ']]' end


Line 415: Line 465:
table.insert(resultPart, '| ' .. purchType)
table.insert(resultPart, '| ' .. purchType)
elseif column == 'Description' then
elseif column == 'Description' then
table.insert(resultPart, '| ' .. purchase.description)
table.insert(resultPart, '| ' .. purchase.customDescription)
elseif column == 'Cost' then
elseif column == 'Cost' then
local cellProp = '|style="text-align:right;"'
local cellProp = '|style="text-align:right;"'
Line 465: Line 515:
end
end
end
end
local shopCat = ShopData.Shop[cat]
    local shopCat = GameData.getEntityByName('shopCategories', cat)
if shopCat == nil then
if shopCat == nil then
return 'ERROR: Invalid category '..cat..'[[Category:Pages with script errors]]'
return 'ERROR: Invalid category '..cat..'[[Category:Pages with script errors]]'
else
else
return p._getShopTable(shopCat, options)
        local catPurchases = p.getPurchases(function(purch) return purch.category == shopCat.id end)
return p._getShopTable(catPurchases, options)
end
end
end
end


function p.getItemCostArray(itemID)
function p.getItemCostArray(itemID)
local purchaseArray = {}
    local purchaseArray = {}
 
    for i, purchase in ipairs(GameData.rawData.shopPurchases) do
for catName, cat in Shared.skpairs(ShopData.Shop) do
        if purchase.cost ~= nil and purchase.cost.items ~= nil then
for j, purchase in Shared.skpairs(cat) do
            for j, itemCost in ipairs(purchase.cost.items) do
if purchase.cost.items ~= nil then
                if itemCost.id == itemID then
for k, costLine in Shared.skpairs(purchase.cost.items) do
                    table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemCost.quantity })
if costLine[1] == itemID then
                    break
local temp = p.processPurchase(catName, j - 1)
                end
temp.qty = costLine[2]
            end
table.insert(purchaseArray, temp)
        end
break
    end
end
    return purchaseArray
end
end
end
end
 
return purchaseArray
end
end


function p.getItemSourceArray(itemID)
function p.getItemSourceArray(itemID)
local purchaseArray = {}
    local purchaseArray = {}
 
    for i, purchase in ipairs(GameData.rawData.shopPurchases) do
for catName, cat in Shared.skpairs(ShopData.Shop) do
        if purchase.contains ~= nil and purchase.contains.items ~= nil then
for j, purchase in Shared.skpairs(cat) do
            for j, itemContains in ipairs(purchase.contains.items) do
if purchase.contains.items ~= nil and purchase.contains.items ~= nil then
                if itemContains.id == itemID then
for k, containsLine in Shared.skpairs(purchase.contains.items) do
                    table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemContains.quantity })
if containsLine [1] == itemID then
                    break
local temp = p.processPurchase(catName, j - 1)
                end
temp.qty = containsLine[2]
            end
table.insert(purchaseArray, temp)
        end
break
    end
end
    return purchaseArray
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
end


Line 531: Line 558:
result = result..'\r\n!colspan="2"|'..Icons.Icon({'Shop'})..' Purchase'
result = result..'\r\n!colspan="2"|'..Icons.Icon({'Shop'})..' Purchase'
if purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 1 then
if purchase.contains.items ~= nil and Shared.tableCount(purchase.contains.items) > 1 then
result = result..' - '..Icons.Icon({purchase.name, type='item'})
result = result..' - '..Icons.Icon({p._getPurchaseName(purchase), type='item'})
end
end


Line 551: Line 578:
local purchaseArray = p.getItemSourceArray(item.id)
local purchaseArray = p.getItemSourceArray(item.id)


for i, purchase in Shared.skpairs(purchaseArray) do
for i, purchase in ipairs(purchaseArray) do
table.insert(tableArray, p._getPurchaseTable(purchase))
table.insert(tableArray, p._getPurchaseTable(purchase))
end
end
Line 569: Line 596:


function p.getShopMiscUpgradeTable()
function p.getShopMiscUpgradeTable()
local purchList = p.getPurchases(function(cat, purch) return cat == 'General' and string.find(purch.name, '^Auto Eat') == nil end)
local purchList = p.getPurchases(function(purch) return purch.category == 'melvorD:General' and string.find(purch.id, '^melvorD:Auto_Eat') == nil end)
 
return p._getShopTable(purchList, { columns = { 'Purchase', 'Description', 'Cost', 'Requirements' }, purchaseHeader = 'Upgrade' })
return p._getShopTable(purchList, { columns = { 'Purchase', 'Description', 'Cost', 'Requirements' }, purchaseHeader = 'Upgrade' })
end
end


function p.getShopSkillcapeTable()
function p.getShopSkillcapeTable()
local capeList = p.getPurchases(function(cat, purch) return cat == 'Skillcapes' end)
local capeList = p.getPurchases(function(purch) return purch.category == 'melvorD:Skillcapes' end)
local sortOrderFunc = function(a, b)
local sortOrderFunc = function(a, b)
if a.cost.gp == b.cost.gp then
if a.cost.gp == b.cost.gp then
return a.name < b.name
return p._getPurchaseName(a) < p._getPurchaseName(b)
else
else
return a.cost.gp < b.cost.gp
return a.cost.gp < b.cost.gp
Line 592: Line 620:
function p.getAutoEatTable()
function p.getAutoEatTable()
local resultPart = {}
local resultPart = {}
local purchasesAE = p.getPurchases(function(cat, purch) return string.find(purch.name, '^Auto Eat') ~= nil end)
local purchasesAE = p.getPurchases(function(purch) return purch.category == 'melvorD:General' and string.find(purch.id, '^melvorD:Auto_Eat') ~= nil end)


-- Table header
-- Table header
Line 601: Line 629:
local mods = {["increasedAutoEatEfficiency"] = 0, ["increasedAutoEatHPLimit"] = 0, ["increasedAutoEatThreshold"] = 0}
local mods = {["increasedAutoEatEfficiency"] = 0, ["increasedAutoEatHPLimit"] = 0, ["increasedAutoEatThreshold"] = 0}
for i, purchase in ipairs(purchasesAE) do
for i, purchase in ipairs(purchasesAE) do
        local purchaseName = p._getPurchaseName(purchase)
-- Modifiers must be accumulated as we go
-- Modifiers must be accumulated as we go
for modName, modValue in pairs(mods) do
for modName, modValue in pairs(mods) do
Line 608: Line 637:
end
end


local costAmt = p._getPurchaseSortValue(purchase)
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, '|-\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({purchaseName, type='upgrade', noicon=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.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.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="' .. mods.increasedAutoEatHPLimit .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatHPLimit, 0, 0)) .. '%')
table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. costAmt .. '" | ' .. Icons.GP(costAmt))
table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. p._getPurchaseSortValue(purchase) .. '" | ' .. p.getCostString(purchase.cost, false))
end
end
table.insert(resultPart, '|}')
table.insert(resultPart, '|}')
Line 627: Line 655:
local getGodDungeon =
local getGodDungeon =
function(reqs)
function(reqs)
if reqs.dungeonCompletion ~= nil then
            for i, req in ipairs(reqs) do
for i, areaReq in ipairs(reqs.dungeonCompletion) do
                if req.type == 'DungeonCompletion' and string.find(req.dungeonID, 'God_Dungeon$') ~= nil then
local dung = AreaData['dungeons'][areaReq[1] + 1]
                    return GameData.getEntityByID('dungeons', req.dungeonID)
if string.find(dung.name, 'God Dungeon$') ~= nil then return dung end
                end
end
            end
end
        end
end


local upgradeList = p.getPurchases(
local upgradeList = p.getPurchases(
function(cat, purch)
function(purch)
if cat == 'SkillUpgrades' and purch.unlockRequirements ~= nil then
if purch.category == 'melvorD:SkillUpgrades' and purch.purchaseRequirements ~= nil then
return getGodDungeon(purch.unlockRequirements) ~= nil
return getGodDungeon(purch.purchaseRequirements) ~= nil
end
end
return false
return false
end)
end)
if Shared.tableCount(upgradeList) == 0 then return '' end
if Shared.tableIsEmpty(upgradeList) then
        return ''
    end


-- Table header
-- Table header
Line 651: Line 680:
-- Rows for each God upgrade
-- Rows for each God upgrade
for i, upgrade in ipairs(upgradeList) do
for i, upgrade in ipairs(upgradeList) do
local dung = getGodDungeon(upgrade.unlockRequirements)
        local upgradeName = p._getPurchaseName(upgrade)
local dung = getGodDungeon(upgrade.purchaseRequirements)
local costSortValue = p._getPurchaseSortValue(upgrade)
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, '|-\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({upgrade.name, type='upgrade', noicon=true}))
table.insert(resultPart, '| ' .. Icons.Icon({upgradeName, type='upgrade', noicon=true}))
table.insert(resultPart, '| ' .. upgrade.description)
table.insert(resultPart, '| ' .. upgrade.customDescription)
table.insert(resultPart, '| data-sort-value="' .. dung.name .. '"| ' .. Icons.Icon({dung.name, type='dungeon'}))
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))
table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. costSortValue .. '"| ' .. p.getCostString(upgrade.cost, false))
Line 685: Line 715:
'increasedChancePerfectCookPot', 'increasedChancePerfectCookGlobal'}
'increasedChancePerfectCookPot', 'increasedChancePerfectCookGlobal'}
local totalBonusVal, totalPerfectChance = 0, 0
local totalBonusVal, totalPerfectChance = 0, 0
local utilityList = p.getPurchases(function(cat, purch) return cat == 'SkillUpgrades' and string.find(purch.name, category .. '$') ~= nil end)
local utilityList = p.getPurchases(function(purch) return purch.category == 'melvorD:SkillUpgrades' and string.find(p._getPurchaseName(purch), category .. '$') ~= nil end)
local resultPart = {}
local resultPart = {}
Line 697: Line 727:
-- Row for each upgrade
-- Row for each upgrade
for i, utility in ipairs(utilityList) do
for i, utility in ipairs(utilityList) do
        local utilityName = p._getPurchaseName(utility)
-- First determine bonus XP/doubling chance and perfect chance
-- First determine bonus XP/doubling chance and perfect chance
local bonusVal, perfectChance = 0, 0
local bonusVal, perfectChance = 0, 0
Line 716: Line 747:
totalBonusVal = totalBonusVal + bonusVal
totalBonusVal = totalBonusVal + bonusVal
totalPerfectChance = totalPerfectChance + perfectChance
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, '|-')
table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({utility.name, type='upgrade', size='50', notext=true}))
table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({utilityName, type='upgrade', size='50', notext=true}))
table.insert(resultPart, '|' .. utility.name)
table.insert(resultPart, '|' .. utilityName)
table.insert(resultPart, '|style="text-align:right"|' .. p.getRequirementString(unlockReqs))
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"|' .. p.getCostString(utility.cost, false))
table.insert(resultPart, '|style="text-align:right"|' .. '+' .. bonusVal .. '%')
table.insert(resultPart, '|style="text-align:right"|' .. '+' .. bonusVal .. '%')