Anonymous

Module:Shop: Difference between revisions

From Melvor Idle
7,583 bytes added ,  25 July 2021
getGodUpgradeTable: Initial implementation
(getShopSkillcapeTable: Move from Module:Items & enforce min-width for icon column)
(getGodUpgradeTable: Initial implementation)
(5 intermediate revisions by the same user not shown)
Line 92: Line 92:
end
end


function p._getShopTable(Purchases)
function p._getPurchaseSortValue(purchase)
   local result = '{| class="wikitable sortable stickyHeader"'
   local costCurrencies = {'gp', 'slayerCoins', 'raidCoins'}
   result = result..'\r\n|- class="headerRow-0"'
   for j, curr in ipairs(costCurrencies) do
  result = result..'\r\n!colspan="2"|Purchase!!Type!!Description!!style="min-width:90px"|Cost!!Requirements'
    local costAmt = purchase.cost[curr]
    if costAmt ~= nil and costAmt > 0 then
      return costAmt
    end
  end
end
 
function p._getShopTable(Purchases, options)
  local availableColumns = { 'Purchase', 'Type', 'Description', 'Cost', 'Requirements' }
  local headerPropsDefault = {
    ["Purchase"] = 'colspan="2"',
    ["Cost"] = 'style="min-width:90px"'
  }
  local usedColumns, purchHeader, sortOrder, headerProps = {}, 'Purchase', nil, {}
 
  -- Process options if specified
  if options ~= nil and type(options) == 'table' then
    -- Custom columns
    if options.columns ~= nil and type(options.columns) == 'table' then
      for i, column in ipairs(options.columns) do
        if Shared.contains(availableColumns, column) then
          table.insert(usedColumns, column)
        end
      end
    end
    -- Purchase column header text
    if options.purchaseHeader ~= nil and type(options.purchaseHeader) == 'string' then
      purchHeader = options.purchaseHeader
    end
    -- Custom sort order
    if options.sortOrder ~= nil and type(options.sortOrder) == 'function' then
      sortOrder = options.sortOrder
    end
    -- Header properties
    if options.headerProps ~= nil and type(options.headerProps) == 'table' then
      headerProps = options.headerProps
    end
  end
  -- Use default columns if no custom columns specified
  if Shared.tableCount(usedColumns) == 0 then
    usedColumns = availableColumns
  end
  if Shared.tableCount(headerProps) == 0 then
    headerProps = headerPropsDefault
  end


   local costCurrencies = {'gp', 'slayerCoins', 'raidCoins'}
  -- Various overrides for certain shop items
   for i, purchase in Shared.skpairs(Purchases) do
   local purchOverrides = {
     result = result..'\r\n|-\r\n|'
    ["Extra Bank Slot"] = { icon = {'Bank Slot', 'upgrade'}, link = 'Bank Slot', cost = Icons.Icon({'Coins', size = 25, notext = true}) .. ' <span style="font-size:127%; font-family: MathJax_Math; font-style: italic;">C<sub>b</sub></span>*' },
    -- Golbin Raid items
    ["Reduce Wave Skip Cost"] = { icon = {'Melvor Logo', nil}, link = nil },
    ["Food Bonus"] = { icon = {'Melvor Logo', nil}, link = nil },
    ["Ammo Gatherer"] = { icon = {'Melvor Logo', nil}, link = nil },
    ["Rune Pouch"] = { icon = {'Melvor Logo', nil}, link = nil },
    ["Increase Starting Prayer Points"] = { icon = {'Melvor Logo', nil}, link = nil },
    ["Unlock Combat Passive Slot"] = { icon = {'Melvor Logo', nil}, link = nil },
    ["Prayer"] = { icon = {'Prayer', 'skill'}, link = nil },
    ["Increase Prayer Level"] = { icon = {'Prayer', 'skill'}, link = nil },
    ["Increase Prayer Points gained per Wave Completion"] = { icon = {'Prayer', 'skill'}, link = nil }
  }
  -- Begin output generation
  local resultPart = {}
  -- Generate header
  table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
  table.insert(resultPart, '|- class="headerRow-0"')
   for i, column in ipairs(usedColumns) do
    local prop = headerProps[column]
    table.insert(resultPart, '!' .. (prop and prop .. '| ' or ' ') .. (column == 'Purchase' and purchHeader or column))
  end
 
  local purchIterator = nil
  if sortOrder == nil then
    purchIterator = Shared.skpairs
  else
    table.sort(Purchases, sortOrder)
    purchIterator = ipairs
  end
  for i, purchase in purchIterator(Purchases) do
     local purchOverride = nil
    if purchOverrides ~= nil then
      purchOverride = purchOverrides[purchase.name]
    end


     local purchType = 'Item'
     local purchType = 'Item'
Line 110: Line 187:
     end
     end


    -- Translate certain media strings to icons, mostly for Golbin Raid shop objects
     local iconName = purchase.name
     local iconOverrides = {
     local iconType = (purchType == 'Item Bundle' and 'item' or string.lower(purchType))
      ["assets/media/main/logo.svg"] = { icon = 'Melvor Logo', type = nil, noLink = true },
    local iconNoLink = nil
      ["assets/media/skills/prayer/prayer.svg"] = { icon = 'Prayer', type = 'skill', noLink = true }
     local purchLink = ''
    }
    local costString = p.getCostString(purchase.cost)
     local iconName, iconType, iconNoLink = purchase.name, (purchType == 'Item Bundle' and 'item' or string.lower(purchType)), nil
    if purchOverride ~= nil then
     if iconOverrides[purchase.media] ~= nil then
       if purchOverride.icon ~= nil then
       iconName, iconType, iconNoLink = iconOverrides[purchase.media].icon, iconOverrides[purchase.media].type, iconOverrides[purchase.media].noLink
        iconName = purchOverride.icon[1]
        iconType = purchOverride.icon[2]
      end
      if purchOverride.link == nil then
        iconNoLink = true
      else
        purchLink = purchOverride.link .. '|'
      end
      if purchOverride.cost ~= nil then costString = purchOverride.cost end
     end
     end


     local purchName = purchase.name
     local purchName = purchase.name
     if iconNoLink == nil or iconNoLink ~= true then purchName = '[[' .. purchName .. ']]' end
     if iconNoLink == nil or iconNoLink ~= true then purchName = '[[' .. purchLink .. purchName .. ']]' end
    result = result..'style="min-width:25px"|'..Icons.Icon({iconName, type=iconType, notext=true, nolink=iconNoLink, size='50'})
    result = result..'||'..purchName..'||'..purchType
    result = result..'||'..purchase.description..'||style="text-align:right;"'


     for j, curr in Shared.skpairs(costCurrencies) do
    table.insert(resultPart, '|-')
       local costAmt = purchase.cost[curr]
     for j, column in ipairs(usedColumns) do
       if costAmt ~= nil and costAmt > 0 then
      if column == 'Purchase' then
        result = result..' data-sort-value="'..costAmt..'"'
        table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({iconName, type=iconType, notext=true, nolink=iconNoLink, size='50'}))
         break
        table.insert(resultPart, '| ' .. purchName)
      elseif column == 'Type' then
        table.insert(resultPart, '| ' .. purchType)
       elseif column == 'Description' then
        table.insert(resultPart, '| ' .. purchase.description)
       elseif column == 'Cost' then
        local cellProp = '|style="text-align:right;"'
        local sortValue = p._getPurchaseSortValue(purchase)
        if sortValue ~= nil then cellProp = cellProp .. ' data-sort-value="' .. sortValue .. '"' end
         table.insert(resultPart, cellProp .. '| ' .. costString)
      elseif column == 'Requirements' then
        table.insert(resultPart, '| ' .. p.getRequirementString(purchase.unlockRequirements))
      else
        -- Shouldn't be reached, but will prevent the resulting table becoming horribly mis-aligned if it ever happens
        table.insert(resultPart, '| ')
       end
       end
     end
     end
    result = result..'|'..p.getCostString(purchase.cost)..'||'..p.getRequirementString(purchase.unlockRequirements)
   end
   end
  table.insert(resultPart, '|}')


   result = result..'\r\n|}'
   return table.concat(resultPart, '\r\n')
  return result
end
end


function p.getShopTable(frame)
function p.getShopTable(frame)
   local cat = frame.args ~= nil and frame.args[1] or frame
   local cat = frame.args ~= nil and frame.args[1] or frame
  local options = {}
  if frame.args ~= nil then
    if frame.args.columns ~= nil then options.columns = Shared.splitString(frame.args.columns, ',') end
    if frame.args.purchaseHeader ~= nil then options.purchaseHeader = frame.args.purchaseHeader end
    if frame.args.sortOrder ~= nil then options.sortOrder = frame.args.sortOrder end
  end
   local shopCat = ShopData.Shop[cat]
   local shopCat = ShopData.Shop[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)
     return p._getShopTable(shopCat, options)
   end
   end
end
end
Line 196: Line 297:
   for category, purchaseArray in Shared.skpairs(ShopData.Shop) do
   for category, purchaseArray in Shared.skpairs(ShopData.Shop) do
     for i, purchase in Shared.skpairs(purchaseArray) do
     for i, purchase in Shared.skpairs(purchaseArray) do
       if checkFunc(purchase) then
       if checkFunc(category, purchase) then
         table.insert(purchaseList, p.processPurchase(category, i - 1))
         table.insert(purchaseList, p.processPurchase(category, i - 1))
       end
       end
Line 253: Line 354:


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


function p.getShopSkillcapeTable()
function p.getShopSkillcapeTable()
   local result = ''
   local capeList = p.getPurchases(function(cat, purch) return cat == 'Skillcapes' end)
   local capeList = Items.getItems(function(item) return Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion' end)
   local sortOrderFunc = function(a, b)
                      if a.cost.gp == b.cost.gp then
                        return a.name < b.name
                      else
                        return a.cost.gp < b.cost.gp
                      end
                    end
  return p._getShopTable(capeList,
    { columns = { 'Purchase', 'Description', 'Cost' },
      purchaseHeader = 'Cape',
      sortOrder = sortOrderFunc,
      headerProps = {["Purchase"] = 'colspan="2" style="width:200px;"', ["Cost"] = 'style=width:120px;'}
    })
end
 
function p.getAutoEatTable()
  local resultPart = {}
  local purchasesAE = p.getPurchases(function(cat, purch) return string.find(purch.name, '^Auto Eat') ~= nil end)
 
  -- Table header
  table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
  table.insert(resultPart, '|- class="headerRow-0"')
  table.insert(resultPart, '!colspan="2"|Auto Eat Tier!!Minimum Threshold!!Efficiency!!Max Healing!!Cost')
  -- Rows for each Auto Eat tier
  local mods = {["increasedAutoEatEfficiency"] = 0, ["increasedAutoEatHPLimit"] = 0, ["increasedAutoEatThreshold"] = 0}
  for i, purchase in ipairs(purchasesAE) do
    -- Modifiers must be accumulated as we go
    for modName, modValue in pairs(mods) do
      if purchase.contains.modifiers[modName] ~= nil then
        mods[modName] = mods[modName] + purchase.contains.modifiers[modName]
      end
    end
 
    local costAmt = p._getPurchaseSortValue(purchase)
    table.insert(resultPart, '|-\r\n|style="min-width:25px; text-align:center;" data-sort-value="' .. purchase.name .. '"| ' .. Icons.Icon({purchase.name, type='upgrade', size=50, notext=true}))
    table.insert(resultPart, '| [[' .. purchase.name .. ']]')
    table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. mods.increasedAutoEatThreshold .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatThreshold, 0, 0)) .. '%')
    table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. mods.increasedAutoEatEfficiency .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatEfficiency, 0, 0)) .. '%')
    table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. mods.increasedAutoEatHPLimit .. '" | ' .. Shared.formatnum(Shared.round(mods.increasedAutoEatHPLimit, 0, 0)) .. '%')
    table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. costAmt .. '" | ' .. Icons.GP(costAmt))
  end
  table.insert(resultPart, '|}')


   result = result..'\r\n{|class="wikitable sortable stickyHeader"'
   return table.concat(resultPart, '\r\n')
  result = result..'\r\n|- class="headerRow-0"'
end
  result = result..'\r\n!colspan="2" style="width:200px"|Cape'
  result = result..'!!Description!!style="width:120px"|Price'


   --Sort the table by cost and then name
function p.getGodUpgradeTable()
   table.sort(capeList, function(a, b)  
  local resultPart = {}
                        if a.buysFor == b.buysFor then
   -- Obtain list of God upgrades: look for skill upgrades which have a dungeon completion
                          return a.name < b.name
  --  requirement for an area whose name ends with 'God Dungeon'
                        else
  local getGodDungeon =
                          return a.sellsFor < b.buysFor
    function(reqs)
                        end
      if reqs.dungeonCompletion ~= nil then
                      end)
        for i, areaReq in ipairs(reqs.dungeonCompletion) do
   for i, thisItem in pairs(capeList) do
          local dung = Areas.getAreaByID('dungeon', areaReq[1])
     result = result..'\r\n|-\r\n|style="min-width:25px"|'..Icons.Icon({thisItem.name, type='item', size='50', notext=true})
          if string.find(dung.name, 'God Dungeon$') ~= nil then return dung end
     result = result..'||[['..thisItem.name..']]'
        end
     result = result..'\r\n||'..thisItem.description
      end
     result = result..'||style="text-align:left" data-sort-value="'..thisItem.buysFor..'"'
    end
    result = result..'|'..Icons.GP(thisItem.buysFor)
                         
   local upgradeList = p.getPurchases(
    function(cat, purch)
      if cat == 'SkillUpgrades' and purch.unlockRequirements ~= nil then
        return getGodDungeon(purch.unlockRequirements) ~= nil
      end
      return false
    end)
  if Shared.tableCount(upgradeList) == 0 then return '' end
 
  -- Table header
  table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
  table.insert(resultPart, '|- class="headerRow-0"')
  table.insert(resultPart, '!colspan="2"|God Upgrade!!Effect!!Dungeon!!Cost')
 
  -- Rows for each God upgrade
   for i, upgrade in ipairs(upgradeList) do
     local dung = getGodDungeon(upgrade.unlockRequirements)
    local costSortValue = p._getPurchaseSortValue(upgrade)
    table.insert(resultPart, '|-\r\n|style="min-width:25px; text-align:center;" data-sort-value="' .. upgrade.name .. '"| ' .. Icons.Icon({upgrade.name, type='upgrade', size=50, notext=true}))
     table.insert(resultPart, '| [[' .. upgrade.name .. ']]')
     table.insert(resultPart, '| ' .. upgrade.description)
     table.insert(resultPart, '| data-sort-value="' .. dung.name .. '"| ' .. Icons.Icon({dung.name, type='dungeon'}))
    table.insert(resultPart, '| style="text-align:right;" data-sort-value="' .. costSortValue .. '"| ' .. p.getCostString(upgrade.cost))
   end
   end
   result = result..'\r\n|}'
   table.insert(resultPart, '|}')


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


return p
return p