Anonymous

Module:Items/ComparisonTables: Difference between revisions

From Melvor Idle
added code to show special attacks in the Modifiers table for equipment because it seemed like the thing to do
(More abbreviation)
(added code to show special attacks in the Modifiers table for equipment because it seemed like the thing to do)
(48 intermediate revisions by 3 users not shown)
Line 1: Line 1:
local p = {}
local p = {}


local MonsterData = mw.loadData('Module:Monsters/data')
local Constants = require('Module:Constants')
local ItemData = mw.loadData('Module:Items/data')
local SkillData = mw.loadData('Module:Skills/data')
local Constants = mw.loadData('Module:Constants/data')
 
local Shared = require('Module:Shared')
local Shared = require('Module:Shared')
local Magic = require('Module:Magic')
local Areas = require('Module:CombatAreas')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')
local Items = require('Module:Items')
local Items = require('Module:Items')
local ItemSourceTables = require('Module:Items/SourceTables')


local weaponTypes = {'Magic Staff', 'Magic Wand', 'Ranged Weapon', 'Weapon'}
local weaponTypes = {'Magic Staff', 'Magic Wand', 'Ranged Weapon', 'Weapon'}


function p._getEquipmentTable(itemList)
local styleOverrides = {
  --Getting some lists set up here that will be used later
Melee = {'Slayer Helmet (Basic)', 'Slayer Platebody (Basic)', 'Paladin Gloves', 'Desert Wrappings', 'Almighty Lute', 'Candy Cane', 'Bob's Rake'},
  --First, the list of columns used by both weapons & armour
Ranged = {'Slayer Cowl (Basic)', 'Slayer Leather Body (Basic)', 'Ice Arrows'},
  local statColumns = {'stabAttackBonus', 'slashAttackBonus','blockAttackBonus','rangedAttackBonus', 'magicAttackBonus', 'strengthBonus', 'rangedStrengthBonus', 'magicDamageBonus', 'defenceBonus', 'rangedDefenceBonus', 'magicDefenceBonus', 'damageReduction', 'attackLevelRequired', 'defenceLevelRequired', 'rangedLevelRequired', 'magicLevelRequired'}
Magic = {'Slayer Wizard Hat (Basic)', 'Slayer Wizard Robes (Basic)', 'Enchanted Shield', 'Elementalist Gloves'},
None = {},
}
 
function p._getEquipmentTable(itemList, includeModifiers, includeDescription, sortByName)
if includeModifiers == nil then includeModifiers = false end
if sortByName == nil then sortByName = false end
 
--Getting some lists set up here that will be used later
--First, the list of columns used by both weapons & armour
local statColumns = {'stabAttackBonus', 'slashAttackBonus','blockAttackBonus','rangedAttackBonus', 'magicAttackBonus', 'meleeStrengthBonus', 'rangedStrengthBonus', 'magicDamageBonus', 'meleeDefenceBonus', 'rangedDefenceBonus', 'magicDefenceBonus', 'damageReduction', 'attackLevelRequired', 'defenceLevelRequired', 'rangedLevelRequired', 'magicLevelRequired'}
 
if(Shared.tableCount(itemList) == 0) then
return 'ERROR: you must select at least one item to get stats for[[Category:Pages with script errors]]'
end
 
local isWeaponType = ((itemList[1].validSlots ~= nil and Shared.contains(itemList[1].validSlots, 'Weapon'))
or (itemList[1].occupiesSlots ~= nil and Shared.contains(itemList[1].occupiesSlots, 'Weapon'))) and Shared.contains(weaponTypes, itemList[1].type)


  if(Shared.tableCount(itemList) == 0) then
--Now that we have a preliminary list, let's figure out which columns are irrelevant (IE are zero for all items in the selection)
    return 'ERROR: you must select at least one item to get stats for'
local ignoreColumns = Shared.clone(statColumns)
  end
for i, item in pairs(itemList) do
local ndx = 1
while Shared.tableCount(ignoreColumns) >= ndx do
if Items._getItemStat(item, ignoreColumns[ndx], true) ~= 0 then
table.remove(ignoreColumns, ndx)
else
ndx = ndx + 1
end
end
end


  local isWeaponType = Shared.contains(weaponTypes, itemList[1].type)
--Now to remove the ignored columns (and also we need to track groups like defence bonuses to see how many remain)
local attBonusCols = 5
local strBonusCols = 2
local defBonusCols = 3
local lvlReqCols = 4
local ndx = 1
while Shared.tableCount(statColumns) >= ndx do
local colName = statColumns[ndx]
if Shared.contains(ignoreColumns, colName) then
if Shared.contains(colName, 'AttackBonus') then attBonusCols = attBonusCols - 1 end
if Shared.contains(colName, 'trengthBonus') then strBonusCols = strBonusCols - 1 end
if Shared.contains(colName, 'efenceBonus') then defBonusCols = defBonusCols - 1 end
if Shared.contains(colName, 'LevelRequired') then lvlReqCols = lvlReqCols - 1 end
table.remove(statColumns, ndx)
else
ndx = ndx + 1
end
end


  --Now that we have a preliminary list, let's figure out which columns are irrelevant (IE are zero for all items in the selection)
--Alright, let's start the table by building the shared header
  local ignoreColumns = Shared.clone(statColumns)
local resultPart = {}
  for i, item in pairs(itemList) do
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"\r\n|-class="headerRow-0"')
    local ndx = 1
if isWeaponType then
    while Shared.tableCount(ignoreColumns) >= ndx do
--Weapons have extra columns here for Attack Speed and "Two Handed?"
      if Items._getItemStat(item, ignoreColumns[ndx], true) ~= 0 then
table.insert(resultPart, '\r\n!colspan="4"|')
        table.remove(ignoreColumns, ndx)
else
      else
table.insert(resultPart, '\r\n!colspan="2"|')
        ndx = ndx + 1
end
      end
if attBonusCols > 0 then
    end
table.insert(resultPart, '\r\n!colspan="'..attBonusCols..'"style="padding:0 0.5em 0 0.5em;"|Attack Bonus')
  end
end
if strBonusCols > 0 then
table.insert(resultPart, '\r\n!colspan="'..strBonusCols..'"style="padding:0 0.5em 0 0.5em;"|Str. Bonus')
end
if Shared.contains(statColumns, 'magicDamageBonus') then
table.insert(resultPart, '\r\n!colspan="1"style="padding:0 0.5em 0 0.5em;"|% Dmg Bonus')
end
if defBonusCols > 0 then
table.insert(resultPart, '\r\n!colspan="'..defBonusCols..'"style="padding:0 0.5em 0 0.5em;"|Defence Bonus')
end
if Shared.contains(statColumns, 'damageReduction') then
table.insert(resultPart, '\r\n!colspan="1"style="padding:0 0.5em 0 0.5em;"|DR')
end
if lvlReqCols > 0 then
table.insert(resultPart, '\r\n!colspan="'..lvlReqCols..'"style="padding:0 0.5em 0 0.5em;"|Lvl Req')
end
if includeModifiers and includeDescription then
table.insert(resultPart, '\r\n!colspan="2"|')
elseif includeModifiers or includeDescription then
table.insert(resultPart, '\r\n!colspan="1"|')
end
--One header row down, one to go
table.insert(resultPart, '\r\n|-class="headerRow-1"')
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|Item')
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|Name')
--Weapons have Attack Speed here
if isWeaponType then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|Attack Speed')
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|Two Handed?')
end
--Attack bonuses
if Shared.contains(statColumns, 'slashAttackBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Attack', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'stabAttackBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Strength', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'blockAttackBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'rangedAttackBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'magicAttackBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}))
end
--Strength bonuses
if Shared.contains(statColumns, 'meleeStrengthBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Strength', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'rangedStrengthBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'magicDamageBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}))
end
--Defence bonuses
if Shared.contains(statColumns, 'meleeDefenceBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'rangedDefenceBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'magicDefenceBonus') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'damageReduction') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}))
end
--Level requirements
if Shared.contains(statColumns, 'attackLevelRequired') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Attack', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'defenceLevelRequired') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'rangedLevelRequired') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}))
end
if Shared.contains(statColumns, 'magicLevelRequired') then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}))
end
--If includeModifiers is set to 'true', add the Modifiers column
if includeModifiers then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|Modifiers')
end
--If includeDescription is set to 'true', add the Description column
if includeDescription then
table.insert(resultPart, '\r\n!style="padding:0 1em 0 0.5em;"|Description')
end


  --Now to remove the ignored columns (and also we need to track groups like defence bonuses to see how many remain)
if sortByName then
  local attBonusCols = 5
table.sort(itemList, function(a, b) return a.name < b.name end)
  local strBonusCols = 2
else
  local defBonusCols = 3
table.sort(itemList, function(a, b) return a.id < b.id end)
  local lvlReqCols = 4
end
  local ndx = 1
for i, item in pairs(itemList) do
  while Shared.tableCount(statColumns) >= ndx do
if isWeaponType then
    local colName = statColumns[ndx]
--Building rows for weapons
    if Shared.contains(ignoreColumns, colName) then
local atkSpeed = Items._getItemStat(item, 'attackSpeed', true)
      if Shared.contains(colName, 'AttackBonus') then attBonusCols = attBonusCols - 1 end
table.insert(resultPart, '\r\n|-')
      if Shared.contains(colName, 'trengthBonus') then strBonusCols = strBonusCols - 1 end
table.insert(resultPart, '\r\n|style ="text-align: left;padding: 0 0 0 0;"|'..Icons.Icon({item.name, type='item', size=50, notext=true}))
      if Shared.contains(colName, 'efenceBonus') then defBonusCols = defBonusCols - 1 end
table.insert(resultPart, '\r\n|style ="text-align: left;padding: 0 0.5em 0 0.5em;"|'..Icons.Icon({item.name, type='item', noicon=true}))
      if Shared.contains(colName, 'LevelRequired') then lvlReqCols = lvlReqCols - 1 end
table.insert(resultPart, '\r\n| data-sort-value="' .. atkSpeed .. '" style ="text-align: right;padding: 0 0.5em 0 0;" |'..Shared.round(atkSpeed / 1000, 3, 1) .. 's')
      table.remove(statColumns, ndx)
--That's the first list out of the way, now for 2-Handed
    else
table.insert(resultPart, '\r\n| style ="text-align: right;"|')
      ndx = ndx + 1
table.insert(resultPart, Items._getItemStat(item, 'isTwoHanded') and 'Yes' or 'No')
    end
for j, statName in pairs(statColumns) do
  end
local statValue = Items._getItemStat(item, statName, true)
 
table.insert(resultPart, '\r\n| style ="text-align: right;padding: 0 0.5em 0 0;')
  --Alright, let's start the table by building the shared header
if string.find(statName, '^(.+)LevelRequired$') == nil then
  local result = '{| class="wikitable sortable stickyHeader"\r\n|-class="headerRow-0"'
if statValue > 0 then
  if isWeaponType then
table.insert(resultPart, 'background-color:lightgreen;')
    --Weapons have extra columns here for Attack Speed and "Two Handed?"
elseif statValue < 0 then
    result = result..'\r\n!colspan="4"|'
table.insert(resultPart, 'background-color:lightpink;')
  else
end
    result = result..'\r\n!colspan="2"|'
end
  end
table.insert(resultPart, '"|'..Shared.formatnum(statValue))
  if attBonusCols > 0 then
if statName == 'magicDamageBonus' or statName == 'damageReduction' then table.insert(resultPart, '%') end
    result = result..'\r\n!colspan="'..attBonusCols..'"style="padding:0 0.5em 0 0.5em;"|Attack Bonus'
end
  end
--If requested, add the item Modifiers
  if strBonusCols > 0 then
if includeModifiers then
    result = result..'\r\n!colspan="'..strBonusCols..'"style="padding:0 0.5em 0 0.5em;"|Str. Bonus'
table.insert(resultPart, '\r\n|style="text-align:left;padding:0 0.5em 0 0.5em;"|')
  end
local txtLines = {}
  if Shared.contains(statColumns, 'magicDamageBonus') then
local modTxt = Constants.getModifiersText(item.modifiers, true)
    result = result..'\r\n!colspan="1"style="padding:0 0.5em 0 0.5em;"|% Damage Bonus'
if modTxt ~= '' then
  end
table.insert(txtLines, modTxt)
  if defBonusCols > 0 then
end
    result = result..'\r\n!colspan="'..defBonusCols..'"style="padding:0 0.5em 0 0.5em;"|Defence Bonus'
--For items with a special attack, show the details
  end
if item.hasSpecialAttack then
  if Shared.contains(statColumns, 'damageReduction') then
table.insert(txtLines, "'''Special Attack:'''")
    result = result..'\r\n!colspan="1"style="padding:0 0.5em 0 0.5em;"|DR'
for i, spAtt in ipairs(item.specialAttacks) do
  end
table.insert(txtLines, spAtt.defaultChance .. '% chance for ' .. spAtt.name .. ':')
  if lvlReqCols > 0 then
table.insert(txtLines, spAtt.description)
    result = result..'\r\n!colspan="'..lvlReqCols..'"style="padding:0 0.5em 0 0.5em;"|Lvl Req'
end
  end
end
  result = result..'\r\n!colspan="1"|'
table.insert(resultPart, table.concat(txtLines, '<br/>'))
  --One header row down, one to go
end
  result = result..'\r\n|-class="headerRow-1"'
--If requested, add description
  result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Item'
if includeDescription then
  result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Name'
table.insert(resultPart, '\r\n|style="text-align:left;padding:0 0.5em 0 0.5em;"|')
  --Weapons have Attack Speed here
table.insert(resultPart, item.description ~= nil and item.description or '')
  if isWeaponType then
end
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Attack Speed'
else
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Two Handed?'
--Building rows for armour
  end
table.insert(resultPart, '\r\n|-')
  --Attack bonuses
table.insert(resultPart, '\r\n|style ="text-align: left;padding: 0 0 0 0;"|'..Icons.Icon({item.name, type='item', size=50, notext=true}))
  if Shared.contains(statColumns, 'slashAttackBonus') then
table.insert(resultPart, '\r\n|style ="text-align: left;padding: 0 0.5em 0 0.5em;"|'..Icons.Icon({item.name, type='item', noicon=true}))
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Attack', type='skill', notext='true'})
for j, statName in pairs(statColumns) do
  end
local statValue = Items._getItemStat(item, statName, true)
  if Shared.contains(statColumns, 'stabAttackBonus') then
table.insert(resultPart, '\r\n| style ="text-align: right;padding: 0 0.5em 0 0;')
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Strength', type='skill', notext='true'})
if statValue > 0 then
  end
table.insert(resultPart, 'background-color:lightgreen;')
  if Shared.contains(statColumns, 'blockAttackBonus') then
elseif statValue < 0 then
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'})
table.insert(resultPart, 'background-color:lightpink;')
  end
end
  if Shared.contains(statColumns, 'rangedAttackBonus') then
table.insert(resultPart, '"|'..Shared.formatnum(statValue))
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'})
if statName == 'magicDamageBonus' or statName == 'damageReduction' then table.insert(resultPart, '%') end
  end
end
  if Shared.contains(statColumns, 'magicAttackBonus') then
--If requested, add the item Modifiers
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'})
if includeModifiers then
  end
table.insert(resultPart, '\r\n|style="text-align:left;padding:0 0.5em 0 0.5em;"|')
  --Strength bonuses
local txtLines = {}
  if Shared.contains(statColumns, 'strengthBonus') then
local modTxt = Constants.getModifiersText(item.modifiers, true)
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Strength', type='skill', notext='true'})
if modTxt ~= '' then
  end
table.insert(txtLines, modTxt)
  if Shared.contains(statColumns, 'rangedStrengthBonus') then
end
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'})
--For items with a special attack, show the details
  end
if item.hasSpecialAttack then
  if Shared.contains(statColumns, 'magicDamageBonus') then
table.insert(txtLines, "'''Special Attack:'''")
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'})
for i, spAtt in ipairs(item.specialAttacks) do
  end
table.insert(txtLines, spAtt.defaultChance .. '% chance for ' .. spAtt.name .. ':')
  --Defence bonuses
table.insert(txtLines, spAtt.description)
  if Shared.contains(statColumns, 'defenceBonus') then
end
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'})
end
  end
table.insert(resultPart, table.concat(txtLines, '<br/>'))
  if Shared.contains(statColumns, 'rangedDefenceBonus') then
end
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'})
--If requested, add description
  end
if includeDescription then
  if Shared.contains(statColumns, 'magicDefenceBonus') then
table.insert(resultPart, '\r\n|style="text-align:left;padding:0 0.5em 0 0.5em;"|')
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'})
table.insert(resultPart, item.description ~= nil and item.description or '')
  end
end
  if Shared.contains(statColumns, 'damageReduction') then
end
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'})
end
  end
  --Level requirements
  if Shared.contains(statColumns, 'attackLevelRequired') then
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Attack', type='skill', notext='true'})
  end
  if Shared.contains(statColumns, 'defenceLevelRequired') then
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'})
  end
  if Shared.contains(statColumns, 'rangedLevelRequired') then
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'})
  end
  if Shared.contains(statColumns, 'magicLevelRequired') then
    result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'})
  end
  --And finally Sources
  result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Sources'


  table.sort(itemList, function(a, b) return a.id < b.id end)
table.insert(resultPart, '\r\n|}')
  for i, item in pairs(itemList) do
    if isWeaponType then
      --Building rows for weapons
      result = result..'\r\n|-'
      result = result..'\r\n|style ="text-align: left;padding: 0 0 0 0;"|'..Icons.Icon({item.name, type='item', size=50, notext=true})
      result = result..'\r\n|style ="text-align: left;padding: 0 0.5em 0 0.5em;"|[['..item.name..']]'
      result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;" |'..Shared.formatnum(item.attackSpeed)
      --That's the first list out of the way, now for 2-Handed
      result = result..'\r\n| style ="text-align: right;"|'
      if item.isTwoHanded then result = result..'Yes' else result = result..'No' end
      for j, statName in pairs(statColumns) do
        local statValue = Items._getItemStat(item, statName, true)
        result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;'
        if not Shared.contains(statName, 'LevelRequired') then
          if statValue > 0 then
            result = result..'background-color:lightgreen;'
          elseif statValue < 0 then
            result = result..'background-color:lightpink;'
          end
        end
        result = result..'"|'..Shared.formatnum(statValue)
        if statName == 'magicDamageBonus' or statName == 'damageReduction' then result = result..'%' end
      end
      --Finally, the Sources
      result = result..'\r\n| style ="text-align: right;white-space: nowrap;padding: 0 0.5em 0 0.5em;" |'
      result = result..ItemSourceTables._getItemSources(item)
    else
      --Building rows for armour
      result = result..'\r\n|-'
      result = result..'\r\n|style ="text-align: left;padding: 0 0 0 0;"|'..Icons.Icon({item.name, type='item', size=50, notext=true})
      result = result..'\r\n|style ="text-align: left;padding: 0 0.5em 0 0.5em;"|[['..item.name..']]'
      for j, statName in pairs(statColumns) do
        local statValue = Items._getItemStat(item, statName, true)
        result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;'
        if statValue > 0 then
          result = result..'background-color:lightgreen;'
        elseif statValue < 0 then
          result = result..'background-color:lightpink;'
        end
        result = result..'"|'..Shared.formatnum(statValue)
        if statName == 'magicDamageBonus' or statName == 'damageReduction' then result = result..'%' end
      end
      --Finally, the Sources
      result = result..'\r\n| style ="text-align: right;white-space: nowrap;padding: 0 0.5em 0 0.5em;" |'
      result = result..ItemSourceTables._getItemSources(item)
    end
  end


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


function p.getEquipmentTable(frame)
function p._getCategoryTable(style, slot, other, includeModifiers, includeDescription, sortByName)
  local args = frame.args ~= nil and frame.args or frame
if type(slot) == 'number' then
  local type = args.type
slot = Constants.getEquipmentSlotName(slot)
  local tier = args.tier
end
  local slotStr = args.slot
 
  local ammoTypeStr = args.ammoType
local itemList = Items.getItems(function(item)
  local category = args.category ~= nil and args.category or 'Combat'
-- Exclude Golbin raid exclusives for now, such that they don't
-- pollute various equipment tables
if item.golbinRaidExclusive ~= nil and item.golbinRaidExclusive then
return false
end
local isMatch = true
if style == 'Melee' then
if (Items._getItemStat(item, 'defenceLevelRequired') == nil and Items._getItemStat(item, 'attackLevelRequired') == nil) and not Shared.contains(styleOverrides.Melee, item.name) then isMatch = false end
elseif style == 'Ranged' then
if Items._getItemStat(item, 'rangedLevelRequired') == nil and not Shared.contains(styleOverrides.Ranged, item.name) then isMatch = false end
elseif style == 'Magic' then
if Items._getItemStat(item, 'magicLevelRequired') == nil and not Shared.contains(styleOverrides.Magic, item.name) then isMatch = false end
elseif style == 'None' then
if (Items._getItemStat(item, 'defenceLevelRequired') ~= nil or Items._getItemStat(item, 'rangedLevelRequired') ~= nil or Items._getItemStat(item, 'magicLevelRequired') ~= nil or
Shared.contains(styleOverrides.Melee, item.name) or Shared.contains(styleOverrides.Ranged, item.name) or Shared.contains(styleOverrides.Magic, item.name)) and
not Shared.contains(styleOverrides.None, item.name) then
isMatch = false
end
end
if slot == nil or not Shared.contains(item.validSlots, slot) then isMatch = false end
 
if isMatch and other ~= nil then
if slot == 'Cape' then
local isSkillcape = Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion'
if other == 'Skillcapes' then
isMatch = isSkillcape
elseif other == 'No Skillcapes' then
isMatch = not isSkillcape
end
end
if slot == 'Weapon' then --For quiver slot or weapon slot, 'other' is the ammo type
if other == 'Arrows' then
if item.ammoTypeRequired ~= 0 then isMatch = false end
elseif other == 'Bolts' then
if item.ammoTypeRequired ~= 1 then isMatch = false end
end
elseif slot == 'Quiver' then
if other == 'Arrows' then
if item.ammoType ~= 0 then isMatch = false end
elseif other == 'Bolts' then
if item.ammoType ~= 1 then isMatch = false end
elseif other == 'Javelins' then
if item.ammoType ~= 2 then isMatch = false end
elseif other == 'Throwing Knives' then
if item.ammoType ~= 3 then isMatch = false end
elseif other == 'Thrown' then
if item.ammoType ~= 2 and item.ammoType ~= 3 then isMatch = false end
end
end
end


  --Find out what Ammo Type we're working with
return isMatch
  local ammoType = nil
end)
  if ammoTypeStr ~= nil then
    if ammoTypeStr == "Arrows" then
return p._getEquipmentTable(itemList, includeModifiers, includeDescription, sortByName)
      ammoType = 0
end
    elseif ammoTypeStr == 'Bolts' then
      ammoType = 1
    elseif ammoTypeStr == 'Javelins' then
      ammoType = 2
    elseif ammoTypeStr == 'Throwing Knives' then
      ammoType = 3
    end
  end


  --Find out what slot we're working with
function p.getCategoryTable(frame)
  local slot = nil
local style = frame.args ~= nil and frame.args[1] or frame[1]
  if slotStr ~= nil then
local slot = frame.args ~= nil and frame.args[2] or frame[2]
    slot = Constants.equipmentSlot[slotStr]
local other = frame.args ~= nil and frame.args[3] or frame[3]
  end
local includeModifiers = frame.args ~= nil and frame.args.includeModifiers or frame.includeModifiers
 
local includeDescription = frame.args ~= nil and frame.args.includeDescription or frame.includeDescription
  local isWeaponType = Shared.contains(weaponTypes, type)
local sortByName = frame.args ~= nil and frame.args.sortByName or frame.sortByName


  --Now we need to figure out which items are in this list
includeModifiers = includeModifiers ~= nil and string.upper(includeModifiers) == 'TRUE' or false
  local itemList = {}
includeDescription = includeDescription ~= nil and string.upper(includeDescription) == 'TRUE' or false
  for i, itemBase in pairs(ItemData.Items) do
sortByName = sortByName ~= nil and string.upper(sortByName) == 'TRUE' or false
    local item = Shared.clone(itemBase)
    item.id = i - 1
    local listItem = false
    if isWeaponType then
    listItem = item.type == type and item.category == category
      if ammoType ~= nil then listItem = listItem and item.ammoTypeRequired == ammoType end
    else
      --Now for handling armour
      if type == "Armour" or type == "Melee" then
        listItem = item.defenceLevelRequired ~= nil or (item.category == 'Combat' and item.type == 'Armour')
      elseif type == "Ranged Armour" or type == "Ranged" then
        listItem = item.rangedLevelRequired ~= nil or (item.category == 'Combat' and item.type == 'Ranged Armour')
      elseif type == "Magic Armour" or type == "Magic" then
        listItem = item.magicLevelRequired ~= nil or (item.category == 'Combat' and item.type == 'Magic Armour')
      else
        listItem = item.type == type and item.category ~= 'Combat'
      end
      if ammoType ~= nil then listItem = listItem and item.ammoType == ammoType end
      if slot ~= nil then listItem = listItem and item.equipmentSlot == slot end
    end
    if listItem then
      table.insert(itemList, item)
    end
  end


  return p._getEquipmentTable(itemList)
return p._getCategoryTable(style, slot, other, includeModifiers, includeDescription, sortByName)
end
end


function p.getTableForList(frame)
function p.getTableForList(frame)
  local stuffString = frame.args ~= nil and frame.args[1] or frame
local stuffString = frame.args ~= nil and frame.args[1] or frame[1]
  local itemNames = Shared.splitString(stuffString, ',')
local itemNames = Shared.splitString(stuffString, ',')
 
local includeModifiers = frame.args ~= nil and frame.args[2] or frame[2]
includeModifiers = includeModifiers ~= nil and string.upper(includeModifiers) == 'TRUE' or false
 
local itemList = {}
local errMsg = 'ERROR: Some items not found in database: [[Category:Pages with script errors]]'
local hasErr = false
for i, name in Shared.skpairs(itemNames) do
local nextItem = Items.getItem(Shared.trim(name))
if nextItem == nil then
errMsg = errMsg.." '"..name.."'"
hasErr = true
else
table.insert(itemList, nextItem)
end
end
 
if hasErr then
return errMsg
else
return p._getEquipmentTable(itemList, includeModifiers)
end
end
 
function p.getDoubleLootTable(frame)
local modsDL = {
'increasedChanceToDoubleLootCombat',
'decreasedChanceToDoubleLootCombat',
'increasedChanceToDoubleLootThieving',
'decreasedChanceToDoubleLootThieving',
'increasedChanceToDoubleItemsGlobal',
'decreasedChanceToDoubleItemsGlobal'
}
local modDetail = {}
for i, modName in pairs(modsDL) do
local mName, mText, mSign, mIsNeg, mValUnsigned = Constants.getModifierDetails(modName)
modDetail[modName] = { mult = (mSign == "+" and 1 or -1) }
end
 
local itemList = Items.getItems(function(item)
if item.modifiers ~= nil then
for modName, val in pairs(item.modifiers) do
if Shared.contains(modsDL, modName) then return true end
end
return false
end
end)
table.sort(itemList, function(a, b) return a.id < b.id end)
 
local resultPart = {}
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"\r\n|-class="headerRow-0"')
table.insert(resultPart, '\r\n!colspan="2"|Name!!Bonus!!Description')
for i, item in Shared.skpairs(itemList) do
local lootValue = 0
for modName, modDet in pairs(modDetail) do
lootValue = lootValue + (item.modifiers[modName] or 0) * modDet.mult
end
table.insert(resultPart, '\r\n|-')
table.insert(resultPart, '\r\n|data-sort-value="'..item.name..'"|'..Icons.Icon({item.name, type='item', size=50, notext=true}))
table.insert(resultPart, '||'..Icons.Icon({item.name, type='item', noicon=true}))
table.insert(resultPart, '||style ="text-align: right;" data-sort-value="'..lootValue..'"|'..lootValue..'%')
table.insert(resultPart, '||'..item.description)
end
 
table.insert(resultPart, '\r\n|}')
return table.concat(resultPart)
end
 
function p.getStatChangeString(item1, item2)
--Used by getItemUpgradeTable to get the stat change between two items
local changeArray = {}
 
local getSpecificStatString = function(val1, val2, subStr)
if val1 == nil then val1 = 0 end
if val2 == nil then val2 = 0 end
 
if val1 ~= val2 then
local txt = string.gsub(subStr, '{V}', Shared.numStrWithSign(val1 - val2))
table.insert(changeArray, txt)
end
end
 
--Unfortunately just gonna have to manually check all the changes I think...
local statList = {
-- {'statName', 'statDescription'}
{'stabAttackBonus', '{V} '..Icons.Icon({'Melee', notext=true})..' Stab Bonus'},
{'slashAttackBonus', '{V} '..Icons.Icon({'Melee', notext=true})..' Slash Bonus'},
{'blockAttackBonus', '{V} '..Icons.Icon({'Melee', notext=true})..' Block Bonus'},
{'meleeStrengthBonus', '{V} '..Icons.Icon({'Strength', type='skill', notext=true})..' Strength Bonus'},
{'rangedStrengthBonus', '{V} '..Icons.Icon({'Ranged', type='skill', notext=true})..' Strength Bonus'},
{'magicStrengthBonus', '{V}% '..Icons.Icon({'Magic', type='skill', notext=true})..' Damage Bonus'},
{'meleeDefenceBonus', '{V} '..Icons.Icon({'Defence', type='skill', notext=true})..' Defence Bonus'},
{'rangedDefenceBonus', '{V} '..Icons.Icon({'Ranged', type='skill', notext=true})..' Defence Bonus'},
{'magicDefenceBonus', '{V} '..Icons.Icon({'Magic', type='skill', notext=true})..' Defence Bonus'},
{'damageReduction', '{V}% Damage Reduction'},
{'increasedSlayerXP', '{V}% '..Icons.Icon({'Slayer', type='skill', notext=true})..' Bonus XP'},
{'attackLevelRequired', '{V} '..Icons.Icon({'Attack', type='skill', notext=true})..' Level Required'},
{'defenceLevelRequired', '{V} '..Icons.Icon({'Defence', type='skill', notext=true})..' Level Required'},
{'rangedLevelRequired', '{V} '..Icons.Icon({'Ranged', type='skill', notext=true})..' Level Required'},
{'magicLevelRequired', '{V} '..Icons.Icon({'Magic', type='skill', notext=true})..' Level Required'},
}
for i, stat in ipairs(statList) do
if stat[1] == 'increasedSlayerXP' then
getSpecificStatString(Items._getItemModifier(item1, stat[1], 'Slayer'), Items._getItemModifier(item2, stat[1], 'Slayer'), stat[2])
else
getSpecificStatString(Items._getItemStat(item1, stat[1]), Items._getItemStat(item2, stat[1]), stat[2])
end
end
 
return table.concat(changeArray, '<br/>')
end
 
function p.getItemUpgradeTable(frame)
local category = frame.args ~= nil and frame.args[1] or frame
local itemArray = {}
local isEquipment = false
 
if string.upper(category) == 'POTION' then
itemArray = Items.getItems(function(item) return Shared.contains(item.name, 'Potion') and item.itemsRequired ~= nil end)
elseif string.upper(category) == 'OTHER' then
itemArray = Items.getItems(function(item)
return not Shared.contains(item.name, 'Potion') and item.itemsRequired ~= nil and item.validSlots == nil
end)
else
if Constants.getEquipmentSlotID(category) == nil then
return 'ERROR: Invalid option. Choose either an equipment slot, Potion, or Other[[Category:Pages with script errors]]'
end
isEquipment = true
itemArray = Items.getItems(function(item)
return item.itemsRequired ~= nil and Shared.contains(item.validSlots, category)
end)
end
table.sort(itemArray, function(a, b) return a.id < b.id end)
 
local resultPart = {}
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
table.insert(resultPart, '\r\n|- class="headerRow-0"')
table.insert(resultPart, '\r\n!colspan="2"|Upgraded Item!!Ingredients')
if isEquipment then table.insert(resultPart, '!!Stat Change') end
 
for i, item in Shared.skpairs(itemArray) do
table.insert(resultPart, '\r\n|-')
table.insert(resultPart, '\r\n|'..Icons.Icon({item.name, type='item', size='50', notext=true}))
table.insert(resultPart, '||'..Icons.Icon({item.name, type='item', noicon=true}))
 
local matArray = {}
local statChangeString = ''
for i, row in Shared.skpairs(item.itemsRequired) do
local mat = Items.getItemByID(row[1])
table.insert(matArray, Icons.Icon({mat.name, type='item', qty=row[2]}))
 
if item.validSlots ~= nil and mat.validSlots ~= nil and statChangeString == '' then
statChangeString = p.getStatChangeString(item, mat)
end
end
if item.trimmedGPCost ~= nil and item.trimmedGPCost > 0 then
table.insert(matArray, Icons.GP(item.trimmedGPCost))
end
table.insert(resultPart, '||'..table.concat(matArray, '<br/>'))


  local itemList = {}
if isEquipment then
  local errMsg = 'ERROR: Some items not found in database: '
table.insert(resultPart, '||'..statChangeString)
  local hasErr = false
end
  for i, name in Shared.skpairs(itemNames) do
end
    local nextItem = Items.getItem(name)
    if nextItem == nil then
      errMsg = errMsg.." '"..name.."'"
      hasErr = true
    else
      table.insert(itemList, nextItem)
    end
  end


  if hasErr then
table.insert(resultPart, '\r\n|}')
    return errMsg
return table.concat(resultPart)
  else
    return p._getEquipmentTable(itemList)
  end
end
end


return p
return p