Anonymous

Module:Monsters: Difference between revisions

From Melvor Idle
m
getChestDrops: Added punctuation
(Tweaked Dungeon Rewards to account for Miolite Caves not rewarding any GP)
m (getChestDrops: Added punctuation)
(7 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 290: Line 290:


   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 300: 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 321: 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 333: 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 342: 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 357: 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 369: 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 380: 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 387: 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 426: 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 451: 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 471: 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 480: 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 508: 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 566: 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 580: 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 586: 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 635: 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 645: 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 657: 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 670: 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 694: 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 761: 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 795: 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 801: 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 873: 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 898: Line 939:
   -- Input validation
   -- Input validation
   local tier = frame.args ~= nil and frame.args[1] or frame
   local tier = frame.args ~= nil and frame.args[1] or frame
   local SlayerTiers = Constants.Slayer.Tiers
   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 951: Line 994:
   --Making a single function for getting a table of monsters given a list of IDs.
   --Making a single function for getting a table of monsters given a list of IDs.
   local hideDungeons = excludeDungeons ~= nil and excludeDungeons or false
   local hideDungeons = excludeDungeons ~= nil and excludeDungeons or false
   local tableTxt = '{| class="wikitable sortable stickyHeader"'
   local tableParts = {}
  table.insert(tableParts, '{| class="wikitable sortable stickyHeader"')
   -- First header row
   -- First header row
   tableTxt = tableTxt .. '\r\n|- class="headerRow-0"\r\n! colspan="5" | !! colspan="4" |Offensive Stats !! colspan="3" |Evasion Rating !! colspan="4" |'
   table.insert(tableParts, '\r\n|- class="headerRow-0"\r\n! colspan="5" | !! colspan="4" |Offensive Stats !! colspan="3" |Evasion Rating !! colspan="4" |')
   -- Second header row
   -- Second header row
   tableTxt = tableTxt .. '\r\n|- class="headerRow-1"\r\n!Monster !!Name !!ID !!Combat Level '
   table.insert(tableParts, '\r\n|- class="headerRow-1"\r\n!Monster !!Name !!ID !!Combat Level ')
   tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Hitpoints', type='skill'})
   table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Hitpoints', type='skill'}))
   tableTxt = tableTxt .. '!!Attack Type !!Attack Speed (s) !!Max Hit !!Accuracy '
   table.insert(tableParts, '!!Attack Type !!Attack Speed (s) !!Max Hit !!Accuracy ')
   tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Defence', type='skill', notext=true})
   table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Defence', type='skill', notext=true}))
   tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Ranged', type='skill', notext=true})
   table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Ranged', type='skill', notext=true}))
   tableTxt = tableTxt .. '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Magic', type='skill', notext=true})
   table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Magic', type='skill', notext=true}))
   tableTxt = tableTxt .. '!!Drop Chance !!Coins !!Bones !!Locations'
   table.insert(tableParts, '!!Drop Chance !!Coins !!Bones !!Locations')


   -- Generate row per monster
   -- Generate row per monster
Line 988: Line 1,032:
     end
     end


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


   tableTxt = tableTxt .. "\r\n|}"
   table.insert(tableParts, '\r\n|}')
   return tableTxt
   return table.concat(tableParts)
end
end


return p
return p