Module:Shop: Difference between revisions

3,400 bytes added ,  25 July 2021
_getShopTable: Overhaul to allow for greater control over output format; getShopSkillcapeTable: Use _getShopTable; getShopMiscUpgradeTable: Initial implementation
m (Price -> Cost for consistency with other shop tables)
(_getShopTable: Overhaul to allow for greater control over output format; getShopSkillcapeTable: Use _getShopTable; getShopMiscUpgradeTable: Initial implementation)
Line 102: Line 102:
end
end


function p._getShopTable(Purchases)
function p._getShopTable(Purchases, options)
   local result = '{| class="wikitable sortable stickyHeader"'
   local availableColumns = { 'Purchase', 'Type', 'Description', 'Cost', 'Requirements' }
   result = result..'\r\n|- class="headerRow-0"'
   local headerPropsDefault = {
  result = result..'\r\n!colspan="2"|Purchase!!Type!!Description!!style="min-width:90px"|Cost!!Requirements'
    ["Purchase"] = 'colspan="2"',
    ["Cost"] = 'style="min-width:90px"'
  }
  local usedColumns, purchHeader, sortOrder, headerProps = {}, 'Purchase', nil, {}


   for i, purchase in Shared.skpairs(Purchases) do
   -- Process options if specified
     result = result..'\r\n|-\r\n|'
  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
 
  -- Various overrides for certain shop items
  local purchOverrides = {
    ["Extra Bank Slot"] = { icon = {'Bank Slot', 'upgrade'}, link = 'Bank Slot', cost = Icons.Icon({'Coins', size = 25, notext = true}) .. ' <math>C_b</math>*' },
    -- 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 119: 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;"'


     local sortValue = p._getPurchaseSortValue(purchase)
     table.insert(resultPart, '|-')
    if sortValue ~= nil then result = result..' data-sort-value="'..sortValue..'"' end
    for j, column in ipairs(usedColumns) do
    result = result..'|'..p.getCostString(purchase.cost)..'||'..p.getRequirementString(purchase.unlockRequirements)
      if column == 'Purchase' then
        table.insert(resultPart, '|style="min-width:25px"|' .. Icons.Icon({iconName, type=iconType, notext=true, nolink=iconNoLink, size='50'}))
        table.insert(resultPart, '| ' .. purchName)
      elseif column == 'Type' then
        table.insert(resultPart, '| ' .. purchType)
      elseif column == 'Description' then
        table.insert(resultPart, '| ' .. purchase.description)
      elseif column == 'Cost' then
        local cellProp = '|style="text-align:right;"'
        local sortValue = p._getPurchaseSortValue(purchase)
        if sortValue ~= nil then cellProp = cellProp .. ' data-sort-value="' .. sortValue .. '"' end
        table.insert(resultPart, cellProp .. '| ' .. costString)
      elseif column == 'Requirements' then
        table.insert(resultPart, '| ' .. p.getRequirementString(purchase.unlockRequirements))
      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
  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 257: 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 resultPart = {}
   local capeList = p.getPurchases(function(cat, purch) return cat == 'Skillcapes' end)
   local capeList = p.getPurchases(function(cat, purch) return cat == 'Skillcapes' end)
 
   local sortOrderFunc = function(a, b)
   table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
                      if a.cost.gp == b.cost.gp then
  table.insert(resultPart, '|- class="headerRow-0"')
                        return a.name < b.name
  table.insert(resultPart, '!colspan="2" style="width:200px"|Cape!!Description!!style="width:120px"|Cost')
                      else
 
                        return a.cost.gp < b.cost.gp
  --Sort the table by cost and then name
                      end
  table.sort(capeList, function(a, b)  
                    end
                        if a.cost.gp == b.cost.gp then
   return p._getShopTable(capeList,
                          return a.name < b.name
     { columns = { 'Purchase', 'Description', 'Cost' },
                        else
      purchaseHeader = 'Cape',
                          return a.cost.gp < b.cost.gp
      sortOrder = sortOrderFunc,
                        end
      headerProps = {["Purchase"] = 'colspan="2" style="width:200px;"', ["Cost"] = 'style=width:120px;'}
                      end)
    })
   for i, thisItem in ipairs(capeList) do
    local sortValue = p._getPurchaseSortValue(thisItem)
     table.insert(resultPart, '|-\r\n|style="min-width:25px; text-align:center;"| ' .. Icons.Icon({thisItem.name, type='item', size=50, notext=true}))
    table.insert(resultPart, '| [[' .. thisItem.name .. ']]')
    table.insert(resultPart, '| ' .. thisItem.description)
    table.insert(resultPart, '|style="text-align:right;" data-sort-value="' .. sortValue .. '"| ' .. p.getCostString(thisItem.cost))
  end
  table.insert(resultPart, '|}')
 
  return table.concat(resultPart, '\r\n')
end
end