Module:Monsters: Difference between revisions

Amend odd indentation; _getMonsterCombatLevel/_getMonsterAreas: Refactor
m (fixed ids)
(Amend odd indentation; _getMonsterCombatLevel/_getMonsterAreas: Refactor)
Line 19: Line 19:


for i, monster in pairs(MonsterData.Monsters) do
for i, monster in pairs(MonsterData.Monsters) do
if(monster.name == name) then
if monster.name == name then
result = Shared.clone(monster)
result = Shared.clone(monster)
--Make sure every monster has an ID, and account for the 1-based indexing of Lua
--Make sure every monster has an ID, and account for the 1-based indexing of Lua
Line 104: Line 104:


local iconText = ''
local iconText = ''
if monster.attackType == 'melee' then
if monster.attackType == 'melee' then
iconText = Icons.Icon({'Melee', notext=notext, nolink=nolink})
iconText = Icons.Icon({'Melee', notext=notext, nolink=nolink})
elseif monster.attackType == 'ranged' then
elseif monster.attackType == 'ranged' then
Line 215: Line 215:
local range = 0.325 * (1.5 * p._getMonsterLevel(monster, 'Ranged'))
local range = 0.325 * (1.5 * p._getMonsterLevel(monster, 'Ranged'))
local magic = 0.325 * (1.5 * p._getMonsterLevel(monster, 'Magic'))
local magic = 0.325 * (1.5 * p._getMonsterLevel(monster, 'Magic'))
if melee > range and melee > magic then
return math.floor(base + math.max(melee, range, magic))
return math.floor(base + melee)
elseif range > magic then
return math.floor(base + range)
else
return math.floor(base + magic)
end
end
end


Line 344: Line 338:


function p._getMonsterAreas(monster, excludeDungeons)
function p._getMonsterAreas(monster, excludeDungeons)
local result = ''
local resultPart = {}
local hideDungeons = excludeDungeons ~= nil and excludeDungeons or false
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 ipairs(areaList) do
if area.type ~= 'dungeon' or not hideDungeons then
if area.type ~= 'dungeon' or not hideDungeons then
if i > 1 then result = result..'<br/>' end
table.insert(resultPart, Icons.Icon({area.name, type = area.type}))
result = result..Icons.Icon({area.name, type = area.type})
end
end
end
end
return result
return table.concat(resultPart, '<br/>')
end
end


Line 475: Line 468:
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
 
bonus = p.getEquipmentStat(monster, 'magicDamageBonus')
bonus = p.getEquipmentStat(monster, 'magicDamageBonus')
baseLevel = p._getMonsterLevel(monster, 'Magic')
baseLevel = p._getMonsterLevel(monster, 'Magic')
Line 534: Line 527:
local iconText = p._getMonsterStyleIcon({monster, notext=true})
local iconText = p._getMonsterStyleIcon({monster, notext=true})
local typeText = ''
local typeText = ''
if monster.attackType == 'melee' then
if monster.attackType == 'melee' then
typeText = 'Melee'
typeText = 'Melee'
elseif monster.attackType == 'ranged' then
elseif monster.attackType == 'ranged' then
Line 719: Line 712:
local maxQty = row[3]
local maxQty = row[3]
if thisItem ~= nil then
if thisItem ~= nil then
result = result..'\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item'})
result = result..'\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item'})
else
else
result = result..'\r\n|-\r\n|Unknown Item[[Category:Pages with script errors]]'
result = result..'\r\n|-\r\n|Unknown Item[[Category:Pages with script errors]]'
end
end
Line 731: Line 724:


--Adding price columns
--Adding price columns
local itemPrice = 0
local itemPrice = 0
if thisItem == nil then
if thisItem == nil then
result = result..'||data-sort-value="0"|???'
result = result..'||data-sort-value="0"|???'
else
else
itemPrice = thisItem.sellsFor ~= nil and thisItem.sellsFor or 0
itemPrice = thisItem.sellsFor ~= nil and thisItem.sellsFor or 0
if itemPrice == 0 or maxQty == 1 then
if itemPrice == 0 or maxQty == 1 then
result = result..'||'..Icons.GP(itemPrice)
result = result..'||'..Icons.GP(itemPrice)
Line 798: Line 791:
local lootChance = monster.lootChance ~= nil and monster.lootChance or 100
local lootChance = monster.lootChance ~= nil and monster.lootChance or 100


local totalWt = 0
local totalWt = 0
--for i, row in pairs(monster.lootTable) do
--for i, row in pairs(monster.lootTable) do
--totalWt = totalWt + row[2]
--totalWt = totalWt + row[2]
--end
--end
local dropChance = 0
local dropChance = 0
local dropWt = 0
local dropWt = 0
for i, row in Shared.skpairs(monster.lootTable) do
for i, row in Shared.skpairs(monster.lootTable) do
local thisItem = Items.getItemByID(row[1])
local thisItem = Items.getItemByID(row[1])
totalWt = totalWt + row[2]
totalWt = totalWt + row[2]
if item['id'] == thisItem['id'] then
if item['id'] == thisItem['id'] then
dropWt = row[2]
dropWt = row[2]
end
end
end
end
dropChance = (dropWt / totalWt * lootChance)
dropChance = (dropWt / totalWt * lootChance)
return Shared.round(dropChance, 2, 2)
return Shared.round(dropChance, 2, 2)
end
end
end
end
Line 870: Line 863:
result = result..'||style="text-align:left" data-sort-value="'..thisItem.sellsFor..'"'
result = result..'||style="text-align:left" data-sort-value="'..thisItem.sellsFor..'"'
if qty > 1 then
if qty > 1 then
result = result..'|'..Icons.GP(thisItem.sellsFor, thisItem.sellsFor * qty)
result = result..'|'..Icons.GP(thisItem.sellsFor, thisItem.sellsFor * qty)
else
else
result = result..'|'..Icons.GP(thisItem.sellsFor)
result = result..'|'..Icons.GP(thisItem.sellsFor)
Line 929: Line 922:
-- Declare function for building table rows to avoid repeating code
-- Declare function for building table rows to avoid repeating code
local buildRow = function(entityID, monsterCount, specialType)
local buildRow = function(entityID, monsterCount, specialType)
local monIcon, monLevel, monHP, monMaxHit, monStyle, monCount
local monIcon, monLevel, monHP, monMaxHit, monStyle, monCount
local monData = {}
local monData = {}
if specialType ~= nil and Shared.contains({'Afflicted', 'SlayerArea'}, specialType) then
if specialType ~= nil and Shared.contains({'Afflicted', 'SlayerArea'}, specialType) then
-- Special handling for Into the Mist
-- Special handling for Into the Mist
if specialType == 'Afflicted' then
if specialType == 'Afflicted' then
local iconQ = Icons.Icon({'Into the Mist', notext=true, nolink=true, img='Question'})
local iconQ = Icons.Icon({'Into the Mist', notext=true, nolink=true, img='Question'})
Line 948: Line 941:
monCount = monsterCount
monCount = monsterCount
end
end
else
else
-- entityID corresponds to a monster
-- entityID corresponds to a monster
local monster = p.getMonsterByID(entityID)
local monster = p.getMonsterByID(entityID)
monIcon = Icons.Icon({monster.name, type='monster'})
monIcon = Icons.Icon({monster.name, type='monster'})
monLevel = p._getMonsterCombatLevel(monster)
monLevel = p._getMonsterCombatLevel(monster)
monHP = p._getMonsterHP(monster)
monHP = p._getMonsterHP(monster)
monMaxHit = p._getMonsterMaxHit(monster)
monMaxHit = p._getMonsterMaxHit(monster)
monStyle = p._getMonsterStyleIcon({monster})
monStyle = p._getMonsterStyleIcon({monster})
monCount = monsterCount
monCount = monsterCount
end
end
local getValSort = function(val)
local getValSort = function(val)
if type(val) == 'table' then
if type(val) == 'table' then
if type(val[1]) == 'number' and type(val[2]) == 'number' then
if type(val[1]) == 'number' and type(val[2]) == 'number' then
return (val[1] + val[2]) / 2
return (val[1] + val[2]) / 2
else
return (type(val[1]) == 'number' and val[1]) or 0
end
else
else
return (type(val) == 'number' and val) or 0
return (type(val[1]) == 'number' and val[1]) or 0
end
end
else
return (type(val) == 'number' and val) or 0
end
end
local getValText = function(val)
end
if type(val) == 'table' and Shared.tableCount(val) == 2 then
local getValText = function(val)
if type(val[1]) == 'number' and type(val[2]) == 'number' then
if type(val) == 'table' and Shared.tableCount(val) == 2 then
return Shared.formatnum(val[1]) .. ' - ' .. Shared.formatnum(val[2])
if type(val[1]) == 'number' and type(val[2]) == 'number' then
else
return Shared.formatnum(val[1]) .. ' - ' .. Shared.formatnum(val[2])
return val[1] .. ' - ' .. val[2]
end
elseif type(val) == 'number' then
return Shared.formatnum(val)
else
else
return val
return val[1] .. ' - ' .. val[2]
end
end
elseif type(val) == 'number' then
return Shared.formatnum(val)
else
return val
end
end
end
local resultPart = {}
local resultPart = {}
table.insert(resultPart, '\r\n|-\r\n| ' .. monIcon)
table.insert(resultPart, '\r\n|-\r\n| ' .. monIcon)
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monLevel) .. '"| ' .. getValText(monLevel))
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monLevel) .. '"| ' .. getValText(monLevel))
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monHP) .. '"| ' .. getValText(monHP))
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monHP) .. '"| ' .. getValText(monHP))
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monMaxHit) .. '"| ' .. getValText(monMaxHit))
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monMaxHit) .. '"| ' .. getValText(monMaxHit))
table.insert(resultPart, '\r\n| ' .. monStyle)
table.insert(resultPart, '\r\n| ' .. monStyle)
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monCount) .. '"| ' .. getValText(monCount))
table.insert(resultPart, '\r\n|style="text-align:right;" data-sort-value="' .. getValSort(monCount) .. '"| ' .. getValText(monCount))
return table.concat(resultPart)
return table.concat(resultPart)
end
end


local returnPart = {}
local returnPart = {}
Line 1,107: Line 1,100:
if not p._isDungeonOnlyMonster(monster) then
if not p._isDungeonOnlyMonster(monster) then
if monster.dropCoins ~= nil and monster.dropCoins[2] > 1 then
if monster.dropCoins ~= nil and monster.dropCoins[2] > 1 then
local avgGp = (monster.dropCoins[1] + monster.dropCoins[2]) / 2
local avgGp = (monster.dropCoins[1] + monster.dropCoins[2]) / 2
result = result..'<br/>'..monster.name..','..monster.dropCoins[1]..','..(monster.dropCoins[2])..','..avgGp
result = result..'<br/>'..monster.name..','..monster.dropCoins[1]..','..(monster.dropCoins[2])..','..avgGp
end
end
end
end
Line 1,257: Line 1,250:
table.insert(tableParts, '!!' .. Icons.Icon({'Coins', notext=true, nolink=true}) .. ' Coins !!Bones !!Locations')
table.insert(tableParts, '!!' .. Icons.Icon({'Coins', notext=true, nolink=true}) .. ' Coins !!Bones !!Locations')


-- Generate row per monster
-- Generate row per monster
for i, monsterID in Shared.skpairs(monsterIDs) do
for i, monsterID in Shared.skpairs(monsterIDs) do
local monster = p.getMonsterByID(monsterID)
local monster = p.getMonsterByID(monsterID)
Line 1,301: Line 1,294:


function p.getSpecialAttackTable(frame)
function p.getSpecialAttackTable(frame)
local spAttTable = {}
local spAttTable = {}


for i, monster in ipairs(MonsterData.Monsters) do
for i, monster in ipairs(MonsterData.Monsters) do
if monster.specialAttacks ~= nil and Shared.tableCount(monster.specialAttacks) > 0 then
if monster.specialAttacks ~= nil and Shared.tableCount(monster.specialAttacks) > 0 then
local overrideChance = (monster.overrideSpecialChances ~= nil and Shared.tableCount(monster.overrideSpecialChances) > 0)
local overrideChance = (monster.overrideSpecialChances ~= nil and Shared.tableCount(monster.overrideSpecialChances) > 0)
for j, spAtt in ipairs(monster.specialAttacks) do
for j, spAtt in ipairs(monster.specialAttacks) do
local attChance = (overrideChance and monster.overrideSpecialChances[j] or spAtt.defaultChance)
local attChance = (overrideChance and monster.overrideSpecialChances[j] or spAtt.defaultChance)
if spAttTable[spAtt.id] == nil then
if spAttTable[spAtt.id] == nil then
    spAttTable[spAtt.id] = { ['defn'] = spAtt, ['icons'] = {} }
spAttTable[spAtt.id] = { ['defn'] = spAtt, ['icons'] = {} }
end
if spAttTable[spAtt.id]['icons'][attChance] == nil then
    spAttTable[spAtt.id]['icons'][attChance] = {}
end
table.insert(spAttTable[spAtt.id]['icons'][attChance], Icons.Icon({ monster.name, type = 'monster' }))
end
end
end
if spAttTable[spAtt.id]['icons'][attChance] == nil then
spAttTable[spAtt.id]['icons'][attChance] = {}
end
table.insert(spAttTable[spAtt.id]['icons'][attChance], Icons.Icon({ monster.name, type = 'monster' }))
end
end
end
end


local resultPart = {}
local resultPart = {}
table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
table.insert(resultPart, '\r\n|- class="headerRow-0"')
table.insert(resultPart, '\r\n|- class="headerRow-0"')
table.insert(resultPart, '\r\n!Name!!style="min-width:225px"|Monsters!!Chance!!Effect')
table.insert(resultPart, '\r\n!Name!!style="min-width:225px"|Monsters!!Chance!!Effect')


for i, spAttData in Shared.skpairs(spAttTable) do
for i, spAttData in Shared.skpairs(spAttTable) do
local spAtt = spAttData.defn
local spAtt = spAttData.defn
local firstRow = true
local firstRow = true
local rowsSpanned = Shared.tableCount(spAttData.icons)
local rowsSpanned = Shared.tableCount(spAttData.icons)
local rowSuffix = ''
local rowSuffix = ''
if rowsSpanned > 1 then
if rowsSpanned > 1 then
rowSuffix = '|rowspan="' .. rowsSpanned .. '"'
rowSuffix = '|rowspan="' .. rowsSpanned .. '"'
end
end
for chance, iconList in Shared.skpairs(spAttData.icons) do
for chance, iconList in Shared.skpairs(spAttData.icons) do
table.insert(resultPart, '\r\n|-')
table.insert(resultPart, '\r\n|-')
if firstRow then
if firstRow then
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.name)
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.name)
end
end
table.insert(resultPart, '\r\n|data-sort-value="' .. spAtt.name .. '"| ' .. table.concat(iconList, '<br/>'))
table.insert(resultPart, '\r\n|data-sort-value="' .. spAtt.name .. '"| ' .. table.concat(iconList, '<br/>'))
table.insert(resultPart, '\r\n|data-sort-value="' .. chance .. '"| ' .. Shared.round(chance, 2, 0) .. '%')
table.insert(resultPart, '\r\n|data-sort-value="' .. chance .. '"| ' .. Shared.round(chance, 2, 0) .. '%')
if firstRow then
if firstRow then
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.description)
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.description)
firstRow = false
firstRow = false
end
end
end
end
end
table.insert(resultPart, '\r\n|}')
end
table.insert(resultPart, '\r\n|}')


return table.concat(resultPart)
return table.concat(resultPart)
end
end


return p
return p