Difference between revisions of "Module:ModifierTables"
From Melvor Idle
Falterfire (talk | contribs) (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 | + | --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 | |
− | + | 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 | end | ||
function p.getItemsWithModifier(modifiers, skill, getOpposites) | 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 | end | ||
function p.getObstaclesWithModifier(modifiers, skill, getOpposites) | 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 | end | ||
function p.getPillarsWithModifier(modifiers, skill, getOpposites) | 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 | end | ||
function p.getPetsWithModifier(modifiers, skill, getOpposites) | 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 | end | ||
Line 158: | Line 168: | ||
function p.getUpgradesWithModifier(modifiers, skill, getOpposites) | 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 | end | ||
function p._getModifierTable(modifiers, skill, columnName, getOpposites, displayOtherMods, maxOtherMods) | 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 | 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 | end | ||
function p.getModifierTable(frame) | 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 | 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