Anonymous

Module:Shop: Difference between revisions

From Melvor Idle
m
Changed Ship Table header from 'Survey Time Decrease' to 'Cartography Interval'; This modifier effects more than survey intervals
(getShopMiscUpgradeTable: Mash a few skill upgrades into here for now)
m (Changed Ship Table header from 'Survey Time Decrease' to 'Cartography Interval'; This modifier effects more than survey intervals)
(32 intermediate revisions by 4 users not shown)
Line 4: Line 4:
local Constants = require('Module:Constants')
local Constants = require('Module:Constants')
local GameData = require('Module:GameData')
local GameData = require('Module:GameData')
local Common = require('Module:Common')
local Items = require('Module:Items')
local Items = require('Module:Items')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')
 
local Pets = require('Module:Pets')
-- 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)
function p.getPurchase(purchaseName)
    local purchList = p.getPurchases(function(purch) return p._getPurchaseName(purch) == purchaseName end)
local purchList = p.getPurchases(function(purch) return Common.getPurchaseName(purch) == purchaseName end)
    if purchList ~= nil and not Shared.tableIsEmpty(purchList) then
if purchList ~= nil and not Shared.tableIsEmpty(purchList) then
        return purchList[1]
return purchList[1]
    end
end
end
end


Line 36: Line 21:


function p.getPurchases(checkFunc)
function p.getPurchases(checkFunc)
    return GameData.getEntities('shopPurchases', checkFunc)
return GameData.getEntities('shopPurchases', checkFunc)
end
end


Line 44: Line 29:
return p.getCostString(purchase.cost, displayInline)
return p.getCostString(purchase.cost, displayInline)
elseif stat == 'requirements' then
elseif stat == 'requirements' then
return p.getRequirementString(purchase.purchaseRequirements)
return Common.getRequirementString(purchase.purchaseRequirements, 'None')
elseif stat == 'contents' then
elseif stat == 'contents' then
return p._getPurchaseContents(purchase, true)
return p._getPurchaseContents(purchase, true)
elseif stat == 'type' then
elseif stat == 'type' then
return p._getPurchaseType(purchase)
return Common.getPurchaseType(purchase)
elseif stat == 'buyLimit' then
elseif stat == 'buyLimit' then
return p._getPurchaseBuyLimit(purchase, not displayInline)
return p._getPurchaseBuyLimit(purchase, not displayInline)
elseif stat == 'buyLimitHardcore' then
return p._getPurchaseBuyLimitNumeric(purchase, 'melvorF:Hardcore')
elseif stat == 'description' then
return p._getPurchaseDescription(purchase)
elseif stat =='expansionicon' then
return p._getPurchaseExpansionIcon(purchase)
else
else
return purchase[stat]
return purchase[stat]
Line 58: Line 49:
function p.getPurchaseStat(frame)
function p.getPurchaseStat(frame)
local args = frame.args ~= nil and frame.args or frame
local args = frame.args ~= nil and frame.args or frame
local purchaseName = args[1]
local purchaseName = Shared.fixPagename(args[1])
local statName = args[2]
local statName = args[2]
local displayInline = (args['inline'] ~= nil and string.lower(args['inline']) == 'true' or false)
local displayInline = (args['inline'] ~= nil and string.lower(args['inline']) == 'true' or false)
Line 64: Line 55:
local purchaseList = {}
local purchaseList = {}
if statName == 'cost' then
if statName == 'cost' then
purchaseList = p.getPurchases(function(purch) return p._getPurchaseName(purch) == purchaseName end)
purchaseList = p.getPurchases(function(purch) return Common.getPurchaseName(purch) == purchaseName end)
else
else
purchaseList = {p.getPurchase(purchaseName)}
purchaseList = {p.getPurchase(purchaseName)}
Line 70: Line 61:


if Shared.tableIsEmpty(purchaseList) then
if Shared.tableIsEmpty(purchaseList) then
return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]"
return Shared.printError("Couldn't find purchase with name '" .. purchaseName .. "'")
else
else
local resultPart = {}
local resultPart = {}
Line 80: Line 71:
end
end


function p._getPurchaseName(purch)
function p._getPurchaseExpansionIcon(purch)
    if purch.customName ~= nil then
if purch.id ~= nil then
        return purch.customName
return Icons.getExpansionIcon(purch.id)
    elseif purch.contains ~= nil then
elseif purch.contains ~= nil then
    local item = nil
local item = nil
        if purch.contains.items ~= nil and not Shared.tableIsEmpty(purch.contains.items) then
if purch.contains.items ~= nil and not Shared.tableIsEmpty(purch.contains.items) then
            item = Items.getItemByID(purch.contains.items[1].id)
return Icons.getExpansionIcon(purch.contains.items[1].id)
        elseif purch.contains.itemCharges ~= nil and not Shared.tableIsEmpty(purch.contains.itemCharges) then
elseif purch.contains.itemCharges ~= nil and not Shared.tableIsEmpty(purch.contains.itemCharges) then
        item = Items.getItemByID(purch.contains.itemCharges.id)
return Icons.getExpansionIcon(purch.contains.itemCharges.id)
        end
end
        if item ~= nil then
            return item.name
if purch.contains.petID ~= nil then
        end
return Icons.getExpansionIcon(purch.contains.petID)
        if purch.contains.petID ~= nil then
end
            local pet = GameData.getEntityByID('pets', purch.contains.petID)
end
            if pet ~= nil then
return ''
                return pet.name
            end
        end
    end
    return ''
end
end


Line 109: Line 95:
elseif purch.contains ~= nil then
elseif purch.contains ~= nil then
local item = nil
local item = nil
if purch.contains.items ~= nil and Shared.tableCount(purch.contains.items) == 1 then
if purch.contains.modifiers ~= nil then
return Constants.getModifiersText(purch.contains.modifiers, false)
elseif purch.contains.petID ~= nil then
local pet = Pets.getPetByID(purch.contains.petID)
return Pets._getPetEffect(pet)
elseif purch.contains.items ~= nil and Shared.tableCount(purch.contains.items) == 1 then
item = Items.getItemByID(purch.contains.items[1].id)
item = Items.getItemByID(purch.contains.items[1].id)
elseif purch.contains.itemCharges ~= nil then
elseif purch.contains.itemCharges ~= nil then
Line 128: Line 119:
local displayInline = (inline ~= nil and inline or false)
local displayInline = (inline ~= nil and inline or false)
local costArray = {}
local costArray = {}
    local currencies = {'gp', 'slayerCoins', 'raidCoins'}
local currencies = {'gp', 'slayerCoins', 'raidCoins'}
    for i, currency in ipairs(currencies) do
for i, currency in ipairs(currencies) do
        if cost[currency] ~= nil then
if cost[currency] ~= nil then
            local costStr = p.getCurrencyCostString(cost[currency], currency)
local costStr = p.getCurrencyCostString(cost[currency], currency)
            if costStr ~= nil then
if costStr ~= nil then
                table.insert(costArray, costStr)
table.insert(costArray, costStr)
            end
end
        end
end
    end
end
if cost.items ~= nil and not Shared.tableIsEmpty(cost.items) then
if cost.items ~= nil and not Shared.tableIsEmpty(cost.items) then
        local itemArray = {}
local itemArray = {}
for i, itemCost in ipairs(cost.items) do
for i, itemCost in ipairs(cost.items) do
local item = Items.getItemByID(itemCost.id)
local item = Items.getItemByID(itemCost.id)
            if item ~= nil then
if item ~= nil then
    table.insert(itemArray, Icons.Icon({item.name, type="item", notext=(not displayInline and true or nil), qty=itemCost.quantity}))
table.insert(itemArray, Icons.Icon({item.name, type="item", notext=(not displayInline and true or nil), qty=itemCost.quantity}))
            end
end
end
if not Shared.tableIsEmpty(itemArray) then
table.insert(costArray, table.concat(itemArray, ', '))
end
end
        if not Shared.tableIsEmpty(itemArray) then
            table.insert(costArray, table.concat(itemArray, ', '))
        end
end
end


    if not Shared.tableIsEmpty(costArray) then
if not Shared.tableIsEmpty(costArray) then
        local sep, lastSep = '<br/>', '<br/>'
local sep, lastSep = '<br/>', '<br/>'
        if displayInline then
if displayInline then
            sep = ', '
sep = ', '
            lastSep = Shared.tableCount(costArray) > 2 and ', and ' or ' and '
lastSep = Shared.tableCount(costArray) > 2 and ', and ' or ' and '
        end
end
        return mw.text.listToText(costArray, sep, lastSep)
return mw.text.listToText(costArray, sep, lastSep)
    end
end
end
end


Line 173: Line 164:


function p.getCurrencyCostString(cost, currency)
function p.getCurrencyCostString(cost, currency)
    local decoratorList = {
local decoratorList = {
        ["gp"] = Icons.GP,
["gp"] = Icons.GP,
        ["slayerCoins"] = Icons.SC,
["slayerCoins"] = Icons.SC,
        ["raidCoins"] = Icons.RC
["raidCoins"] = Icons.RC
    }
}
    local decorator = nil
local decorator = nil
    if currency ~= nil then
if currency ~= nil then
        decorator = decoratorList[currency]
decorator = decoratorList[currency]
    end
end
    if decorator == nil then
if decorator == nil then
        decorator = function(cost) return cost end
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
end


local reqArray = {}
if cost.type == 'BankSlot' then
    for i, req in ipairs(reqs) do
-- Unusual bit of code that basically evaluates wikitext '<math>C_b</math>*'
        if req.type == 'SkillLevel' then
return mw.getCurrentFrame():callParserFunction('#tag:math', {'C_b'}) .. '*'
            local skillName = Constants.getSkillName(req.skillID)
elseif cost.type == 'Linear' and (cost.initial > 0 or cost.scaling > 0) then
            if skillName ~= nil then
return decorator(cost.initial) .. '<br/>+' .. decorator(cost.scaling) .. ' for each purchase'
                table.insert(reqArray, Icons._SkillReq(skillName, req.level))
elseif cost.type == 'Glove' or cost.type == 'Fixed' and cost.cost > 0 then
            end
-- Type Glove exists in game so the Merchant's Permit cost reduction can be applied,
        elseif req.type == 'DungeonCompletion' then
-- it makes no difference here
            local dung = GameData.getEntityByID('dungeons', req.dungeonID)
return decorator(cost.cost)
            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.getEntityByID('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.pet ~= 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
end
end
Line 295: Line 202:
for i, itemLine in ipairs(purchase.contains.items) do
for i, itemLine in ipairs(purchase.contains.items) do
local item = Items.getItemByID(itemLine.id)
local item = Items.getItemByID(itemLine.id)
            local itemQty = itemLine.quantity
local itemQty = itemLine.quantity
if asList then
if asList then
table.insert(containArray, Icons.Icon({item.name, type='item', qty=itemQty}))
table.insert(containArray, Icons.Icon({item.name, type='item', qty=itemQty}))
Line 301: Line 208:
local GPVal = item.sellsFor * itemQty
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| class="table-img"| ' .. 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="'..item.name..'"|'.. Icons.getExpansionIcon(item.id) .. 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
Line 308: Line 215:
end
end
if purchase.contains.itemCharges ~= nil and purchase.contains.itemCharges.quantity > 0 then
if purchase.contains.itemCharges ~= nil and purchase.contains.itemCharges.quantity > 0 then
        local gloveItem = Items.getItemByID(purchase.contains.itemCharges.id)
local gloveItem = Items.getItemByID(purchase.contains.itemCharges.id)
        local chargeQty = purchase.contains.itemCharges.quantity
local chargeQty = purchase.contains.itemCharges.quantity
        if gloveItem ~= nil then
if gloveItem ~= nil then
            if asList then
if asList then
                table.insert(containArray, '+'..Shared.formatnum(chargeQty)..' '..Icons.Icon({gloveItem.name, type='item'})..' Charges')
table.insert(containArray, '+'..Shared.formatnum(chargeQty)..' '..Icons.Icon({gloveItem.name, type='item'})..' Charges')
            else
else
                table.insert(containArray, '|-\r\n| style="min-width:25px"| ' .. Icons.Icon({gloveItem.name, type='item', notext=true, size='25'}))
table.insert(containArray, '|-\r\n| class="table-img"| ' .. 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, '| ' .. 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))
table.insert(containArray, '| data-sort-value="0"| ' .. Icons.GP(0))
            end
end
        end
end
end
end
end
end
Line 331: Line 238:
function p.getPurchaseContents(frame)
function p.getPurchaseContents(frame)
local args = frame.args ~= nil and frame.args or frame
local args = frame.args ~= nil and frame.args or frame
local purchaseName = args[1]
local purchaseName = Shared.fixPagename(args[1])
local asList = (args[2] ~= nil and string.upper(args[2]) == 'TRUE')
local asList = (args[2] ~= nil and string.upper(args[2]) == 'TRUE')
local purchase = p.getPurchase(purchaseName)
local purchase = p.getPurchase(purchaseName)


if purchase == nil then
if purchase == nil then
return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]"
return Shared.printError("Couldn't find purchase with name '" .. purchaseName .. "'")
else
else
return p._getPurchaseContents(purchase, asList)
return p._getPurchaseContents(purchase, asList)
end
end
end
function p._getPurchaseBuyLimitNumeric(purchase, gamemodeID)
local buyLimit = (purchase.defaultBuyLimit > 0 and purchase.defaultBuyLimit)
if not Shared.tableIsEmpty(purchase.buyLimitOverrides) then
local gamemodeLimit = GameData.getEntityByProperty(purchase.buyLimitOverrides, 'gamemodeID', gamemodeID)
if gamemodeLimit ~= nil and gamemodeLimit.maximum ~= nil then
buyLimit = gamemodeLimit.maximum
end
end
return buyLimit
end
end


function p._getPurchaseBuyLimit(purchase, asList)
function p._getPurchaseBuyLimit(purchase, asList)
if asList == nil then asList = true end
if asList == nil then asList = true end
    local defaultLimit = (purchase.defaultBuyLimit == 0 and 'Unlimited') or Shared.formatnum(purchase.defaultBuyLimit)
local defaultLimit = (purchase.defaultBuyLimit == 0 and 'Unlimited') or Shared.formatnum(purchase.defaultBuyLimit)
    if purchase.buyLimitOverrides == nil or Shared.tableIsEmpty(purchase.buyLimitOverrides) then
if purchase.buyLimitOverrides == nil or Shared.tableIsEmpty(purchase.buyLimitOverrides) then
        -- Same limit for all game modes
-- Same limit for all game modes
        return defaultLimit
return defaultLimit
    else
else
        -- The limit varies depending on game mode
-- The limit varies depending on game mode
        local limitTable = {}
local limitTable = {}
        local gamemodeHasIcon = { 'melvorF:Hardcore', 'melvorF:Adventure' }
local gamemodeHasIcon = { 'melvorF:Hardcore', 'melvorF:Adventure' }
        for i, buyLimit in ipairs(purchase.buyLimitOverrides) do
for i, buyLimit in ipairs(purchase.buyLimitOverrides) do
            local gamemode = GameData.getEntityByID('gamemodes', buyLimit.gamemodeID)
local gamemode = GameData.getEntityByID('gamemodes', buyLimit.gamemodeID)
            if gamemode ~= nil then
if gamemode ~= nil then
                local gamemodeText = nil
local gamemodeName = Shared.splitString(gamemode.name, ' ')[1]
                if Shared.contains(gamemodeHasIcon, gamemode.id) then
local gamemodeText = nil
                    gamemodeText = Icons.Icon({gamemode.name, notext=(not asList or nil)})
if Shared.contains(gamemodeHasIcon, gamemode.id) then
                else
gamemodeText = Icons.Icon({gamemodeName, notext=(not asList or nil)})
                    gamemodeText = '[[Game Mode#' .. gamemode.name .. '|' .. gamemode.name .. ']]'
else
                end
gamemodeText = '[[Game Mode#' .. gamemodeName .. '|' .. gamemodeName .. ']]'
                local limitText = (buyLimit.maximum == 0 and 'Unlimited') or Shared.formatnum(buyLimit.maximum)
end
                table.insert(limitTable, limitText .. (asList and ' for ' or ' ') .. gamemodeText)
local limitText = (buyLimit.maximum == 0 and 'Unlimited') or Shared.formatnum(buyLimit.maximum)
            end
table.insert(limitTable, limitText .. (asList and ' for ' or ' ') .. gamemodeText)
        end
end
        table.insert(limitTable, defaultLimit .. (asList and ' for ' or ' ') .. 'All other game modes')
end
        return table.concat(limitTable, (asList and ' or ' or '<br/>'))
table.insert(limitTable, defaultLimit .. (asList and ' for ' or ' ') .. 'All other game modes')
    end
return table.concat(limitTable, (asList and ' or ' or '<br/>'))
end
end
end


Line 377: Line 296:
if purchase == nil then
if purchase == nil then
return "ERROR: Couldn't find purchase with name '" .. purchaseName .. "'[[Category:Pages with script errors]]"
return Shared.printError("Couldn't find purchase with name '" .. purchaseName .. "'")
else
else
return p._getPurchaseBuyLimit(purchase, asList)
return p._getPurchaseBuyLimit(purchase, asList)
end
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
end


function p.getPurchaseIcon(frame)
function p.getPurchaseIcon(frame)
local args = frame.args ~= nil and frame.args or frame
local args = frame.args ~= nil and frame.args or frame
local purchaseName = args[1]
local purchaseName = Shared.fixPagename(args[1])
local purchase = p.getPurchase(purchaseName)
local purchase = p.getPurchase(purchaseName)


if purchase == nil then
if purchase == nil then
return "ERROR: Couldn't find purchase with name '" .. tostring(purchaseName) .. "'[[Category:Pages with script errors]]"
return Shared.printError("Couldn't find purchase with name '" .. tostring(purchaseName) .. "'")
else
else
args[1] = purchase
args[1] = purchase
return p._getPurchaseIcon(args)
return Common.getPurchaseIcon(args)
end
end
end
end
Line 420: Line 319:
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.type == 'BankSlot' then
if costAmt.type == 'BankSlot' then
            return -1
return -1
        elseif costAmt.type == 'Linear' then
elseif costAmt.type == 'Linear' then
            return costAmt.initial
return costAmt.initial
        elseif costAmt.type == 'Glove' or costAmt.type == 'Fixed' and costAmt.cost > 0 then
elseif costAmt.type == 'Glove' or costAmt.type == 'Fixed' and costAmt.cost > 0 then
            return costAmt.cost
return costAmt.cost
        end
end
    end
end
end
end


Line 493: Line 392:
end
end
for i, purchase in ipairs(Purchases) do
for i, purchase in ipairs(Purchases) do
        local purchName = p._getPurchaseName(purchase)
local purchName = Common.getPurchaseName(purchase)
local purchOverride = nil
local purchExpIcon = p._getPurchaseExpansionIcon(purchase)
if purchOverrides ~= nil then
local purchType = Common.getPurchaseType(purchase)
purchOverride = purchOverrides[purchName]
end
 
local purchType = p._getPurchaseType(purchase)
local iconNoLink = nil
local purchLink = ''
local costString = p.getCostString(purchase.cost, false)
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, '|-')
table.insert(resultPart, '|-')
for j, column in ipairs(usedColumns) do
for j, column in ipairs(usedColumns) do
if column == 'Purchase' then
if column == 'Purchase' then
table.insert(resultPart, '|style="min-width:25px"|' .. p._getPurchaseIcon({purchase, notext=true, size='50'}))
table.insert(resultPart, '|class="table-img"|' .. Common.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, '| data-sort-value="'..purchName..'"|'..purchExpIcon .. Common.getPurchaseIcon({purchase, noicon=true}))
table.insert(resultPart, '| ' .. purchName)
elseif column == 'Type' then
elseif column == 'Type' then
table.insert(resultPart, '| ' .. purchType)
table.insert(resultPart, '| ' .. purchType)
Line 529: Line 412:
table.insert(resultPart, cellProp .. '| ' .. costString)
table.insert(resultPart, cellProp .. '| ' .. costString)
elseif column == 'Requirements' then
elseif column == 'Requirements' then
table.insert(resultPart, '| ' .. p.getRequirementString(purchase.purchaseRequirements))
table.insert(resultPart, '| ' .. Common.getRequirementString(purchase.purchaseRequirements, 'None'))
elseif column == 'Buy Limit' then
elseif column == 'Buy Limit' then
local buyLimit = p._getPurchaseBuyLimit(purchase, false)
local buyLimit = p._getPurchaseBuyLimit(purchase, false)
Line 542: Line 425:
table.insert(resultPart, '|}')
table.insert(resultPart, '|}')


return table.concat(resultPart, '\r\n')
return table.concat(resultPart, '\n')
end
end


Line 574: Line 457:
end
end
end
end
    local shopCat = GameData.getEntityByName('shopCategories', 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 Shared.printError('Invalid category ' .. cat)
else
else
        local catPurchases = p.getPurchases(function(purch) return purch.category == shopCat.id end)
local catPurchases = p.getPurchases(function(purch) return purch.category == shopCat.id end)
return p._getShopTable(catPurchases, options)
return p._getShopTable(catPurchases, options)
end
end
Line 584: Line 467:


function p.getItemCostArray(itemID)
function p.getItemCostArray(itemID)
    local purchaseArray = {}
local purchaseArray = {}
    for i, purchase in ipairs(GameData.rawData.shopPurchases) do
for i, purchase in ipairs(GameData.rawData.shopPurchases) do
        if purchase.cost ~= nil and purchase.cost.items ~= nil then
if purchase.cost ~= nil and purchase.cost.items ~= nil then
            for j, itemCost in ipairs(purchase.cost.items) do
for j, itemCost in ipairs(purchase.cost.items) do
                if itemCost.id == itemID then
if itemCost.id == itemID then
                    table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemCost.quantity })
table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemCost.quantity })
                    break
break
                end
end
            end
end
        end
end
    end
end
    return purchaseArray
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 i, purchase in ipairs(GameData.rawData.shopPurchases) do
        if purchase.contains ~= nil then
if purchase.contains ~= nil then
        if purchase.contains.items ~= nil then
if purchase.contains.items ~= nil then
            for j, itemContains in ipairs(purchase.contains.items) do
for j, itemContains in ipairs(purchase.contains.items) do
                if itemContains.id == itemID then
if itemContains.id == itemID then
                    table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemContains.quantity })
table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = itemContains.quantity })
                    break
break
                end
end
            end
end
        end
end
        if purchase.contains.itemCharges ~= nil and purchase.contains.itemCharges.id == itemID then
if purchase.contains.itemCharges ~= nil and purchase.contains.itemCharges.id == itemID then
        table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = 1 })
table.insert(purchaseArray, { ["purchase"] = purchase, ["qty"] = 1 })
        end
end
        end
end
    end
end
    return purchaseArray
return purchaseArray
end
end


Line 622: Line 505:
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({p._getPurchaseName(purchase), type='item'})
result = result..' - '..p._getPurchaseExpansionIcon(purchase)..Icons.Icon({Common.getPurchaseName(purchase), type='item'})
end
end


Line 629: Line 512:


result = result..'\r\n|-\r\n!style="text-align:right;"|Requirements'
result = result..'\r\n|-\r\n!style="text-align:right;"|Requirements'
result = result..'\r\n|'..p.getRequirementString(purchase.purchaseRequirements)
result = result..'\r\n|'..Common.getRequirementString(purchase.purchaseRequirements, 'None')


result = result..'\r\n|-\r\n!style="text-align:right;"|Contains'
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|'..p._getPurchaseContents(purchase, true)


result = result..'\r\n|}'
result = result..'\r\n|}'
Line 653: Line 536:
local item = Items.getItem(itemName)
local item = Items.getItem(itemName)
if item == nil then
if item == nil then
return "ERROR: No item named "..itemName.." exists in the data module"
return Shared.printError('No item named ' .. itemName .. ' exists in the data module')
end
end


Line 660: Line 543:


function p.getShopMiscUpgradeTable()
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)
-- All purchases in the general category besides Auto Eat, which is handled by getAutoEatTable()
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
function p.getShopSkillUpgradeTable()
-- All purchaes in the SkillUpgrades category except tools and any upgrades displayed as
-- tools (e.g. ship upgrades)
local purchList = p.getPurchases(
function(purch)
return purch.category == 'melvorD:SkillUpgrades'
-- Exclude tools, handled by p.getToolTable()
and string.find(purch.id, '_Axe$') == nil
and string.find(purch.id, '_Pickaxe$') == nil
and string.find(purch.id, '_Rod$') == nil
and string.find(purch.id, '_Pickaxe$') == nil
and string.find(purch.id, 'Fire$') == nil
and string.find(purch.id, 'Furnace$') == nil
and string.find(purch.id, 'Pot$') == nil
and string.find(purch.id, 'Sieve$') == nil
and string.find(purch.id, 'Trowel$') == nil
and string.find(purch.id, 'Brush$') == nil
and string.find(purch.id, 'Shovel$') == nil
and string.find(purch.id, 'ShipUpgrade') == nil
-- Exclude God upgrades, handled by p.getGodUpgradeTable()
and p.getGodUpgradeDungeon(purch) == nil
end
)
return p._getShopTable(purchList, { columns = { 'Purchase', 'Description', 'Cost', 'Requirements' }, purchaseHeader = 'Upgrade' })
end
function p.isSkillcapePurchase(purch, isSuperior, skillID)
-- Returns true or false depending on whether the purchase is a skillcape or not.
-- If isSuperior is true, then this checks for superior skillcapes, false checks
-- for regular skillcapes, and nil checks for both.
-- If skillID is specified, then the skillcape must also relate to that skill
local checkCategories = (isSuperior == nil and {'melvorTotH:SuperiorSkillcapes', 'melvorD:Skillcapes'}) or (isSuperior and {'melvorTotH:SuperiorSkillcapes'}) or {'melvorD:Skillcapes'}
-- Some skillcapes (such as Archaeology & Cartography) reside outside of the usual categories
local overrideIDs = {
['melvorTotH:SuperiorSkillcapes'] = {
'melvorAoD:Superior_Archaeology_Skillcape',
'melvorAoD:Superior_Cartography_Skillcape',
'melvorAoD:Cape_of_Completion_AoD'
},
['melvorD:Skillcapes'] = {
'melvorAoD:Archaeology_Skillcape',
'melvorAoD:Cartography_Skillcape'
}
}
for i, cat in ipairs(checkCategories) do
if purch.category == cat or Shared.contains(overrideIDs[cat], purch.id) then
if skillID == nil then
return true
else
-- Also validate purchase requirements for relevant SkillLevel requirement
local hasReq = false
if type(purch.purchaseRequirements) == 'table' then
for j, req in ipairs(purch.purchaseRequirements) do
if req.type == 'SkillLevel' then
if req.skillID == skillID then
hasReq = true
else
-- The presence of any other skill's requirement indicates
-- this is not a skillcape for skill with ID skillID
return false
end
end
end
end
return hasReq
end
end
end
return false
end
end


function p._getShopSkillcapeTable(showSuperior)
function p._getShopSkillcapeTable(showSuperior)
local categoryID = (showSuperior and 'melvorTotH:SuperiorSkillcapes') or 'melvorD:Skillcapes'
local capeList = p.getPurchases(function(purch) return p.isSkillcapePurchase(purch, showSuperior) end)
local capeList = p.getPurchases(function(purch) return purch.category == categoryID end)
local sortOrderFunc =
local sortOrderFunc =
function(a, b)
function(a, b)
local costA, costB = p._getPurchaseSortValue(a), p._getPurchaseSortValue(b)
local costA, costB = p._getPurchaseSortValue(a), p._getPurchaseSortValue(b)
if costA == costB then
if costA == costB then
return p._getPurchaseName(a) < p._getPurchaseName(b)
return Common.getPurchaseName(a) < Common.getPurchaseName(b)
else
else
return costA < costB
return costA < costB
Line 689: Line 645:
local capeCategory = frame.args ~= nil and frame.args[1] or frame
local capeCategory = frame.args ~= nil and frame.args[1] or frame
local showSuperior = string.lower(capeCategory) == 'superior'
local showSuperior = string.lower(capeCategory) == 'superior'
 
return p._getShopSkillcapeTable(showSuperior)
return p._getShopSkillcapeTable(showSuperior)
end
end
Line 695: Line 651:
function p.getSkillcapeTable(frame)
function p.getSkillcapeTable(frame)
local skillName = frame.args ~= nil and frame.args[1] or 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)
local skillID = Constants.getSkillID(skillName)
if skillID == nil then
return Shared.printError('No such skill "' .. (skillName or 'nil') .. '"')
end
 
local capeList = p.getPurchases(function(purch) return p.isSkillcapePurchase(purch, nil, skillID) end)
if Shared.tableIsEmpty(capeList) then
if Shared.tableIsEmpty(capeList) then
return ''
return ''
else
else
capeList = GameData.sortByOrderTable(capeList, GameData.rawData.shopDisplayOrder, true)
local resultPart = {}
local resultPart = {}
table.insert(resultPart, '{| class="wikitable"\r\n')
table.insert(resultPart, '{| class="wikitable"\n')
table.insert(resultPart, '!Skillcape!!Name!!Requirements!!Effect')
table.insert(resultPart, '!Skillcape!!Name!!Requirements!!Effect')
for i, cape in ipairs(capeList) do
for i, cape in ipairs(capeList) do
local capeItem = Items.getItemByID(cape.contains.items[1].id)
local capeItem = Items.getItemByID(cape.contains.items[1].id)
if capeItem ~= nil then
if capeItem ~= nil then
table.insert(resultPart, '\r\n|-\r\n| ' .. Icons.Icon({capeItem.name, type='item', size='60', notext=true}))
table.insert(resultPart, '\n|-\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, '\n| data-sort-value="'..capeItem.name..'"|'..Icons.getExpansionIcon(capeItem.id) .. Icons.Icon({capeItem.name, type='item', noicon=true}))
table.insert(resultPart, '\r\n| ' .. p.getRequirementString(cape.purchaseRequirements))
table.insert(resultPart, '\n| ' .. Common.getRequirementString(cape.purchaseRequirements, 'None'))
table.insert(resultPart, '\r\n| ' .. p._getPurchaseDescription(cape))
table.insert(resultPart, '\n| ' .. p._getPurchaseDescription(cape))
end
end
end
end
table.insert(resultPart, '\r\n|}')
table.insert(resultPart, '\n|}')
return table.concat(resultPart)
return table.concat(resultPart)
end
end
Line 728: Line 690:
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)
local purchaseName = Common.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 736: Line 698:
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, '|-\r\n|class="table-img" 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, '| ' .. 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.increasedAutoEatThreshold .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatThreshold, 0, 0)) .. '%')
Line 746: Line 708:


return table.concat(resultPart, '\r\n')
return table.concat(resultPart, '\r\n')
end
function p.getGodUpgradeDungeon(purch)
-- Identifies skill upgrades which have a dungeon completion requirement for an area
-- whose name ends with 'God Dungeon'. Returns the ID of the dungeon which must be
-- completed before the purchase may be bought if the purchase is a god upgrade
if purch.category == 'melvorD:SkillUpgrades' and type(purch.purchaseRequirements) == 'table' then
for i, req in ipairs(purch.purchaseRequirements) do
if req.type == 'DungeonCompletion' and string.find(req.dungeonID, 'God_Dungeon$') ~= nil then
return req.dungeonID
end
end
end
end
end


function p.getGodUpgradeTable()
function p.getGodUpgradeTable()
local resultPart = {}
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(
local upgradeList = p.getPurchases(
function(purch)
function(purch)
if purch.category == 'melvorD:SkillUpgrades' and purch.purchaseRequirements ~= nil then
return p.getGodUpgradeDungeon(purch) ~= nil
return getGodDungeon(purch.purchaseRequirements) ~= nil
end
return false
end)
end)
if Shared.tableIsEmpty(upgradeList) then
if Shared.tableIsEmpty(upgradeList) then
        return ''
return ''
    end
end


-- Table header
-- Table header
Line 779: Line 740:
-- 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 upgradeName = p._getPurchaseName(upgrade)
local upgradeName = Common.getPurchaseName(upgrade)
local dung = getGodDungeon(upgrade.purchaseRequirements)
local dung = GameData.getEntityByID('dungeons', p.getGodUpgradeDungeon(upgrade))
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="' .. upgradeName .. '"| ' .. Icons.Icon({upgradeName, type='upgrade', size=50, notext=true}))
table.insert(resultPart, '|-\r\n|class="table-img" data-sort-value="' .. upgradeName .. '"| ' ..p._getPurchaseExpansionIcon(upgrade).. Icons.Icon({upgradeName, type='upgrade', size=50, notext=true}))
table.insert(resultPart, '| ' .. Icons.Icon({upgradeName, type='upgrade', noicon=true}))
table.insert(resultPart, '| ' .. Icons.Icon({upgradeName, type='upgrade', noicon=true}))
table.insert(resultPart, '| ' .. p._getPurchaseDescription(upgrade))
table.insert(resultPart, '| ' .. p._getPurchaseDescription(upgrade))
Line 793: Line 754:
end
end


function p.getCookingUtilityTable(frame)
function p.getAoDTable(frame)
local category = nil
-- All purchases in the Atlas of Discovery category except for skillcapes, which are handled
if frame ~= nil then category = frame.args ~= nil and frame.args[1] or frame end
-- by p.getShopSKilcapeTable()
local validCategories = {'Cooking Fire', 'Furnace', 'Pot'}
local purchList = p.getPurchases(
if category == nil or not Shared.contains({'Cooking Fire', 'Furnace', 'Pot'}, category) then
function(purch)
return 'ERROR: Invalid category specified. Must be one of the following: ' .. mw.text.listToText(validCategories, ', ', ' or ')
return purch.category == 'melvorAoD:AtlasOfDiscovery' and not p.isSkillcapePurchase(purch)
end
)
 
return p._getShopTable(purchList, { columns = { 'Purchase', 'Description', 'Cost', 'Requirements' } })
end
 
function p.getToolTable(toolName, searchString, modifiers, skillID)
local skillName = nil
if type(skillID) == 'string' then
skillName = Constants.getSkillName(skillID)
end
local toolArray = p.getPurchases(
function(purch)
return purch.category == 'melvorD:SkillUpgrades' and string.find(purch.id, searchString) ~= nil
end)
 
if Shared.tableIsEmpty(toolArray) then
return ''
end
if modifiers == nil then
modifiers = {}
end
end
 
local categoryShort = string.match(category, '[^%s]+$')
local modTotal = {}
local bonusSkillID = Constants.getSkillID('Cooking')
for i, modDef in ipairs(modifiers) do
local bonusColMod, bonusColName = nil, nil
modTotal[modDef.name] = 0
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
end
local modsPerfectChance = {'increasedChancePerfectCookFire', 'increasedChancePerfectCookFurnace',
 
'increasedChancePerfectCookPot', 'increasedChancePerfectCookGlobal'}
local headerRowSpan = (Shared.tableIsEmpty(toolArray) and 1) or 2
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 = {}
local resultPart = {}
-- Table header
table.insert(resultPart, '{| class="wikitable stickyHeader"')
table.insert(resultPart, '{| class="wikitable stickyHeader"')
table.insert(resultPart, '|- class="headerRow-0"')
table.insert(resultPart, '\n|- class="headerRow-0"')
table.insert(resultPart, '!colspan="4"| !!colspan="2"|' .. bonusColName .. '!!colspan="2"|Bonus Perfect Chance')
table.insert(resultPart, '\n!rowspan="' .. headerRowSpan .. '" colspan="2"| Name')
table.insert(resultPart, '|- class="headerRow-1"')
table.insert(resultPart, '\n!rowspan="' .. headerRowSpan .. '"| ' .. (skillName == nil and 'Requirements' or Icons.Icon({skillName, type='skill', notext=true}) .. ' Level'))
table.insert(resultPart, '!colspan="2"|Name!!Level!!Cost' .. string.rep('!!This ' .. categoryShort .. '!!Total', 2))
table.insert(resultPart, '\n!rowspan="' .. headerRowSpan .. '"| Cost')
for i, modDef in ipairs(modifiers) do
modTotal[modDef.name] = 0
table.insert(resultPart, '\n!colspan="2"| ' .. modDef.header)
end
if headerRowSpan > 1 then
table.insert(resultPart, '\n|- class="headerRow-1"' .. string.rep('\n!This ' .. toolName .. '\n!Total', Shared.tableCount(modifiers)))
end
 
-- Keep track of modifiers which are present on tools but not exposed within the table, so
-- that an error may be printed if any are omitted
local modsUnused = {}
for i, tool in ipairs(toolArray) do
local toolName = Common.getPurchaseName(tool)
local toolCost = p.getCostString(tool.cost, false)
local toolCostSort = p._getPurchaseSortValue(tool) or 0
table.insert(resultPart, '\n|-')
table.insert(resultPart, '\n|class="table-img" data-sort-value="' .. toolName .. '"| ' .. Icons.Icon({toolName, type='upgrade', size='50', notext=true}))
table.insert(resultPart, '\n| data-sort-value="' .. toolName.. '"|' .. Icons.getExpansionIcon(tool.id) .. toolName)
local level, levelStyle = nil, nil
if skillID == nil then
level = 'None'
levelStyle = '|class="table-na"'
else
level = 1
levelStyle = '|style="text-align:right"'
end
if tool.purchaseRequirements ~= nil and not Shared.tableIsEmpty(tool.purchaseRequirements) then
if skillID == nil then
-- Return all requirements
level = Common.getRequirementString(tool.purchaseRequirements, 'None')
if level ~= 'None' then
levelStyle = ''
end
else
-- Return level requirement for just the specified skill
for i, purchReq in ipairs(tool.purchaseRequirements) do
if purchReq.type == 'SkillLevel' and purchReq.skillID == skillID then
level = purchReq.level
break
end
end
end
end
table.insert(resultPart, '\n' .. levelStyle .. '| '..level)
table.insert(resultPart, '\n|style="text-align:right" data-sort-value="' .. toolCostSort .. '"| ' .. toolCost)
 
local resultPrefix = ''
local cellStart = '\n|style="text-align:right"'
if tool.contains ~= nil and tool.contains.modifiers ~= nil then
for modName, modVal in pairs(tool.contains.modifiers) do
if modTotal[modName] == nil and not Shared.contains(modsUnused, modName) then
-- Mod with name modName is provided by the purchase, but not exposed within
-- the output table
table.insert(modsUnused, modName)
end
end


-- Row for each upgrade
for j, modDef in ipairs(modifiers) do
for i, utility in ipairs(utilityList) do
local modName = modDef.name
        local utilityName = p._getPurchaseName(utility)
local modVal = tool.contains.modifiers[modName]
-- First determine bonus XP/doubling chance and perfect chance
if modVal ~= nil then
local bonusVal, perfectChance = 0, 0
if type(modVal) == 'table' and type(modVal[1]) == 'table' and modVal[1].skillID ~= nil and (modDef.skillID == nil or modDef.skillID == modVal[1].skillID) then
if type(utility.contains) == 'table' then
modVal = modVal[1].value
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
modTotal[modName] = modTotal[modName] + modVal
else
modVal = 0
end
end
local cellStartVal = cellStart .. ((modVal == 0 and ' class="table-na"') or '')
local cellStartTot = cellStart .. ((modTotal[modName] == 0 and ' class="table-na"') or '')
table.insert(resultPart, cellStartVal .. '| ' .. (modVal == 0 and '' or modDef.sign) .. modVal .. modDef.suffix)
table.insert(resultPart, cellStartTot .. '| ' .. (modTotal[modName] == 0 and '' or modDef.sign) .. modTotal[modName] .. modDef.suffix)
end
end
end
end
totalBonusVal = totalBonusVal + bonusVal
end
totalPerfectChance = totalPerfectChance + perfectChance
 
local resultPrefix = ''
if not Shared.tableIsEmpty(modsUnused) then
resultPrefix = Shared.printError('The following modifiers are not included within the table: ' .. table.concat(modsUnused, ', ')) .. '\n'
end
table.insert(resultPart, '\n|}')
return resultPrefix .. table.concat(resultPart)
end
 
function p.getAxeTable(frame)
local modifiers = {
{ name = 'decreasedSkillIntervalPercent', header = 'Cut Time Decrease', sign = '-', suffix = '%' },
{ name = 'increasedChanceToDoubleItemsSkill', header = 'Double Items Chance', sign = '+', suffix = '%' },
{ name = 'increasedBirdNestDropRate', header = Icons.Icon({'Bird Nest', 'Drop Chance', type='item', nolink=true}), sign = '+', suffix = '%' },
{ name = 'increasedChanceForAshInWoodcutting', header = Icons.Icon({'Ash', 'Drop Chance', type='item', nolink=true}), sign = '+', suffix = '%' }
}
return p.getToolTable('Axe', '_Axe$', modifiers, 'melvorD:Woodcutting')
end
 
function p.getPickaxeTable(frame)
local modifiers = {
{ name = 'decreasedSkillIntervalPercent', header = 'Mining Time Decrease', sign = '-', suffix = '%' },
{ name = 'increasedChanceToDoubleOres', header = '2x Ore Chance', sign = '+', suffix = '%' },
{ name = 'increasedChanceForOneExtraOre', header = '+1 Ore Chance', sign = '+', suffix = '%' },
{ name = 'increasedChanceForQualitySuperiorGem', header = 'Superior Gem Chance', sign = '+', suffix = '%' },
{ name = 'increasedMeteoriteOre', header = 'Increased ' .. Icons.Icon({'Meteorite Ore', type='item', notext=true}), sign = '+', suffix = '' }
}
 
return p.getToolTable('Pickaxe', '_Pickaxe$', modifiers, 'melvorD:Mining')
end
 
function p.getRodTable(frame)
local modifiers = {
{ name = 'decreasedSkillIntervalPercent', header = 'Catch Time Decrease', sign = '-', suffix = '%' },
{ name = 'increasedChanceForOneExtraFish', header = '+1 Fish Chance', sign = '+', suffix = '%' },
{ name = 'increasedChanceToFindLostChest', header = Icons.Icon({'Lost Chest', type='item', notext=true}) .. ' Chance', sign = '+', suffix = '%' },
{ name = 'increasedFishingCookedChance', header = 'Cooked Fish Chance', sign = '+', suffix = '%' }
}
 
return p.getToolTable('Rod', '_Rod$', modifiers, 'melvorD:Fishing')
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 Shared.printError('Invalid category specified. Must be one of the following: ' .. mw.text.listToText(validCategories, ', ', ' or '))
end
 
local categoryShort = string.match(category, '[^%s]+$')
local modifiers = {
['Cooking Fire'] = {
{ name = 'increasedSkillXP', skillID = 'melvorD:Cooking', header = 'Bonus ' .. Icons.Icon({'Cooking', type='skill', notext=true}) .. ' XP', sign = '+', suffix = '%' },
{ name = 'increasedChancePerfectCookFire', header = Icons.Icon({'Normal Cooking Fire', type='upgrade', notext=true, nolink=true}) .. ' Perfect Cook Chance', sign ='+', suffix = '%' },
{ name = 'decreasedPassiveCookInterval', header = 'Passive Cook Time Decrease', sign = '-', suffix = '%' },
{ name = 'increasedChanceToDoubleItemsSkill', skillID = 'melvorD:Cooking', header = '2x Items Chance', sign = '+', suffix = '%' },
{ name = 'decreasedSkillIntervalPercent', skillID = 'melvorD:Cooking', header = 'Active Cook Time Decrease', sign = '-', suffix = '%' }
},
['Furnace'] = {
{ name = 'increasedChancePerfectCookFurnace', header = Icons.Icon({'Basic Furnace', type='upgrade', notext=true, nolink=true}) .. ' Perfect Cook Chance', sign = '+', suffix = '%' },
{ name = 'increasedChanceToDoubleItemsSkill', skillID = 'melvorD:Cooking', header = '2x Items Chance', sign = '+', suffix = '%' },
{ name = 'decreasedPassiveCookInterval', header = 'Passive Cook Time Decrease', sign = '-', suffix = '%' },
{ name = 'decreasedSkillIntervalPercent', skillID = 'melvorD:Cooking', header = 'Active Cook Time Decrease', sign = '-', suffix = '%' },
{ name = 'increasedChanceAdditionalSkillResource', skillID = 'melvorD:Cooking', header = '+1 Item Chance', sign = '+', suffix = '%' }
},
['Pot'] = {
{ name = 'increasedChancePerfectCookPot', header = Icons.Icon({'Basic Pot', type='upgrade', notext=true, nolink=true}) .. ' Perfect Cook Chance', sign = '+', suffix = '%' },
{ name = 'increasedChanceToDoubleItemsSkill', skillID = 'melvorD:Cooking', header = '2x Items Chance', sign = '+', suffix = '%' },
{ name = 'decreasedPassiveCookInterval', header = 'Passive Cook Time Decrease', sign = '-', suffix = '%' },
{ name = 'decreasedSkillIntervalPercent', skillID = 'melvorD:Cooking', header = 'Active Cook Time Decrease', sign = '-', suffix = '%' },
{ name = 'increasedChanceAdditionalSkillResource', skillID = 'melvorD:Cooking', header = '+1 Item Chance', sign = '+', suffix = '%' },
{ name = 'increasedMasteryXP', skillID = 'melvorD:Cooking', header = 'Increased Cooking ' .. Icons.Icon({'Mastery', nolink=true}) .. ' XP', sign = '+', suffix = '%'}
}
}


table.insert(resultPart, '|-')
return p.getToolTable(categoryShort, categoryShort .. '$', modifiers[category], nil)
table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({utilityName, type='upgrade', size='50', notext=true}))
end
table.insert(resultPart, '|' .. utilityName)
 
table.insert(resultPart, '|style="text-align:right"|' .. p.getRequirementString(utility.purchaseRequirements))
--Adding table for Ship upgrades for Cartography
table.insert(resultPart, '|style="text-align:right"|' .. p.getCostString(utility.cost, false))
function p.getShipTable(frame)
table.insert(resultPart, '|style="text-align:right"|' .. '+' .. bonusVal .. '%')
local modifiers = {
table.insert(resultPart, '|style="text-align:right"|' .. '+' .. totalBonusVal .. '%')
{ name = 'decreasedSkillIntervalPercent', header = 'Cartography Interval', sign = '-', suffix = '%' },
table.insert(resultPart, '|style="text-align:right"|' .. '+' .. perfectChance .. '%')
{ name = 'increasedSightRange', header = 'Increased Sight Range', sign = '+', suffix = '' },
table.insert(resultPart, '|style="text-align:right"|' .. '+' .. totalPerfectChance .. '%')
{ name = 'increasedSurveyRange', header = 'Increased Survey Range', sign = '+', suffix = ''},
}
 
return p.getToolTable('Ship', 'Ship', modifiers, 'melvorAoD:Cartography')
end
 
function p.getArchToolTable(frame)local category = nil
if frame ~= nil then category = frame.args ~= nil and frame.args[1] or frame end
local validCategories = {'Sieve', 'Trowel', 'Brush', 'Shovel'}
if category == nil or not Shared.contains(validCategories, category) then
return Shared.printError('Invalid category specified. Must be one of the following: ' .. mw.text.listToText(validCategories, ', ', ' or '))
end
end
table.insert(resultPart, '|}')


return table.concat(resultPart, '\r\n')
local modifiers = {
{name = 'increased'..category..'ToolLevel', header = 'Increased '..category..' Tool level', sign = '+', suffix = ''}
}
return p.getToolTable(category, category .. '$', modifiers, 'melvorAoD:Archaeology')
end
 
-- Below functions included for backwards compatibility
-- TODO: Remove dependency on these functions in all other modules
function p._getPurchaseName(purchase)
return Common.getPurchaseName(purchase)
end
function p._getPurchaseType(purchase)
return Common.getPurchaseType(purchase)
end
function p._getPurchaseIcon(iconArgs)
return Common.getPurchaseIcon(iconArgs)
end
function p.getRequirementString(reqs)
return Common.getRequirementString(reqs, 'None')
end
end


return p
return p
457

edits