Anonymous

Module:Monsters: Difference between revisions

From Melvor Idle
m
getChestDrops: Added punctuation
m (getSlayerTierMonsterTable: Adjust input validation)
m (getChestDrops: Added punctuation)
(15 intermediate revisions by 2 users not shown)
Line 1: Line 1:
local p = {}
local p = {}


local Constants = mw.loadData('Module:Constants/data')
local MonsterData = mw.loadData('Module:Monsters/data')
local MonsterData = mw.loadData('Module:Monsters/data')


local Constants = require('Module:Constants')
local Areas = require('Module:CombatAreas')
local Areas = require('Module:CombatAreas')
local Magic = require('Module:Magic')
local Magic = require('Module:Magic')
Line 76: Line 76:
   local monster = p.getMonster(MonsterName)
   local monster = p.getMonster(MonsterName)
   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 103: Line 103:


   local iconText = ''
   local iconText = ''
   if  monster.attackType == Constants.attackType.Melee then
   if  Constants.getCombatStyleName(monster.attackType) == 'Melee' then
     iconText = Icons.Icon({'Melee', notext=notext, nolink=nolink})
     iconText = Icons.Icon({'Melee', notext=notext, nolink=nolink})
   elseif monster.attackType == Constants.attackType.Ranged then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Ranged' then
     iconText = Icons.Icon({'Ranged', type='skill', notext=notext, nolink=nolink})
     iconText = Icons.Icon({'Ranged', type='skill', notext=notext, nolink=nolink})
   else
   elseif Constants.getCombatStyleName(monster.attackType) == 'Magic' then
     iconText = Icons.Icon({'Magic', type='skill', notext=notext, nolink=nolink})
     iconText = Icons.Icon({'Magic', type='skill', notext=notext, nolink=nolink})
   end
   end
Line 120: Line 120:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 137: Line 137:
     return p._getMonsterHP(monster)
     return p._getMonsterHP(monster)
   else
   else
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end
end
end
Line 151: Line 151:
     return p._getMonsterAttackSpeed(monster)
     return p._getMonsterAttackSpeed(monster)
   else
   else
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end
end
end
Line 174: Line 174:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 183: Line 183:
   local effAttLvl = 0
   local effAttLvl = 0
   local attBonus = 0
   local attBonus = 0
   if monster.attackType == Constants.attackType.Melee then
   if Constants.getCombatStyleName(monster.attackType) == 'Melee' then
     effAttLvl = monster.attackLevel + 9
     effAttLvl = monster.attackLevel + 9
     attBonus = monster.attackBonus + 64
     attBonus = monster.attackBonus + 64
   elseif monster.attackType == Constants.attackType.Ranged then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Ranged' then
     effAttLvl = monster.rangedLevel + 9
     effAttLvl = monster.rangedLevel + 9
     attBonus = monster.attackBonusRanged + 64
     attBonus = monster.attackBonusRanged + 64
   elseif monster.attackType == Constants.attackType.Magic then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Magic' then
     effAttLvl = monster.magicLevel + 9
     effAttLvl = monster.magicLevel + 9
     attBonus = monster.attackBonusMagic + 64
     attBonus = monster.attackBonusMagic + 64
   else
   else
     return "ERROR: This monster has an invalid attack type somehow"
     return "ERROR: This monster has an invalid attack type somehow[[Category:Pages with script errors]]"
   end
   end


Line 204: Line 204:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 227: Line 227:
     defBonus = monster.defenceBonusMagic + 64
     defBonus = monster.defenceBonusMagic + 64
   else
   else
     return "ERROR: Must choose Melee, Ranged, or Magic"
     return "ERROR: Must choose Melee, Ranged, or Magic[[Category:Pages with script errors]]"
   end
   end
   return effDefLvl * defBonus
   return effDefLvl * defBonus
Line 239: Line 239:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 265: Line 265:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with name "..monsterName.." found"
     return "ERROR: No monster with name "..monsterName.." found[[Category:Pages with script errors]]"
   end
   end


Line 271: Line 271:
end
end


function p._getMonsterAreas(monster)
function p._getMonsterAreas(monster, excludeDungeons)
   local result = ''
   local result = ''
  local hideDungeons = excludeDungeons ~= nil and excludeDungeons or false
   local areaList = Areas.getMonsterAreas(monster.id)
   local areaList = Areas.getMonsterAreas(monster.id)
   for i, area in pairs(areaList) do
   for i, area in pairs(areaList) do
     if i > 1 then result = result..'<br/>' end
     if area.type ~= 'dungeon' or not hideDungeons then
    result = result..Icons.Icon({area.name, type = area.type})
      if i > 1 then result = result..'<br/>' end
      result = result..Icons.Icon({area.name, type = area.type})
    end
   end
   end
   return result
   return result
Line 283: Line 286:
function p.getMonsterAreas(frame)
function p.getMonsterAreas(frame)
   local MonsterName = frame.args ~= nil and frame.args[1] or frame
   local MonsterName = frame.args ~= nil and frame.args[1] or frame
  local hideDungeons = frame.args ~= nil and frame.args[2] or nil
   local monster = p.getMonster(MonsterName)
   local monster = p.getMonster(MonsterName)


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with name "..monsterName.." found"
     return "ERROR: No monster with name "..monsterName.." found[[Category:Pages with script errors]]"
   end
   end


   return p._getMonsterAreas(monster)
   return p._getMonsterAreas(monster, hideDungeons)
end
end


Line 296: Line 300:
   local specialMaxHit = 0
   local specialMaxHit = 0
   local normalMaxHit = p._getMonsterBaseMaxHit(monster)
   local normalMaxHit = p._getMonsterBaseMaxHit(monster)
  local hasActiveBuffSpec = false
   if monster.hasSpecialAttack then
   if monster.hasSpecialAttack then
     for i, specID in pairs(monster.specialAttackID) do
     for i, specID in pairs(monster.specialAttackID) do
Line 317: Line 322:
       end
       end
       if thisMax > specialMaxHit then specialMaxHit = thisMax end
       if thisMax > specialMaxHit then specialMaxHit = thisMax end
      if specAttack.activeBuffs then hasActiveBuffSpec = true end
     end
     end
   end
   end
   --Ensure that if the monster never does a normal attack, the normal max hit is irrelevant
   --Ensure that if the monster never does a normal attack, the normal max hit is irrelevant
   if normalChance == 0 then normalMaxHit = 0 end
   if normalChance == 0 and not hasActiveBuffSpec then normalMaxHit = 0 end
   return math.max(specialMaxHit, normalMaxHit)
   return math.max(specialMaxHit, normalMaxHit)
end
end
Line 329: Line 335:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 338: Line 344:
   local effStrLvl = 0
   local effStrLvl = 0
   local strBonus = 0
   local strBonus = 0
   if monster.attackType == Constants.attackType.Melee then
   if Constants.getCombatStyleName(monster.attackType) == 'Melee' then
     effStrLvl = monster.strengthLevel + 9
     effStrLvl = monster.strengthLevel + 9
     strBonus = monster.strengthBonus
     strBonus = monster.strengthBonus
   elseif monster.attackType == Constants.attackType.Ranged then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Ranged' then
     effStrLvl = monster.rangedLevel + 9
     effStrLvl = monster.rangedLevel + 9
     strBonus = monster.strengthBonusRanged
     strBonus = monster.strengthBonusRanged
   elseif monster.attackType == Constants.attackType.Magic then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Magic' then
     local mSpell = nil
     local mSpell = nil
     if monster.selectedSpell ~= nil then mSpell = Magic.getSpellByID('Spells', monster.selectedSpell) end
     if monster.selectedSpell ~= nil then mSpell = Magic.getSpellByID('Spells', monster.selectedSpell) end
Line 353: Line 359:
     end
     end
   else
   else
     return "ERROR: This monster has an invalid attack type somehow"
    error('blah')
     return "ERROR: This monster has an invalid attack type somehow[[Category:Pages with script errors]]"
   end
   end


Line 365: Line 372:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 376: Line 383:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 383: Line 390:
   local iconText = ''
   local iconText = ''
   local typeText = ''
   local typeText = ''
   if  monster.attackType == Constants.attackType.Melee then
   if  Constants.getCombatStyleName(monster.attackType) == 'Melee' then
     iconText = Icons.Icon({'Melee', notext=true})
     iconText = Icons.Icon({'Melee', notext=true})
     typeText = 'Melee'
     typeText = 'Melee'
   elseif monster.attackType == Constants.attackType.Ranged then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Ranged' then
     iconText = Icons.Icon({'Ranged', type='skill', notext=true})
     iconText = Icons.Icon({'Ranged', type='skill', notext=true})
     typeText = 'Ranged'
     typeText = 'Ranged'
   else
   elseif Constants.getCombatStyleName(monster.attackType) == 'Magic' then
     iconText = Icons.Icon({'Magic', type='skill', notext=true})
     iconText = Icons.Icon({'Magic', type='skill', notext=true})
     typeText = 'Magic'
     typeText = 'Magic'
Line 422: Line 429:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 447: Line 454:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


   local result = '[[Category:Monsters]]'
   local result = '[[Category:Monsters]]'


   if monster.attackType == Constants.attackType.Melee then
   if Constants.getCombatStyleName(monster.attackType) == 'Melee' then
     result = result..'[[Category:Melee Monsters]]'
     result = result..'[[Category:Melee Monsters]]'
   elseif monster.attackType == Constants.attackType.Ranged then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Ranged' then
     result = result..'[[Category:Ranged Monsters]]'
     result = result..'[[Category:Ranged Monsters]]'
   elseif monster.attackType == Constants.attackType.Magic then
   elseif Constants.getCombatStyleName(monster.attackType) == 'Magic' then
     result = result..'[[Category:Magic Monsters]]'
     result = result..'[[Category:Magic Monsters]]'
   end
   end
Line 467: Line 474:
     result = result..'[[Category:Bosses]]'
     result = result..'[[Category:Bosses]]'
   end
   end
  return result
end
function p.getOtherMonsterBoxText(frame)
  local MonsterName = frame.args ~= nil and frame.args[1] or frame
  local monster = p.getMonster(MonsterName)
  if monster == nil then
    return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
  end
  local result = ''
  --Going through and finding out which damage bonuses will apply to this monster
  local monsterTypes = {}
  if monster.isBoss then table.insert(monsterTypes, 'Boss') end
  local areaList = Areas.getMonsterAreas(monster.id)
  local counts = {combat = 0, slayer = 0, dungeon = 0}
  for i, area in Shared.skpairs(areaList) do
    counts[area.type] = counts[area.type] + 1
  end
  if counts.combat > 0 then table.insert(monsterTypes, 'Combat Area') end
  if counts.slayer > 0 then table.insert(monsterTypes, 'Slayer Area') end
  if counts.dungeon > 0 then table.insert(monsterTypes, 'Dungeon') end
  result = result.."\r\n|-\r\n|'''Monster Types:''' "..table.concat(monsterTypes, ", ")
  local SlayerTier = 'N/A'
  if not p._isDungeonOnlyMonster(monster) then
    SlayerTier = Constants.getSlayerTierNameByLevel(p._getMonsterCombatLevel(monster))
  end
  result = result.."\r\n|-\r\n|'''"..Icons.Icon({'Slayer', type='skill'}).." [[Slayer#Slayer Tier Monsters|Tier]]:''' "..SlayerTier


   return result
   return result
Line 476: Line 519:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 504: Line 547:
       avgGp = (monster.dropCoins[1] + monster.dropCoins[2] - 1) / 2
       avgGp = (monster.dropCoins[1] + monster.dropCoins[2] - 1) / 2
       local gpTxt = Icons.GP(monster.dropCoins[1], monster.dropCoins[2] - 1)
       local gpTxt = Icons.GP(monster.dropCoins[1], monster.dropCoins[2] - 1)
       result = result.."\r\nIn addition to loot, the monster will also drop "..gpTxt
       result = result.."\r\nIn addition to loot, the monster will also drop "..gpTxt..'.'
     end
     end


Line 562: Line 605:
     end
     end
     result = result..'\r\n|}'
     result = result..'\r\n|}'
     result = result..'\r\nThe loot dropped by the average kill is worth '..Icons.GP(Shared.round(lootValue, 2, 0)).." if sold"
     result = result..'\r\nThe loot dropped by the average kill is worth '..Icons.GP(Shared.round(lootValue, 2, 0)).." if sold."
     result = result..'<br/>Including GP, the average kill is worth '..Icons.GP(Shared.round(avgGp + lootValue, 2, 0))
     if avgGp > 0 then
      result = result..'<br/>Including GP, the average kill is worth '..Icons.GP(Shared.round(avgGp + lootValue, 2, 0))..'.'
    end
   end
   end


Line 576: Line 621:


   if chest == nil then
   if chest == nil then
     return "ERROR: No item named "..ChestName..' found'
     return "ERROR: No item named "..ChestName..' found[[Category:Pages with script errors]]'
   end
   end


Line 582: Line 627:


   if chest.dropTable == nil then
   if chest.dropTable == nil then
     return "ERROR: "..ChestName.." does not have a drop table"
     return "ERROR: "..ChestName.." does not have a drop table[[Category:Pages with script errors]]"
   else
   else
     local lootChance = 100
     local lootChance = 100
Line 631: Line 676:
     end
     end
     result = result..'\r\n|}'
     result = result..'\r\n|}'
     result = result..'\r\nThe average value of the contents of one chest is '..Icons.GP(Shared.round(lootValue, 2, 0))
     result = result..'\r\nThe average value of the contents of one chest is '..Icons.GP(Shared.round(lootValue, 2, 0))..'.'
   end
   end


Line 641: Line 686:
   local area = Areas.getArea(areaName)
   local area = Areas.getArea(areaName)
   if area == nil then
   if area == nil then
     return "ERROR: Could not find an area named "..areaName
     return "ERROR: Could not find an area named "..areaName..'[[Category:Pages with script errors]]'
   end
   end


Line 653: Line 698:
     local monster = p.getMonsterByID(monsterID)
     local monster = p.getMonsterByID(monsterID)
     tableTxt = tableTxt..'\r\n|-\r\n|'..Icons.Icon({monster.name, type='monster'})
     tableTxt = tableTxt..'\r\n|-\r\n|'..Icons.Icon({monster.name, type='monster'})
     tableTxt = tableTxt..'||'..p.getMonsterCombatLevel(monster.name)
     tableTxt = tableTxt..'||'..p._getMonsterCombatLevel(monster)
     tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterHP(monster.name))
     tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterHP(monster.name))
     tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterMaxHit(monster.name))
     tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterMaxHit(monster.name))
Line 666: Line 711:
   local area = Areas.getArea(areaName)
   local area = Areas.getArea(areaName)
   if area == nil then
   if area == nil then
     return "ERROR: Could not find a dungeon named "..areaName
     return "ERROR: Could not find a dungeon named "..areaName..'[[Category:Pages with script errors]]'
   end
   end


Line 690: Line 735:
       if monsterID ~= 1 then
       if monsterID ~= 1 then
         tableTxt = tableTxt..'\r\n|-\r\n|'..Icons.Icon({name, type='monster'})
         tableTxt = tableTxt..'\r\n|-\r\n|'..Icons.Icon({name, type='monster'})
         tableTxt = tableTxt..'||'..p.getMonsterCombatLevel(name)
         tableTxt = tableTxt..'||'..p._getMonsterCombatLevel(monster)
         tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterHP(name))
         tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterHP(name))
         tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterMaxHit(name))
         tableTxt = tableTxt..'||'..Shared.formatnum(p.getMonsterMaxHit(name))
Line 757: Line 802:
   local area = Areas.getArea(areaName)
   local area = Areas.getArea(areaName)
   if area == nil then
   if area == nil then
     return "ERROR: Could not find an area named "..areaName
     return "ERROR: Could not find an area named "..areaName..'[[Category:Pages with script errors]]'
   end
   end


Line 770: Line 815:
   local bossMonster = p.getMonsterByID(area.monsters[Shared.tableCount(area.monsters)])
   local bossMonster = p.getMonsterByID(area.monsters[Shared.tableCount(area.monsters)])
   local gpMin = bossMonster.dropCoins[1]
   local gpMin = bossMonster.dropCoins[1]
   local gpMax = bossMonster.dropCoins[2]
   local gpMax = bossMonster.dropCoins[2] - 1
   local chestID = bossMonster.lootTable[1][1]
   local chestID = bossMonster.lootTable[1][1]
   local chestQty = bossMonster.lootTable[1][3]
   local chestQty = bossMonster.lootTable[1][3]
   local theChest = Items.getItemByID(chestID)
   local theChest = Items.getItemByID(chestID)
   local result = '* '..Icons.GP(gpMin, gpMax)
   local result = ''
   result = result..'\r\n* '..Icons.Icon({theChest.name, type='item', qty=chestQty})
  if gpMin > 0 and gpMax > 0 then
    result = result..'* '..Icons.GP(gpMin, gpMax)..'\r\n'
  end
   result = result..'* '..Icons.Icon({theChest.name, type='item', qty=chestQty})
   if area.name == 'Volcanic Cave' then
   if area.name == 'Volcanic Cave' then
     result = result..'\r\n* '..Icons.Icon({'Fire Cape', type='item', qty=1})
     result = result..'\r\n* '..Icons.Icon({'Fire Cape', type='item', qty=1})
Line 788: Line 836:
   local area = Areas.getArea(areaName)
   local area = Areas.getArea(areaName)
   if area == nil then
   if area == nil then
     return "ERROR: Could not find an area named "..areaName
     return "ERROR: Could not find an area named "..areaName..'[[Category:Pages with script errors]]'
   end
   end


Line 794: Line 842:
     return p._getDungeonRewards(area)
     return p._getDungeonRewards(area)
   else
   else
     return "ERROR: "..areaName.." is not a dungeon"
     return "ERROR: "..areaName.." is not a dungeon[[Category:Pages with script errors]]"
   end
   end
end
end
Line 866: Line 914:


   if monster == nil then
   if monster == nil then
     return "ERROR: No monster with that name found"
     return "ERROR: No monster with that name found[[Category:Pages with script errors]]"
   end
   end


Line 888: Line 936:
end
end


function p.getSlayerTierMonsterTable(tier)
function p.getSlayerTierMonsterTable(frame)
   -- Input validation
   -- Input validation
   local SlayerTiers = Constants.Slayer.Tiers
   local tier = frame.args ~= nil and frame.args[1] or frame
  local slayerTier = nil
 
   if tier == nil then
   if tier == nil then
     return "ERROR: No tier specified"
     return "ERROR: No tier specified[[Category:Pages with script errors]]"
   elseif tonumber(tier) == nil then
   end
     return "ERROR: Tier must be an integer"
 
  if tonumber(tier) ~= nil then
     slayerTier = Constants.getSlayerTierByID(tonumber(tier))
   else
   else
     tier = math.floor(tonumber(tier))
     slayerTier = Constants.getSlayerTier(tier)
    local tierCount = Shared.tableCount(SlayerTiers) - 1
  end
    if tier < 0 or tier > tierCount then
 
      return "ERROR: Tier must be between 0 and " .. tierCount
  if slayerTier == nil then
    end
    return "ERROR: Invalid slayer tier[[Category:Pages with script errors]]"
    tier = tier + 1
   end
   end


   -- Obtain required tier details
   -- Obtain required tier details
   local minLevel, maxLevel = SlayerTiers[tier].minLevel, SlayerTiers[tier].maxLevel
   local minLevel, maxLevel = slayerTier.minLevel, slayerTier.maxLevel
   if maxLevel < 0 then
   if maxLevel < 0 then
     maxLevel = nil
     maxLevel = nil
Line 911: Line 962:


   -- Build list of monster IDs
   -- Build list of monster IDs
   -- hiddenMonsterIDs below should be changed to {} when 0.19 releases
   -- Right now hiddenMonsterIDs is empty
   local hiddenMonsterIDs = {139}
   local hiddenMonsterIDs = {}
   local monsterIDs = {}
   local monsterIDs = {}
   for i, monster in Shared.skpairs(MonsterData.Monsters) do
   for i, monster in Shared.skpairs(MonsterData.Monsters) do
Line 927: Line 978:
     return ''
     return ''
   else
   else
     local tableTxt = '{| class="wikitable sortable stickyHeader"'
     return p._getMonsterTable(monsterIDs, true)
    -- First header row
  end
    tableTxt = tableTxt .. '\r\n|- class="headerRow-0"\r\n! colspan="5" | !! colspan="4" |Offensive Stats !! colspan="3" |Evasion Rating !! colspan="4" |'
end
    -- Second header row
 
    tableTxt = tableTxt .. '\r\n|- class="headerRow-1"\r\n!Monster !!Name !!ID !!Combat Level '
function p.getFullMonsterTable(frame)
    tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Hitpoints', type='skill'})
  local monsterIDs = {}
    tableTxt = tableTxt .. '!!Attack Type !!Attack Speed (s) !!Max Hit !!Accuracy '
  for i = 0, Shared.tableCount(MonsterData.Monsters) - 1, 1 do
    tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Defence', type='skill', notext=true})
     table.insert(monsterIDs, i)
    tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Ranged', type='skill', notext=true})
  end
     tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Magic', type='skill', notext=true})
    tableTxt = tableTxt .. '!!Drop Chance !!Coins !!Bones !!Locations'


    -- Generate row per monster
  return p._getMonsterTable(monsterIDs, false)
    for i, monsterID in Shared.skpairs(monsterIDs) do
end
      local monster = p.getMonsterByID(monsterID)
 
      local cmbLevel = p._getMonsterCombatLevel(monster)
function p._getMonsterTable(monsterIDs, excludeDungeons)
      local atkSpeed = p._getMonsterAttackSpeed(monster)
  --Making a single function for getting a table of monsters given a list of IDs.
      local maxHit = p._getMonsterMaxHit(monster)
  local hideDungeons = excludeDungeons ~= nil and excludeDungeons or false
      local accR = p._getMonsterAR(monster)
  local tableParts = {}
      local evaR = {p._getMonsterER({monster, "Melee"}), p._getMonsterER({monster, "Ranged"}), p._getMonsterER({monster, "Magic"})}
  table.insert(tableParts, '{| class="wikitable sortable stickyHeader"')
      local lootChance = monster.lootChance ~= nil and monster.lootChance or 100
  -- First header row
      local gpRange = {0, 0}
  table.insert(tableParts, '\r\n|- class="headerRow-0"\r\n! colspan="5" | !! colspan="4" |Offensive Stats !! colspan="3" |Evasion Rating !! colspan="4" |')
      if monster.dropCoins ~= nil and monster.dropCoins[2] > 1 then
  -- Second header row
        gpRange = {monster.dropCoins[1], monster.dropCoins[2] - 1}
  table.insert(tableParts, '\r\n|- class="headerRow-1"\r\n!Monster !!Name !!ID !!Combat Level ')
      end
  table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Hitpoints', type='skill'}))
      local gpTxt = nil
  table.insert(tableParts, '!!Attack Type !!Attack Speed (s) !!Max Hit !!Accuracy ')
      if gpRange[1] == gpRange[2] then
  table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Defence', type='skill', notext=true}))
        gpTxt = gpRange[1]
  table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Ranged', type='skill', notext=true}))
      else
  table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Magic', type='skill', notext=true}))
        gpTxt = gpRange[1] .. '&nbsp;-&nbsp;' .. gpRange[2]
  table.insert(tableParts, '!!Drop Chance !!Coins !!Bones !!Locations')
      end
      local boneTxt = 'None'
      if monster.bones ~= nil then
        local bones = Items.getItemByID(monster.bones)
        boneTxt = Icons.Icon({bones.name, type='item', notext=true})
      end


      tableTxt = tableTxt .. '\r\n|-\r\n|style="text-align: left;" |' .. Icons.Icon({monster.name, type='monster', size=50, notext=true})
  -- Generate row per monster
      tableTxt = tableTxt .. '\r\n|style="text-align:left" |[[' .. monster.name .. ']]'
  for i, monsterID in Shared.skpairs(monsterIDs) do
      tableTxt = tableTxt .. '\r\n|style="text-align:right" |' .. monsterID
    local monster = p.getMonsterByID(monsterID)
      tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. cmbLevel .. '" |' .. Shared.formatnum(cmbLevel)
    local cmbLevel = p._getMonsterCombatLevel(monster)
      tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. monster.hitpoints .. '" |' .. Shared.formatnum(p._getMonsterHP(monster))
    local atkSpeed = p._getMonsterAttackSpeed(monster)
      tableTxt = tableTxt .. '\r\n|style="text-align:right;white-space:nowrap" |' .. p._getMonsterStyleIcon({monster, nolink='true'})
    local maxHit = p._getMonsterMaxHit(monster)
      tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. atkSpeed .. '" |' .. Shared.round(atkSpeed, 1, 1)
    local accR = p._getMonsterAR(monster)
      tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. maxHit .. '" |' .. Shared.formatnum(maxHit)
    local evaR = {p._getMonsterER({monster, "Melee"}), p._getMonsterER({monster, "Ranged"}), p._getMonsterER({monster, "Magic"})}
      tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. accR .. '" |' .. Shared.formatnum(accR)
    local lootChance = monster.lootChance ~= nil and monster.lootChance or 100
       tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. evaR[1] .. '" |' .. Shared.formatnum(evaR[1])
    local gpRange = {0, 0}
      tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. evaR[2] .. '" |' .. Shared.formatnum(evaR[2])
    if monster.dropCoins ~= nil and monster.dropCoins[2] > 1 then
       tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. evaR[3] .. '" |' .. Shared.formatnum(evaR[3])
       gpRange = {monster.dropCoins[1], monster.dropCoins[2] - 1}
      tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. lootChance .. '" |' .. lootChance .. '%'
    end
       tableTxt = tableTxt .. '\r\n|style="text-align:right" data-sort-value="' .. (gpRange[1] + gpRange[2]) / 2 .. '" |' .. gpTxt
    local gpTxt = nil
       tableTxt = tableTxt .. '\r\n|style="text-align:center" |' .. boneTxt
    if gpRange[1] >= gpRange[2] then
       tableTxt = tableTxt .. '\r\n|style="text-align:right;white-space:nowrap" |' .. p._getMonsterAreas(monster)
       gpTxt = Icons.GP(gpRange[1])
    else
       gpTxt = Icons.GP(gpRange[1], gpRange[2])
    end
    local boneTxt = 'None'
    if monster.bones ~= nil then
       local bones = Items.getItemByID(monster.bones)
       boneTxt = Icons.Icon({bones.name, type='item', notext=true})
     end
     end


     tableTxt = tableTxt .. "\r\n|}"
     table.insert(tableParts, '\r\n|-\r\n|style="text-align: left;" |' .. Icons.Icon({monster.name, type='monster', size=50, notext=true}))
     return tableTxt
    table.insert(tableParts, '\r\n|style="text-align:left" |[[' .. monster.name .. ']]')
    table.insert(tableParts, '\r\n|style="text-align:right" |' .. monsterID)
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. cmbLevel .. '" |' .. Shared.formatnum(cmbLevel))
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. monster.hitpoints .. '" |' .. Shared.formatnum(p._getMonsterHP(monster)))
    table.insert(tableParts, '\r\n|style="text-align:right;white-space:nowrap" |' .. p._getMonsterStyleIcon({monster, nolink='true'}))
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. atkSpeed .. '" |' .. Shared.round(atkSpeed, 1, 1))
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. maxHit .. '" |' .. Shared.formatnum(maxHit))
     table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. accR .. '" |' .. Shared.formatnum(accR))
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. evaR[1] .. '" |' .. Shared.formatnum(evaR[1]))
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. evaR[2] .. '" |' .. Shared.formatnum(evaR[2]))
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. evaR[3] .. '" |' .. Shared.formatnum(evaR[3]))
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. lootChance .. '" |' .. lootChance .. '%')
    table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. (gpRange[1] + gpRange[2]) / 2 .. '" |' .. gpTxt)
    table.insert(tableParts, '\r\n|style="text-align:center" |' .. boneTxt)
    table.insert(tableParts, '\r\n|style="text-align:right;white-space:nowrap" |' .. p._getMonsterAreas(monster, hideDungeons))
   end
   end
  table.insert(tableParts, '\r\n|}')
  return table.concat(tableParts)
end
end


return p
return p