Difference between revisions of "Module:ModifierTables"

From Melvor Idle
(fixed a potential bug with getModifierTable if no maxOtherMods was sent in)
(_getModifierTable: Add Astrology constelllations; Indent with tabs instead of spaces)
Line 1: Line 1:
 
--Module that constructs tables for all things that can affect Player Modifiers
 
--Module that constructs tables for all things that can affect Player Modifiers
--This includes Agility, Equipment, and Pets right now
+
--This includes Agility, Equipment, Pets, Prayers, and Constellations right now
  
 
local p = {}
 
local p = {}
Line 8: Line 8:
 
local Pets = require('Module:Pets')
 
local Pets = require('Module:Pets')
 
local Items = require('Module:Items')
 
local Items = require('Module:Items')
 +
local GatheringSkills = require('Module:Skills/Gathering')
 
local Agility = require('Module:Skills/Agility')
 
local Agility = require('Module:Skills/Agility')
 
local Prayer = require('Module:Prayer')
 
local Prayer = require('Module:Prayer')
Line 15: Line 16:
 
--First up, functions to get all the things in a category that have a given modifier:
 
--First up, functions to get all the things in a category that have a given modifier:
 
function p.getModifierValue(modifiers, modifier, skill, getOpposites)
 
function p.getModifierValue(modifiers, modifier, skill, getOpposites)
  --Sometimes nil modifier sets will get here, which is fine. Just return 0 immediately
+
--Sometimes nil modifier sets will get here, which is fine. Just return 0 immediately
  if modifiers == nil then
+
if modifiers == nil then
    return 0
+
return 0
  end
+
end
 
+
 
  --Make sure we have the skillID and not the name
+
--Make sure we have the skillID and not the name
  if skill == '' then
+
if skill == '' then
    skill = nil
+
skill = nil
  elseif type(skill) == 'string' then
+
elseif type(skill) == 'string' then
    skill = Constants.getSkillID(skill)
+
skill = Constants.getSkillID(skill)
  end
+
end
  
  --By default, attempt to add the increased and decreased prefixes to the modifier
+
--By default, attempt to add the increased and decreased prefixes to the modifier
  --But if getOpposites is false, only look for an exact match
+
--But if getOpposites is false, only look for an exact match
  local increaseMod, decreaseMod = '', ''
+
local increaseMod, decreaseMod = '', ''
  if getOpposites == nil or getOpposites then
+
if getOpposites == nil or getOpposites then
    increaseMod = 'increased'..modifier
+
increaseMod = 'increased'..modifier
    decreaseMod = 'decreased'..modifier
+
decreaseMod = 'decreased'..modifier
  else
+
else
    increaseMod = modifier
+
increaseMod = modifier
  end
+
end
  
  local increaseVal, decreaseVal = 0, 0
+
local increaseVal, decreaseVal = 0, 0
  if modifiers[increaseMod] ~= nil and modifiers[increaseMod] ~= nil then
+
if modifiers[increaseMod] ~= nil and modifiers[increaseMod] ~= nil then
    if type(modifiers[increaseMod]) == 'table' then
+
if type(modifiers[increaseMod]) == 'table' then
      for i, subVal in Shared.skpairs(modifiers[increaseMod]) do
+
for i, subVal in Shared.skpairs(modifiers[increaseMod]) do
        if subVal[1] == skill then
+
if subVal[1] == skill then
increaseVal = subVal[2]
+
increaseVal = subVal[2]
        elseif skill == nil or skill == '' then
+
elseif skill == nil or skill == '' then
        increaseVal = increaseVal + subVal[2]
+
increaseVal = increaseVal + subVal[2]
        end
+
end
      end
+
end
    else
+
else
      increaseVal = modifiers[increaseMod]
+
increaseVal = modifiers[increaseMod]
    end
+
end
  end
+
end
  
  if modifiers[decreaseMod] ~= nil and modifiers[decreaseMod] ~= nil then
+
if modifiers[decreaseMod] ~= nil and modifiers[decreaseMod] ~= nil then
    if type(modifiers[decreaseMod]) == 'table' then
+
if type(modifiers[decreaseMod]) == 'table' then
      for i, subVal in Shared.skpairs(modifiers[decreaseMod]) do
+
for i, subVal in Shared.skpairs(modifiers[decreaseMod]) do
        if subVal[1] == skill then
+
if subVal[1] == skill then
decreaseVal = subVal[2]
+
decreaseVal = subVal[2]
        elseif skill == nil or skill == '' then
+
elseif skill == nil or skill == '' then
        decreaseVal = decreaseVal + subVal[2]
+
decreaseVal = decreaseVal + subVal[2]
        end
+
end
      end
+
end
    else
+
else
      decreaseVal = modifiers[decreaseMod]
+
decreaseVal = modifiers[decreaseMod]
    end
+
end
  end
+
end
  
  return increaseVal - decreaseVal
+
return increaseVal - decreaseVal
 
end
 
end
  
 
function p.getItemsWithModifier(modifiers, skill, getOpposites)
 
function p.getItemsWithModifier(modifiers, skill, getOpposites)
  if type(modifiers) == 'string' then
+
if type(modifiers) == 'string' then
    modifiers = {modifiers}
+
modifiers = {modifiers}
  end
+
end
  local itemList = Items.getItems(
+
local itemList = Items.getItems(
        function(item)
+
function(item)
          local result = false
+
for i, mod in Shared.skpairs(modifiers) do
          for i, mod in Shared.skpairs(modifiers) do
+
if p.getModifierValue(item.modifiers, mod, skill, getOpposites) ~= 0 then
            if p.getModifierValue(item.modifiers, mod, skill, getOpposites) ~= 0 then
+
return true
              result = true
+
end
              break
+
end
            end
+
return false
          end
+
end)
          return result
+
return itemList
        end)
 
  return itemList  
 
 
end
 
end
  
 
function p.getObstaclesWithModifier(modifiers, skill, getOpposites)
 
function p.getObstaclesWithModifier(modifiers, skill, getOpposites)
  if type(modifiers) == 'string' then
+
if type(modifiers) == 'string' then
    modifiers = {modifiers}
+
modifiers = {modifiers}
  end
+
end
  local obstList = Agility.getObstacles(
+
local obstList = Agility.getObstacles(
        function(obst)
+
function(obst)
          local result = false
+
for i, mod in Shared.skpairs(modifiers) do
          for i, mod in Shared.skpairs(modifiers) do
+
if p.getModifierValue(obst.modifiers, mod, skill, getOpposites) ~= 0 then
            if p.getModifierValue(obst.modifiers, mod, skill, getOpposites) ~= 0 then
+
return true
              result = true
+
end
              break
+
end
            end
+
return false
          end
+
end)
          return result
+
return obstList
        end)
+
end
  return obstList
+
 
 +
function p.getConstellationsWithModifier(modifiers, skill, getOpposites)
 +
if type(modifiers) == 'string' then
 +
modifiers = {modifiers}
 +
end
 +
local consList = GatheringSkills.getConstellations(
 +
function(cons)
 +
local consMods = GatheringSkills._buildAstrologyModifierArray(cons, 1, true, true, true, true)
 +
for i, modifier in ipairs(modifiers) do
 +
if p.getModifierValue(consMods, modifier, skill, getOpposites) ~= 0 then
 +
return true
 +
end
 +
end
 +
return false
 +
end)
 +
return consList
 
end
 
end
  
 
function p.getPillarsWithModifier(modifiers, skill, getOpposites)
 
function p.getPillarsWithModifier(modifiers, skill, getOpposites)
  if type(modifiers) == 'string' then
+
if type(modifiers) == 'string' then
    modifiers = {modifiers}
+
modifiers = {modifiers}
  end
+
end
  local pillarList = Agility.getPillars(
+
local pillarList = Agility.getPillars(
        function(pillar)
+
function(pillar)
          local result = false
+
for i, mod in Shared.skpairs(modifiers) do
          for i, mod in Shared.skpairs(modifiers) do
+
if p.getModifierValue(pillar.modifiers, mod, skill, getOpposites) ~= 0 then
            if p.getModifierValue(pillar.modifiers, mod, skill, getOpposites) ~= 0 then
+
return true
              result = true
+
end
              break
+
end
            end
+
return false
          end
+
end)
          return result
+
return pillarList
        end)
 
  return pillarList
 
 
end
 
end
  
 
function p.getPetsWithModifier(modifiers, skill, getOpposites)
 
function p.getPetsWithModifier(modifiers, skill, getOpposites)
  if type(modifiers) == 'string' then
+
if type(modifiers) == 'string' then
    modifiers = {modifiers}
+
modifiers = {modifiers}
  end
+
end
  local petList = Pets.getPets(
+
local petList = Pets.getPets(
        function(pet)
+
function(pet)
          local result = false
+
for i, mod in Shared.skpairs(modifiers) do
          for i, mod in Shared.skpairs(modifiers) do
+
if p.getModifierValue(pet.modifiers, mod, skill, getOpposites) ~= 0 then
            if p.getModifierValue(pet.modifiers, mod, skill, getOpposites) ~= 0 then
+
return true
              result = true
+
end
              break
+
end
            end
+
return false
          end
+
end)
          return result
+
return petList
        end)
 
  return petList
 
 
end
 
end
  
Line 158: Line 168:
  
 
function p.getUpgradesWithModifier(modifiers, skill, getOpposites)
 
function p.getUpgradesWithModifier(modifiers, skill, getOpposites)
  if type(modifiers) == 'string' then
+
if type(modifiers) == 'string' then
    modifiers = {modifiers}
+
modifiers = {modifiers}
  end
+
end
  local upgradeList = Shop.getPurchases(
+
local upgradeList = Shop.getPurchases(
        function(category, purchase)
+
function(category, purchase)
          local result = false
+
for i, mod in Shared.skpairs(modifiers) do
          for i, mod in Shared.skpairs(modifiers) do
+
if p.getModifierValue(purchase.contains.modifiers, mod, skill, getOpposites) ~= 0 then
            if p.getModifierValue(purchase.contains.modifiers, mod, skill, getOpposites) ~= 0 then
+
return true
              result = true
+
end
              break
+
end
            end
+
return false
          end
+
end)
          return result
+
return upgradeList
        end)
 
return upgradeList
 
 
end
 
end
  
 
function p._getModifierTable(modifiers, skill, columnName, getOpposites, displayOtherMods, maxOtherMods)
 
function p._getModifierTable(modifiers, skill, columnName, getOpposites, displayOtherMods, maxOtherMods)
  local modifierNames = {}
+
local modifierNames = {}
  if type(modifiers) == 'string' then
+
if type(modifiers) == 'string' then
    modifiers = {modifiers}
+
modifiers = {modifiers}
  end
+
end
  for i, modifier in pairs(modifiers) do
+
for i, modifier in pairs(modifiers) do
    if getOpposites then
+
if getOpposites then
      table.insert(modifierNames, 'increased'..modifier)
+
table.insert(modifierNames, 'increased'..modifier)
      table.insert(modifierNames, 'decreased'..modifier)
+
table.insert(modifierNames, 'decreased'..modifier)
    else
+
else
      table.insert(modifierNames, modifier)
+
table.insert(modifierNames, modifier)
    end
+
end
  end
+
end
 +
 
 +
local hasOtherModifiers = false
 +
local modifierCount = Shared.tableCount(modifiers)
 +
 
 +
if skill == '' then
 +
skill = nil
 +
elseif type(skill) == 'string' then
 +
skill = Constants.getSkillID(skill)
 +
end
 +
 
 +
local getModText =
 +
function(modifiers)
 +
local modTextArray = { ["visible"] = {}, ["overflow"] = {} }
 +
local otherModCount = 0
 +
local mainModText = {}
 +
for modName, modValue in Shared.skpairs(modifiers) do
 +
if Shared.contains(modifierNames, modName) then
 +
if type(modValue) == 'table' and type(modValue[1]) == 'table' then
 +
for j, subVal in ipairs(modValue) do
 +
if subVal[1] == skill or skill == nil or skill == '' then
 +
table.insert(mainModText, Constants._getModifierText(modName, subVal))
 +
else
 +
otherModCount = otherModCount + 1
 +
local key = ((maxOtherMods == nil or otherModCount <= maxOtherMods) and 'visible') or 'overflow'
 +
table.insert(modTextArray[key], Constants._getModifierText(modName, subVal))
 +
end
 +
end
 +
else
 +
table.insert(mainModText, Constants._getModifierText(modName, modValue))
 +
end
 +
else
 +
modValue = (type(modValue) == 'table' and type(modValue[1]) == 'table' and modValue or {modValue})
 +
for j, subValue in ipairs(modValue) do
 +
otherModCount = otherModCount + 1
 +
local key = ((maxOtherMods == nil or otherModCount <= maxOtherMods) and 'visible') or 'overflow'
 +
table.insert(modTextArray[key], Constants._getModifierText(modName, subValue))
 +
end
 +
end
 +
end
 +
 
 +
local overflowModCount = Shared.tableCount(modTextArray['overflow'])
 +
if overflowModCount == 1 then
 +
table.insert(modTextArray['visible'], modTextArray['overflow'][1])
 +
end
 +
local otherModText = {table.concat(modTextArray['visible'], '<br/>')}
 +
 
 +
if overflowModCount > 1 then
 +
-- Number of other modifiers for the object exceed the specified maximum
 +
table.insert(otherModText, '<br/><span style="float:left;margin-left:0;margin-right:1em" class="mw-collapsible mw-collapsed" ')
 +
table.insert(otherModText, 'data-expandtext="Show ' .. Shared.formatnum(overflowModCount) .. ' more modifiers", data-collapsetext="Hide">')
 +
table.insert(otherModText, table.concat(modTextArray['overflow'], '<br/>') .. '</span>')
 +
end
 +
return table.concat(mainModText, '<br/>'), table.concat(otherModText)
 +
end
 +
 
 +
local tableArray = {}
 +
--Going through each type of thing to add to the array
 +
local itemList = p.getItemsWithModifier(modifiers, skill, getOpposites)
 +
for i, item in Shared.skpairs(itemList) do
 +
local row = {}
 +
row.name = item.name
 +
row.icon = Icons.Icon({item.name, type='item'})
 +
row.type = 'Item'
 +
--For equipment, show the slot they go in
 +
if item.validSlots ~= nil then
 +
row.type = row.type..' ('..table.concat(item.validSlots, ', ')..')'
 +
end
 +
local totalVal = 0
 +
for i, mod in pairs(modifiers) do
 +
totalVal = totalVal + p.getModifierValue(item.modifiers, mod, skill, getOpposites)
 +
end
 +
row.val = totalVal
 +
 
 +
row.modifierText, row.otherModifiers = getModText(item.modifiers)
 +
 
 +
if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
 +
hasOtherModifiers = true
 +
end
 +
 
 +
table.insert(tableArray, row)
 +
end
  
  local hasOtherModifiers = false
+
local petList = p.getPetsWithModifier(modifiers, skill, getOpposites)
  local modifierCount = Shared.tableCount(modifiers)
+
for i, pet in Shared.skpairs(petList) do
 +
local row = {}
 +
row.name = pet.name
 +
row.icon = Icons.Icon({pet.name, type='pet'})
 +
row.type = '[[Pets|Pet]]'
 +
local totalVal = 0
 +
for i, mod in pairs(modifiers) do
 +
totalVal = totalVal + p.getModifierValue(pet.modifiers, mod, skill, getOpposites)
 +
end
 +
row.val = totalVal
  
  if skill == '' then
+
row.modifierText, row.otherModifiers = getModText(pet.modifiers)
    skill = nil
 
  elseif type(skill) == 'string' then
 
    skill = Constants.getSkillID(skill)
 
  end
 
  
  local getModText =
+
if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
    function(modifiers)
+
hasOtherModifiers = true
      local modTextArray = { ["visible"] = {}, ["overflow"] = {} }
+
end
      local otherModCount = 0
 
      local mainModText = {}
 
      for modName, modValue in Shared.skpairs(modifiers) do
 
        if Shared.contains(modifierNames, modName) then
 
          if type(modValue) == 'table' then
 
            for j, subVal in ipairs(modValue) do
 
              if subVal[1] == skill or skill == nil or skill == '' then
 
                table.insert(mainModText, Constants._getModifierText(modName, subVal))
 
              else
 
              otherModCount = otherModCount + 1
 
              local key = ((maxOtherMods == nil or otherModCount <= maxOtherMods) and 'visible') or 'overflow'
 
              table.insert(modTextArray[key], Constants._getModifierText(modName, subVal))
 
              end
 
            end
 
          else
 
            table.insert(mainModText, Constants._getModifierText(modName, modValue))
 
          end
 
        else
 
          modValue = (type(modValue) == 'table' and modValue or {modValue})
 
          for j, subValue in ipairs(modValue) do
 
            otherModCount = otherModCount + 1
 
            local key = ((maxOtherMods == nil or otherModCount <= maxOtherMods) and 'visible') or 'overflow'
 
            table.insert(modTextArray[key], Constants._getModifierText(modName, subValue))
 
          end
 
        end
 
      end
 
     
 
  local overflowModCount = Shared.tableCount(modTextArray['overflow'])
 
      if overflowModCount == 1 then
 
      table.insert(modTextArray['visible'], modTextArray['overflow'][1])
 
      end
 
  local otherModText = {table.concat(modTextArray['visible'], '<br/>')}
 
 
 
  if overflowModCount > 1 then
 
  -- Number of other modifiers for the object exceed the specified maximum
 
  table.insert(otherModText, '<br/><span style="float:left;margin-left:0;margin-right:1em" class="mw-collapsible mw-collapsed" ')
 
  table.insert(otherModText, 'data-expandtext="Show ' .. Shared.formatnum(overflowModCount) .. ' more modifiers", data-collapsetext="Hide">')
 
  table.insert(otherModText, table.concat(modTextArray['overflow'], '<br/>') .. '</span>')
 
  end
 
      return table.concat(mainModText, '<br/>'), table.concat(otherModText)
 
    end
 
  
  local tableArray = {}
+
table.insert(tableArray, row)
  --Going through each type of thing to add to the array
 
  local itemList = p.getItemsWithModifier(modifiers, skill, getOpposites)
 
  for i, item in Shared.skpairs(itemList) do
 
    local row = {}
 
    row.name = item.name
 
    row.icon = Icons.Icon({item.name, type='item'})
 
    row.type = 'Item'
 
    --For equipment, show the slot they go in
 
if item.validSlots ~= nil then
 
  row.type = row.type..' ('..table.concat(item.validSlots, ', ')..')'
 
 
end
 
end
    local totalVal = 0
 
    for i, mod in pairs(modifiers) do
 
      totalVal = totalVal + p.getModifierValue(item.modifiers, mod, skill, getOpposites)
 
    end
 
    row.val = totalVal
 
  
    row.modifierText, row.otherModifiers = getModText(item.modifiers)
+
local obstList = p.getObstaclesWithModifier(modifiers, skill, getOpposites)
 +
for i, obst in Shared.skpairs(obstList) do
 +
local row = {}
 +
row.name = obst.name
 +
row.icon = Icons.Icon({'Agility', obst.name, type='skill'})
 +
row.type = '[[Agility#Obstacles|Agility Obstacle '..tostring(tonumber(obst.category)+1)..']]'
 +
local totalVal = 0
 +
for i, mod in pairs(modifiers) do
 +
totalVal = totalVal + p.getModifierValue(obst.modifiers, mod, skill, getOpposites)
 +
end
 +
row.val = totalVal
 +
 
 +
row.modifierText, row.otherModifiers = getModText(obst.modifiers)
  
    if string.len(row.otherModifiers) > 0 then
+
if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
      hasOtherModifiers = true
+
hasOtherModifiers = true
    end
+
end
  
    table.insert(tableArray, row)
+
table.insert(tableArray, row)
  end
+
end
  local petList = p.getPetsWithModifier(modifiers, skill, getOpposites)
 
  for i, pet in Shared.skpairs(petList) do
 
    local row = {}
 
    row.name = pet.name
 
    row.icon = Icons.Icon({pet.name, type='pet'})
 
    row.type = '[[Pets|Pet]]'
 
    local totalVal = 0
 
    for i, mod in pairs(modifiers) do
 
      totalVal = totalVal + p.getModifierValue(pet.modifiers, mod, skill, getOpposites)
 
    end
 
    row.val = totalVal
 
  
    row.modifierText, row.otherModifiers = getModText(pet.modifiers)
+
local pillarList = p.getPillarsWithModifier(modifiers, skill, getOpposites)
 +
for i, pillar in Shared.skpairs(pillarList) do
 +
local row = {}
 +
row.name = pillar.name
 +
row.icon = Icons.Icon({'Agility', pillar.name, type='skill'})
 +
row.type = '[[Agility#Passive Pillars|Agility Pillar]]'
 +
local totalVal = 0
 +
for i, mod in pairs(modifiers) do
 +
totalVal = totalVal + p.getModifierValue(pillar.modifiers, mod, skill, getOpposites)
 +
end
 +
row.val = totalVal
  
    if string.len(row.otherModifiers) > 0 then
+
row.modifierText, row.otherModifiers = getModText(pillar.modifiers)
      hasOtherModifiers = true
 
    end
 
  
    table.insert(tableArray, row)
+
if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
  end
+
hasOtherModifiers = true
  local obstList = p.getObstaclesWithModifier(modifiers, skill, getOpposites)
+
end
  for i, obst in Shared.skpairs(obstList) do
 
    local row = {}
 
    row.name = obst.name
 
    row.icon = Icons.Icon({'Agility', obst.name, type='skill'})
 
    row.type = '[[Agility#Obstacles|Agility Obstacle '..tostring(tonumber(obst.category)+1)..']]'
 
    local totalVal = 0
 
    for i, mod in pairs(modifiers) do
 
      totalVal = totalVal + p.getModifierValue(obst.modifiers, mod, skill, getOpposites)
 
    end
 
    row.val = totalVal
 
  
    row.modifierText, row.otherModifiers = getModText(obst.modifiers)
+
table.insert(tableArray, row)
 +
end
  
    if string.len(row.otherModifiers) > 0 then
+
local prayerList = p.getPrayersWithModifier(modifiers, skill, getOpposites)
      hasOtherModifiers = true
+
for i, prayer in ipairs(prayerList) do
    end
+
local row = {}
 +
row.name = prayer.name
 +
row.icon = Icons.Icon({prayer.name, type='prayer'})
 +
row.type = [[Prayer]]
 +
local totalVal = 0
 +
for i, mod in ipairs(modifiers) do
 +
totalVal = totalVal + p.getModifierValue(prayer.modifiers, mod, skill, getOpposites)
 +
end
 +
row.val = totalVal
  
    table.insert(tableArray, row)
+
row.modifierText, row.otherModifiers = getModText(prayer.modifiers)
  end
 
  
  local pillarList = p.getPillarsWithModifier(modifiers, skill, getOpposites)
+
if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
  for i, pillar in Shared.skpairs(pillarList) do
+
hasOtherModifiers = true
    local row = {}
+
end
    row.name = pillar.name
 
    row.icon = Icons.Icon({'Agility', pillar.name, type='skill'})
 
    row.type = '[[Agility#Passive Pillars|Agility Pillar]]'
 
    local totalVal = 0
 
    for i, mod in pairs(modifiers) do
 
      totalVal = totalVal + p.getModifierValue(pillar.modifiers, mod, skill, getOpposites)
 
    end
 
    row.val = totalVal
 
  
    row.modifierText, row.otherModifiers = getModText(pillar.modifiers)
+
table.insert(tableArray, row)
 +
end
  
    if string.len(row.otherModifiers) > 0 then
+
local upgradeList = p.getUpgradesWithModifier(modifiers, skill, getOpposites)
      hasOtherModifiers = true
+
for i, upgrade in Shared.skpairs(upgradeList) do
    end
+
local row = {}
 +
row.name = upgrade.name
 +
row.icon = Icons.Icon({upgrade.name, type='upgrade'})
 +
row.type = '[[Shop|Upgrade]]'
 +
local totalVal = 0
 +
for i, mod in pairs(modifiers) do
 +
totalVal = totalVal + p.getModifierValue(upgrade.contains.modifiers, mod, skill, getOpposites)
 +
end
 +
row.val = totalVal
  
    table.insert(tableArray, row)
+
row.modifierText, row.otherModifiers = getModText(upgrade.contains.modifiers)
  end
 
 
 
  local prayerList = p.getPrayersWithModifier(modifiers, skill, getOpposites)
 
  for i, prayer in ipairs(prayerList) do
 
  local row = {}
 
  row.name = prayer.name
 
  row.icon = Icons.Icon({prayer.name, type='prayer'})
 
  row.type = [[Prayer]]
 
  local totalVal = 0
 
  for i, mod in ipairs(modifiers) do
 
  totalVal = totalVal + p.getModifierValue(prayer.modifiers, mod, skill, getOpposites)
 
  end
 
  row.val = totalVal
 
 
 
  row.modifierText, row.otherModifiers = getModText(prayer.modifiers)
 
 
 
  if string.len(row.otherModifiers) > 0 then
 
  hasOtherModifiers = true
 
  end
 
 
 
  table.insert(tableArray, row)
 
  end
 
 
 
  local upgradeList = p.getUpgradesWithModifier(modifiers, skill, getOpposites)
 
  for i, upgrade in Shared.skpairs(upgradeList) do
 
    local row = {}
 
    row.name = upgrade.name
 
    row.icon = Icons.Icon({upgrade.name, type='upgrade'})
 
    row.type = '[[Shop|Upgrade]]'
 
    local totalVal = 0
 
    for i, mod in pairs(modifiers) do
 
      totalVal = totalVal + p.getModifierValue(upgrade.contains.modifiers, mod, skill, getOpposites)
 
    end
 
    row.val = totalVal
 
  
    row.modifierText, row.otherModifiers = getModText(upgrade.contains.modifiers)
+
if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
 +
hasOtherModifiers = true
 +
end
  
    if string.len(row.otherModifiers) > 0 then
+
table.insert(tableArray, row)
      hasOtherModifiers = true
+
end
    end
 
  
    table.insert(tableArray, row)
+
local constellationList = p.getConstellationsWithModifier(modifiers, skill, getOpposites)
  end
+
for i, cons in ipairs(constellationList) do
 +
local row = {}
 +
row.name = cons.name
 +
row.icon = Icons.Icon({cons.name, type='constellation'})
 +
row.type = '[[Astrology#Constellations|Constellation]]'
 +
row.val = 15 -- Assume highest possible, the range is 1 to 15 inclusive
  
  local result = '{| class="wikitable sortable stickyHeader"'
+
local modList = GatheringSkills._buildAstrologyModifierArray(cons, {1, 15}, true, true, true, true)
  result = result..'\r\n|- class="headerRow-0"'
+
row.modifierText, row.otherModifiers = getModText(modList)
  result = result..'\r\n!Source!!Type!!'..columnName
 
  if hasOtherModifiers and displayOtherMods then result = result..'!!Other Modifiers' end
 
  
  --Sort by value if only one modifier was passed in
+
if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
  --Otherwise sort alphabetically by type, then name
+
hasOtherModifiers = true
  table.sort(tableArray, function(a, b)
+
end
                          if modifierCount == 1 and a.val ~= b.val then
 
                            return a.val > b.val
 
                          elseif a.type ~= b.type then
 
                            return a.type < b.type
 
                          else
 
                            return a.name < b.name
 
                          end
 
                        end)
 
  for i, row in Shared.skpairs(tableArray) do
 
    result = result..'\r\n|-'
 
    result = result..'\r\n|data-sort-value="'..row.name..'"|'..row.icon
 
    result = result..'||'..row.type..'||data-sort-value="'..row.val..'"|'..row.modifierText
 
    if hasOtherModifiers and displayOtherMods then
 
      result = result..'||'..row.otherModifiers
 
    end
 
  end
 
  
  result = result..'\r\n|}'
+
table.insert(tableArray, row)
  return result
+
end
 +
 
 +
local result = '{| class="wikitable sortable stickyHeader"'
 +
result = result..'\r\n|- class="headerRow-0"'
 +
result = result..'\r\n!Source!!Type!!'..columnName
 +
if hasOtherModifiers and displayOtherMods then result = result..'!!Other Modifiers' end
 +
 
 +
--Sort by value if only one modifier was passed in
 +
--Otherwise sort alphabetically by type, then name
 +
table.sort(tableArray, function(a, b)
 +
if modifierCount == 1 and a.val ~= b.val then
 +
return a.val > b.val
 +
elseif a.type ~= b.type then
 +
return a.type < b.type
 +
else
 +
return a.name < b.name
 +
end
 +
end)
 +
for i, row in Shared.skpairs(tableArray) do
 +
result = result..'\r\n|-'
 +
result = result..'\r\n|data-sort-value="'..row.name..'"|'..row.icon
 +
result = result..'||'..row.type..'||data-sort-value="'..row.val..'"|'..row.modifierText
 +
if hasOtherModifiers and displayOtherMods then
 +
result = result..'||'..row.otherModifiers
 +
end
 +
end
 +
 
 +
result = result..'\r\n|}'
 +
return result
 
end
 
end
  
 
function p.getModifierTable(frame)
 
function p.getModifierTable(frame)
  local modifier = frame.args ~= nil and frame.args[1] or frame[1]
+
local modifier = frame.args ~= nil and frame.args[1] or frame[1]
  local skill = frame.args ~= nil and frame.args.skill or frame.skill
+
local skill = frame.args ~= nil and frame.args.skill or frame.skill
  local columnName = frame.args ~= nil and frame.args[2] or frame[2]
+
local columnName = frame.args ~= nil and frame.args[2] or frame[2]
  local getOpposites = frame.args ~= nil and frame.args[3] or frame[3]
+
local getOpposites = frame.args ~= nil and frame.args[3] or frame[3]
  local displayOtherMods = frame.args ~= nil and frame.args.displayOtherMods or frame.displayOtherMods
+
local displayOtherMods = frame.args ~= nil and frame.args.displayOtherMods or frame.displayOtherMods
  local maxOtherMods = frame.args ~= nil and tonumber(frame.args.maxOtherMods) or 5
+
local maxOtherMods = frame.args ~= nil and tonumber(frame.args.maxOtherMods) or 5
  
  if Shared.contains(modifier, ',') then
+
if Shared.contains(modifier, ',') then
    modifier = Shared.splitString(modifier, ',')
+
modifier = Shared.splitString(modifier, ',')
  end
+
end
 +
 
 +
if getOpposites ~= nil then
 +
getOpposites = string.upper(getOpposites) ~= 'FALSE'
 +
else
 +
getOpposites = true
 +
end
 +
 
 +
if displayOtherMods ~= nil then
 +
displayOtherMods = string.upper(displayOtherMods) ~= 'FALSE'
 +
else
 +
displayOtherMods = true
 +
end
  
  if getOpposites ~= nil then
+
return p._getModifierTable(modifier, skill, columnName, getOpposites, displayOtherMods, maxOtherMods)
    getOpposites = string.upper(getOpposites) ~= 'FALSE'
 
  else
 
    getOpposites = true
 
  end
 
 
 
  if displayOtherMods ~= nil then
 
  displayOtherMods = string.upper(displayOtherMods) ~= 'FALSE'
 
  else
 
  displayOtherMods = true
 
  end
 
 
 
  return p._getModifierTable(modifier, skill, columnName, getOpposites, displayOtherMods, maxOtherMods)
 
 
end
 
end
  
 
return p
 
return p

Revision as of 03:07, 25 January 2022

Documentation for this module may be created at Module:ModifierTables/doc

--Module that constructs tables for all things that can affect Player Modifiers
--This includes Agility, Equipment, Pets, Prayers, and Constellations right now

local p = {}

local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Pets = require('Module:Pets')
local Items = require('Module:Items')
local GatheringSkills = require('Module:Skills/Gathering')
local Agility = require('Module:Skills/Agility')
local Prayer = require('Module:Prayer')
local Shop = require('Module:Shop')
local Icons = require('Module:Icons')

--First up, functions to get all the things in a category that have a given modifier:
function p.getModifierValue(modifiers, modifier, skill, getOpposites)
	--Sometimes nil modifier sets will get here, which is fine. Just return 0 immediately
	if modifiers == nil then
		return 0
	end

	--Make sure we have the skillID and not the name
	if skill == '' then
		skill = nil
	elseif type(skill) == 'string' then
		skill = Constants.getSkillID(skill)
	end

	--By default, attempt to add the increased and decreased prefixes to the modifier
	--But if getOpposites is false, only look for an exact match
	local increaseMod, decreaseMod = '', ''
	if getOpposites == nil or getOpposites then
		increaseMod = 'increased'..modifier
		decreaseMod = 'decreased'..modifier
	else
		increaseMod = modifier
	end

	local increaseVal, decreaseVal = 0, 0
	if modifiers[increaseMod] ~= nil and modifiers[increaseMod] ~= nil then
		if type(modifiers[increaseMod]) == 'table' then
			for i, subVal in Shared.skpairs(modifiers[increaseMod]) do
				if subVal[1] == skill then
					increaseVal = subVal[2]
				elseif skill == nil or skill == '' then
					increaseVal = increaseVal + subVal[2]
				end
			end
		else
			increaseVal = modifiers[increaseMod]
		end
	end

	if modifiers[decreaseMod] ~= nil and modifiers[decreaseMod] ~= nil then
		if type(modifiers[decreaseMod]) == 'table' then
			for i, subVal in Shared.skpairs(modifiers[decreaseMod]) do
				if subVal[1] == skill then
					decreaseVal = subVal[2]
				elseif skill == nil or skill == '' then
					decreaseVal = decreaseVal + subVal[2]
				end
			end
		else
			decreaseVal = modifiers[decreaseMod]
		end
	end

	return increaseVal - decreaseVal
end

function p.getItemsWithModifier(modifiers, skill, getOpposites)
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	local itemList = Items.getItems(
		function(item)
			for i, mod in Shared.skpairs(modifiers) do
				if p.getModifierValue(item.modifiers, mod, skill, getOpposites) ~= 0 then
					return true
				end
			end
			return false
		end)
	return itemList
end

function p.getObstaclesWithModifier(modifiers, skill, getOpposites)
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	local obstList = Agility.getObstacles(
		function(obst)
			for i, mod in Shared.skpairs(modifiers) do
				if p.getModifierValue(obst.modifiers, mod, skill, getOpposites) ~= 0 then
					return true
				end
			end
			return false
		end)
	return obstList
end

function p.getConstellationsWithModifier(modifiers, skill, getOpposites)
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	local consList = GatheringSkills.getConstellations(
			function(cons)
				local consMods = GatheringSkills._buildAstrologyModifierArray(cons, 1, true, true, true, true)
				for i, modifier in ipairs(modifiers) do
					if p.getModifierValue(consMods, modifier, skill, getOpposites) ~= 0 then
						return true
					end
				end
				return false
			end)
	return consList
end

function p.getPillarsWithModifier(modifiers, skill, getOpposites)
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	local pillarList = Agility.getPillars(
		function(pillar)
			for i, mod in Shared.skpairs(modifiers) do
				if p.getModifierValue(pillar.modifiers, mod, skill, getOpposites) ~= 0 then
					return true
				end
			end
			return false
		end)
	return pillarList
end

function p.getPetsWithModifier(modifiers, skill, getOpposites)
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	local petList = Pets.getPets(
		function(pet)
			for i, mod in Shared.skpairs(modifiers) do
				if p.getModifierValue(pet.modifiers, mod, skill, getOpposites) ~= 0 then
					return true
				end
			end
			return false
		end)
	return petList
end

function p.getPrayersWithModifier(modifiers, skill, getOpposites)
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	local prayerList = Prayer.getPrayers(
		function(prayer)
			for i, mod in ipairs(modifiers) do
				if p.getModifierValue(prayer.modifiers, mod, skill, getOpposites) ~= 0 then
					return true
				end
			end
			return false
		end)
	return prayerList
end

function p.getUpgradesWithModifier(modifiers, skill, getOpposites)
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	local upgradeList = Shop.getPurchases(
		function(category, purchase)
			for i, mod in Shared.skpairs(modifiers) do
				if p.getModifierValue(purchase.contains.modifiers, mod, skill, getOpposites) ~= 0 then
					return true
				end
			end
			return false
		end)
	return upgradeList
end

function p._getModifierTable(modifiers, skill, columnName, getOpposites, displayOtherMods, maxOtherMods)
	local modifierNames = {}
	if type(modifiers) == 'string' then
		modifiers = {modifiers}
	end
	for i, modifier in pairs(modifiers) do
		if getOpposites then
			table.insert(modifierNames, 'increased'..modifier)
			table.insert(modifierNames, 'decreased'..modifier)
		else
			table.insert(modifierNames, modifier)
		end
	end

	local hasOtherModifiers = false
	local modifierCount = Shared.tableCount(modifiers)

	if skill == '' then
		skill = nil
	elseif type(skill) == 'string' then
		skill = Constants.getSkillID(skill)
	end

	local getModText =
		function(modifiers)
			local modTextArray = { ["visible"] = {}, ["overflow"] = {} }
			local otherModCount = 0
			local mainModText = {}
			for modName, modValue in Shared.skpairs(modifiers) do
				if Shared.contains(modifierNames, modName) then
					if type(modValue) == 'table' and type(modValue[1]) == 'table' then
						for j, subVal in ipairs(modValue) do
							if subVal[1] == skill or skill == nil or skill == '' then
								table.insert(mainModText, Constants._getModifierText(modName, subVal))
							else
								otherModCount = otherModCount + 1
								local key = ((maxOtherMods == nil or otherModCount <= maxOtherMods) and 'visible') or 'overflow'
								table.insert(modTextArray[key], Constants._getModifierText(modName, subVal))
							end
						end
					else
						table.insert(mainModText, Constants._getModifierText(modName, modValue))
					end
				else
					modValue = (type(modValue) == 'table' and type(modValue[1]) == 'table' and modValue or {modValue})
					for j, subValue in ipairs(modValue) do
						otherModCount = otherModCount + 1
						local key = ((maxOtherMods == nil or otherModCount <= maxOtherMods) and 'visible') or 'overflow'
						table.insert(modTextArray[key], Constants._getModifierText(modName, subValue))
					end
				end
			end

			local overflowModCount = Shared.tableCount(modTextArray['overflow'])
			if overflowModCount == 1 then
				table.insert(modTextArray['visible'], modTextArray['overflow'][1])
			end
			local otherModText = {table.concat(modTextArray['visible'], '<br/>')}

			if overflowModCount > 1 then
				-- Number of other modifiers for the object exceed the specified maximum
				table.insert(otherModText, '<br/><span style="float:left;margin-left:0;margin-right:1em" class="mw-collapsible mw-collapsed" ')
				table.insert(otherModText, 'data-expandtext="Show ' .. Shared.formatnum(overflowModCount) .. ' more modifiers", data-collapsetext="Hide">')
				table.insert(otherModText, table.concat(modTextArray['overflow'], '<br/>') .. '</span>')
			end
			return table.concat(mainModText, '<br/>'), table.concat(otherModText)
		end

	local tableArray = {}
	--Going through each type of thing to add to the array
	local itemList = p.getItemsWithModifier(modifiers, skill, getOpposites)
	for i, item in Shared.skpairs(itemList) do
		local row = {}
		row.name = item.name
		row.icon = Icons.Icon({item.name, type='item'})
		row.type = 'Item'
		--For equipment, show the slot they go in
		if item.validSlots ~= nil then
			row.type = row.type..' ('..table.concat(item.validSlots, ', ')..')'
		end
		local totalVal = 0
		for i, mod in pairs(modifiers) do
			totalVal = totalVal + p.getModifierValue(item.modifiers, mod, skill, getOpposites)
		end
		row.val = totalVal

		row.modifierText, row.otherModifiers = getModText(item.modifiers)

		if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
			hasOtherModifiers = true
		end

		table.insert(tableArray, row)
	end

	local petList = p.getPetsWithModifier(modifiers, skill, getOpposites)
	for i, pet in Shared.skpairs(petList) do
		local row = {}
		row.name = pet.name
		row.icon = Icons.Icon({pet.name, type='pet'})
		row.type = '[[Pets|Pet]]'
		local totalVal = 0
		for i, mod in pairs(modifiers) do
			totalVal = totalVal + p.getModifierValue(pet.modifiers, mod, skill, getOpposites)
		end
		row.val = totalVal

		row.modifierText, row.otherModifiers = getModText(pet.modifiers)

		if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
			hasOtherModifiers = true
		end

		table.insert(tableArray, row)
	end

	local obstList = p.getObstaclesWithModifier(modifiers, skill, getOpposites)
	for i, obst in Shared.skpairs(obstList) do
		local row = {}
		row.name = obst.name
		row.icon = Icons.Icon({'Agility', obst.name, type='skill'})
		row.type = '[[Agility#Obstacles|Agility Obstacle '..tostring(tonumber(obst.category)+1)..']]'
		local totalVal = 0
		for i, mod in pairs(modifiers) do
			totalVal = totalVal + p.getModifierValue(obst.modifiers, mod, skill, getOpposites)
		end
		row.val = totalVal

		row.modifierText, row.otherModifiers = getModText(obst.modifiers)

		if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
			hasOtherModifiers = true
		end

		table.insert(tableArray, row)
	end

	local pillarList = p.getPillarsWithModifier(modifiers, skill, getOpposites)
	for i, pillar in Shared.skpairs(pillarList) do
		local row = {}
		row.name = pillar.name
		row.icon = Icons.Icon({'Agility', pillar.name, type='skill'})
		row.type = '[[Agility#Passive Pillars|Agility Pillar]]'
		local totalVal = 0
		for i, mod in pairs(modifiers) do
			totalVal = totalVal + p.getModifierValue(pillar.modifiers, mod, skill, getOpposites)
		end
		row.val = totalVal

		row.modifierText, row.otherModifiers = getModText(pillar.modifiers)

		if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
			hasOtherModifiers = true
		end

		table.insert(tableArray, row)
	end

	local prayerList = p.getPrayersWithModifier(modifiers, skill, getOpposites)
	for i, prayer in ipairs(prayerList) do
		local row = {}
		row.name = prayer.name
		row.icon = Icons.Icon({prayer.name, type='prayer'})
		row.type = [[Prayer]]
		local totalVal = 0
		for i, mod in ipairs(modifiers) do
			totalVal = totalVal + p.getModifierValue(prayer.modifiers, mod, skill, getOpposites)
		end
		row.val = totalVal

		row.modifierText, row.otherModifiers = getModText(prayer.modifiers)

		if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
			hasOtherModifiers = true
		end

		table.insert(tableArray, row)
	end

	local upgradeList = p.getUpgradesWithModifier(modifiers, skill, getOpposites)
	for i, upgrade in Shared.skpairs(upgradeList) do
		local row = {}
		row.name = upgrade.name
		row.icon = Icons.Icon({upgrade.name, type='upgrade'})
		row.type = '[[Shop|Upgrade]]'
		local totalVal = 0
		for i, mod in pairs(modifiers) do
			totalVal = totalVal + p.getModifierValue(upgrade.contains.modifiers, mod, skill, getOpposites)
		end
		row.val = totalVal

		row.modifierText, row.otherModifiers = getModText(upgrade.contains.modifiers)

		if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
			hasOtherModifiers = true
		end

		table.insert(tableArray, row)
	end

	local constellationList = p.getConstellationsWithModifier(modifiers, skill, getOpposites)
	for i, cons in ipairs(constellationList) do
		local row = {}
		row.name = cons.name
		row.icon = Icons.Icon({cons.name, type='constellation'})
		row.type = '[[Astrology#Constellations|Constellation]]'
		row.val = 15 -- Assume highest possible, the range is 1 to 15 inclusive

		local modList = GatheringSkills._buildAstrologyModifierArray(cons, {1, 15}, true, true, true, true)
		row.modifierText, row.otherModifiers = getModText(modList)

		if not hasOtherModifiers and string.len(row.otherModifiers) > 0 then
			hasOtherModifiers = true
		end

		table.insert(tableArray, row)
	end

	local result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!Source!!Type!!'..columnName
	if hasOtherModifiers and displayOtherMods then result = result..'!!Other Modifiers' end

	--Sort by value if only one modifier was passed in
	--Otherwise sort alphabetically by type, then name
	table.sort(tableArray, function(a, b)
			if modifierCount == 1 and a.val ~= b.val then
				return a.val > b.val
			elseif a.type ~= b.type then
				return a.type < b.type
			else
				return a.name < b.name
			end
		end)
	for i, row in Shared.skpairs(tableArray) do
		result = result..'\r\n|-'
		result = result..'\r\n|data-sort-value="'..row.name..'"|'..row.icon
		result = result..'||'..row.type..'||data-sort-value="'..row.val..'"|'..row.modifierText
		if hasOtherModifiers and displayOtherMods then
			result = result..'||'..row.otherModifiers
		end
	end

	result = result..'\r\n|}'
	return result
end

function p.getModifierTable(frame)
	local modifier = frame.args ~= nil and frame.args[1] or frame[1]
	local skill = frame.args ~= nil and frame.args.skill or frame.skill
	local columnName = frame.args ~= nil and frame.args[2] or frame[2]
	local getOpposites = frame.args ~= nil and frame.args[3] or frame[3]
	local displayOtherMods = frame.args ~= nil and frame.args.displayOtherMods or frame.displayOtherMods
	local maxOtherMods = frame.args ~= nil and tonumber(frame.args.maxOtherMods) or 5

	if Shared.contains(modifier, ',') then
		modifier = Shared.splitString(modifier, ',')
	end

	if getOpposites ~= nil then
		getOpposites = string.upper(getOpposites) ~= 'FALSE'
	else
		getOpposites = true
	end

	if displayOtherMods ~= nil then
		displayOtherMods = string.upper(displayOtherMods) ~= 'FALSE'
	else
		displayOtherMods = true
	end

	return p._getModifierTable(modifier, skill, columnName, getOpposites, displayOtherMods, maxOtherMods)
end

return p