12,787
edits
m (fixed ids) |
(_getMonsterStyleIcon: Revert change to use adjusted Icon override instead) |
||
(24 intermediate revisions by 4 users not shown) | |||
Line 19: | Line 19: | ||
for i, monster in pairs(MonsterData.Monsters) do | for i, monster in pairs(MonsterData.Monsters) do | ||
if | 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 31: | Line 31: | ||
function p.getMonsterByID(ID) | function p.getMonsterByID(ID) | ||
local result = Shared.clone(MonsterData.Monsters[ID + 1]) | local result = Shared.clone(MonsterData.Monsters[ID + 1]) | ||
result.id = ID | if result ~= nil then | ||
return | result.id = ID | ||
return result | |||
else | |||
return nil | |||
end | |||
end | end | ||
Line 104: | Line 108: | ||
local iconText = '' | local iconText = '' | ||
if | 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 219: | ||
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')) | ||
return math.floor(base + math.max(melee, range, magic)) | |||
end | end | ||
Line 304: | Line 302: | ||
-- Determines if the monster is capable of dropping bones, and returns the bones | -- Determines if the monster is capable of dropping bones, and returns the bones | ||
-- item if so, or nil otherwise | -- item if so, or nil otherwise | ||
function p. | function p._getMonsterBones(monster) | ||
if monster.bones ~= nil and monster.bones >= 0 then | if monster.bones ~= nil and monster.bones >= 0 then | ||
local boneItem = Items.getItemByID(monster.bones) | local boneItem = Items.getItemByID(monster.bones) | ||
Line 344: | Line 342: | ||
function p._getMonsterAreas(monster, excludeDungeons) | function p._getMonsterAreas(monster, excludeDungeons) | ||
local | 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 | for i, area in ipairs(areaList) do | ||
if area.type ~= 'dungeon' or not hideDungeons then | if area.type ~= 'dungeon' or not hideDungeons then | ||
table.insert(resultPart, Icons.Icon({area.name, type = area.type})) | |||
end | end | ||
end | end | ||
return | return table.concat(resultPart, '<br/>') | ||
end | end | ||
Line 475: | Line 472: | ||
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 531: | ||
local iconText = p._getMonsterStyleIcon({monster, notext=true}) | local iconText = p._getMonsterStyleIcon({monster, notext=true}) | ||
local typeText = '' | local typeText = '' | ||
if | if monster.attackType == 'melee' then | ||
typeText = 'Melee' | typeText = 'Melee' | ||
elseif monster.attackType == 'ranged' then | elseif monster.attackType == 'ranged' then | ||
Line 588: | Line 585: | ||
local result = '' | local result = '' | ||
if type(monster.passiveID) == 'table' and Shared.tableCount(monster.passiveID) > 0 then | |||
if monster. | |||
result = result .. '===Passives===' | result = result .. '===Passives===' | ||
for i, passiveID in pairs(monster.passiveID) do | for i, passiveID in pairs(monster.passiveID) do | ||
Line 679: | Line 675: | ||
local result = '' | local result = '' | ||
local bones = p. | local bones = p._getMonsterBones(monster) | ||
local boneVal = 0 | |||
--Show the bones only if either the monster shows up outside of dungeons _or_ the monster drops shards | --Show the bones only if either the monster shows up outside of dungeons _or_ the monster drops shards | ||
if bones ~= nil then | if bones ~= nil then | ||
local boneQty = (monster.boneQty ~= nil and monster.boneQty or 1) | |||
result = result.."'''Always Drops:'''" | result = result.."'''Always Drops:'''" | ||
result = result..'\r\n{|class="wikitable" id="bonedrops"' | result = result..'\r\n{|class="wikitable" id="bonedrops"' | ||
result = result..'\r\n!Item !! Qty' | result = result..'\r\n!Item !! Qty' | ||
result = result..'\r\n|-\r\n|'..Icons.Icon({bones.name, type='item'}) | result = result..'\r\n|-\r\n|'..Icons.Icon({bones.name, type='item'}) | ||
result = result..'||'. | result = result..'||'..boneQty..'\r\n'..'|}' | ||
boneVal = boneQty * bones.sellsFor | |||
end | end | ||
Line 714: | Line 713: | ||
--Sort the loot table by weight in descending order | --Sort the loot table by weight in descending order | ||
table.sort(monster.lootTable, function(a, b) return a[2] > b[2] end) | table.sort(monster.lootTable, function(a, b) return a[2] > b[2] end) | ||
for i, row in | for i, row in ipairs(monster.lootTable) do | ||
local thisItem = Items.getItemByID(row[1]) | local thisItem = Items.getItemByID(row[1]) | ||
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'}) | |||
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 730: | ||
--Adding price columns | --Adding price columns | ||
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 | |||
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 745: | Line 744: | ||
--Getting the drop chance | --Getting the drop chance | ||
local dropChance = (row[2] / totalWt * lootChance) | local dropChance = (row[2] / totalWt * lootChance) | ||
if dropChance | if dropChance < 100 then | ||
--Show fraction as long as it isn't going to be 1/1 | --Show fraction as long as it isn't going to be 1/1 | ||
result = result..'||style="text-align:right" data-sort-value="'..row[2]..'"' | result = result..'||style="text-align:right" data-sort-value="'..row[2]..'"' | ||
Line 753: | Line 752: | ||
result = result..'||colspan="2" data-sort-value="'..row[2]..'"' | result = result..'||colspan="2" data-sort-value="'..row[2]..'"' | ||
end | end | ||
result = result..'style="text-align:right"|'.. | -- If chance is less than 0.10% then show 2 significant figures, otherwise 2 decimal places | ||
local fmt = (dropChance < 0.10 and '%.2g') or '%.2f' | |||
result = result..'style="text-align:right"|'..string.format(fmt, dropChance)..'%' | |||
--Adding to the average loot value based on price & dropchance | --Adding to the average loot value based on price & dropchance | ||
Line 770: | Line 771: | ||
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." | ||
if avgGp > 0 then | if avgGp > 0 then | ||
result = result.. | result = result.."<br/>Including GP" | ||
if boneVal > 0 then | |||
result = result..' and bones' | |||
end | |||
result = result..', the average kill is worth '..Icons.GP(Shared.round(avgGp + lootValue + boneVal, 2, 0))..'.' | |||
end | end | ||
end | end | ||
Line 776: | Line 781: | ||
--If no other drops, make sure to at least say so. | --If no other drops, make sure to at least say so. | ||
if result == '' then result = 'None' end | if result == '' then result = 'None' end | ||
return result | |||
end | |||
function p._getMonsterLootValue(monster) | |||
if monster == nil then | |||
return "ERROR: No monster with that name found[[Category:Pages with script errors]]" | |||
end | |||
local result = 0 | |||
local boneVal = 0 | |||
local bones = p._getMonsterBones(monster) | |||
--Show the bones only if either the monster shows up outside of dungeons _or_ the monster drops shards | |||
if bones ~= nil then | |||
local boneQty = monster.boneQty ~= nil and monster.boneQty or 1 | |||
boneVal = bones.sellsFor * boneQty | |||
result = result + boneVal | |||
end | |||
--Likewise, seeing the loot table is tied to the monster appearing outside of dungeons | |||
if not p._isDungeonOnlyMonster(monster) then | |||
local lootChance = monster.lootChance ~= nil and monster.lootChance or 100 | |||
local lootValue = 0 | |||
local avgGp = 0 | |||
if monster.dropCoins ~= nil and monster.dropCoins[2] > 1 then | |||
avgGp = (monster.dropCoins[1] + monster.dropCoins[2]) / 2 | |||
end | |||
local multiDrop = Shared.tableCount(monster.lootTable) > 1 | |||
local totalWt = 0 | |||
for i, row in pairs(monster.lootTable) do | |||
totalWt = totalWt + row[2] | |||
end | |||
for i, row in ipairs(monster.lootTable) do | |||
local thisItem = Items.getItemByID(row[1]) | |||
local maxQty = row[3] | |||
--Adding price columns | |||
local itemPrice = 0 | |||
if thisItem ~= nil then | |||
itemPrice = thisItem.sellsFor ~= nil and thisItem.sellsFor or 0 | |||
end | |||
--Getting the drop chance | |||
local dropChance = (row[2] / totalWt * lootChance) | |||
--Adding to the average loot value based on price & dropchance | |||
lootValue = lootValue + (dropChance * 0.01 * itemPrice * ((1 + maxQty) / 2)) | |||
end | |||
if avgGp > 0 then | |||
result = result + avgGp + lootValue | |||
end | |||
end | |||
return result | return result | ||
end | end | ||
Line 798: | Line 860: | ||
local lootChance = monster.lootChance ~= nil and monster.lootChance or 100 | local lootChance = monster.lootChance ~= nil and monster.lootChance or 100 | ||
local totalWt = 0 | |||
--for i, row in pairs(monster.lootTable) do | |||
--totalWt = totalWt + row[2] | |||
--end | |||
local dropChance = 0 | |||
local dropWt = 0 | |||
for i, row in ipairs(monster.lootTable) do | |||
totalWt = totalWt + row[2] | |||
if item.id == row[1] then | |||
dropWt = row[2] | dropWt = row[2] | ||
end | end | ||
end | |||
dropChance = (dropWt / totalWt * lootChance) | |||
return Shared.round(dropChance, 2, 2) | |||
end | end | ||
end | end | ||
Line 824: | Line 885: | ||
return "ERROR: No item named "..ChestName..' found[[Category:Pages with script errors]]' | return "ERROR: No item named "..ChestName..' found[[Category:Pages with script errors]]' | ||
end | end | ||
local result = '' | local result = '' | ||
Line 843: | Line 903: | ||
--Sort the loot table by weight in descending order | --Sort the loot table by weight in descending order | ||
local chestDrops, dropIdx = {}, 0 | |||
local hasQty = type(chest.dropQty) == 'table' | |||
for i, row in pairs(chest.dropTable) do | for i, row in pairs(chest.dropTable) do | ||
local qty = hasQty and chest.dropQty[i] or 1 | |||
dropIdx = dropIdx + 1 | |||
chestDrops[dropIdx] = {row[1], row[2], qty} | |||
end | end | ||
table.sort( | table.sort(chestDrops, function(a, b) return a[2] > b[2] end) | ||
for i, row in | for i, row in ipairs(chestDrops) do | ||
local thisItem = Items.getItemByID(row[1]) | local thisItem = Items.getItemByID(row[1]) | ||
local qty = row[3] | local qty = row[3] | ||
Line 870: | Line 930: | ||
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) | |||
else | else | ||
result = result..'|'..Icons.GP(thisItem.sellsFor) | result = result..'|'..Icons.GP(thisItem.sellsFor) | ||
Line 900: | Line 960: | ||
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) | tableTxt = tableTxt..'||'..p._getMonsterCombatLevel(monster) | ||
tableTxt = tableTxt..'||'..Shared.formatnum(p. | tableTxt = tableTxt..'||'..Shared.formatnum(p._getMonsterHP(monster)) | ||
tableTxt = tableTxt..'||'..Shared.formatnum(p. | tableTxt = tableTxt..'||'..Shared.formatnum(p._getMonsterMaxHit(monster)) | ||
tableTxt = tableTxt..'||'..p. | tableTxt = tableTxt..'||'..p._getMonsterStyleIcon({monster, nolink=true}) | ||
end | end | ||
tableTxt = tableTxt..'\r\n|}' | tableTxt = tableTxt..'\r\n|}' | ||
Line 929: | Line 989: | ||
-- 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 monData = {} | |||
if specialType ~= nil and Shared.contains({'Afflicted', 'SlayerArea'}, specialType) then | |||
-- 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 1,008: | ||
monCount = monsterCount | monCount = monsterCount | ||
end | end | ||
else | |||
-- entityID corresponds to a monster | |||
local monster = p.getMonsterByID(entityID) | |||
monIcon = Icons.Icon({monster.name, type='monster'}) | |||
monLevel = p._getMonsterCombatLevel(monster) | |||
monHP = p._getMonsterHP(monster) | |||
monMaxHit = p._getMonsterMaxHit(monster) | |||
monStyle = p._getMonsterStyleIcon({monster}) | |||
monCount = monsterCount | |||
end | |||
local getValSort = function(val) | |||
if type(val) == 'table' then | |||
if type(val[1]) == 'number' and type(val[2]) == 'number' then | |||
return (val[1] + val[2]) / 2 | |||
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 | ||
end | |||
local getValText = function(val) | |||
if type(val) == 'table' and Shared.tableCount(val) == 2 then | |||
if type(val[1]) == 'number' and type(val[2]) == 'number' then | |||
return Shared.formatnum(val[1]) .. ' - ' .. Shared.formatnum(val[2]) | |||
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 = {} | |||
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(monHP) .. '"| ' .. getValText(monHP)) | |||
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|style="text-align:right;" data-sort-value="' .. getValSort(monCount) .. '"| ' .. getValText(monCount)) | |||
return table.concat(resultPart) | |||
end | |||
local returnPart = {} | local returnPart = {} | ||
Line 1,107: | Line 1,167: | ||
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 | |||
result = result..'<br/>'..monster.name..','..monster.dropCoins[1]..','..(monster.dropCoins[2])..','..avgGp | |||
end | end | ||
end | end | ||
Line 1,119: | Line 1,179: | ||
local totalGP = 0 | local totalGP = 0 | ||
local bones = p. | local bones = p._getMonsterBones(monster) | ||
if bones ~= nil then | if bones ~= nil then | ||
totalGP = totalGP + bones.sellsFor * (type(monster.boneQty) == 'number' and monster.boneQty or 1) | totalGP = totalGP + bones.sellsFor * (type(monster.boneQty) == 'number' and monster.boneQty or 1) | ||
Line 1,257: | Line 1,317: | ||
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 | |||
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,276: | Line 1,336: | ||
gpTxt = Shared.formatnum(gpRange[1]) .. ' - ' .. Shared.formatnum(gpRange[2]) | gpTxt = Shared.formatnum(gpRange[1]) .. ' - ' .. Shared.formatnum(gpRange[2]) | ||
end | end | ||
local bones = p. | local bones = p._getMonsterBones(monster) | ||
local boneTxt = (bones ~= nil and Icons.Icon({bones.name, type='item', notext=true})) or 'None' | local boneTxt = (bones ~= nil and Icons.Icon({bones.name, type='item', notext=true})) or 'None' | ||
Line 1,294: | Line 1,354: | ||
table.insert(tableParts, '\r\n|style="text-align:center" |' .. boneTxt) | table.insert(tableParts, '\r\n|style="text-align:center" |' .. boneTxt) | ||
table.insert(tableParts, '\r\n|style="text-align:right;width:190px" |' .. p._getMonsterAreas(monster, hideDungeons)) | table.insert(tableParts, '\r\n|style="text-align:right;width:190px" |' .. p._getMonsterAreas(monster, hideDungeons)) | ||
end | |||
table.insert(tableParts, '\r\n|}') | |||
return table.concat(tableParts) | |||
end | |||
function p.getMattMonsterTable(frame) | |||
--Making a single function for getting a table of monsters given a list of IDs. | |||
local tableParts = {} | |||
table.insert(tableParts, '{| class="wikitable sortable stickyHeader"') | |||
-- Second header row | |||
table.insert(tableParts, '\r\n|- class="headerRow-1"\r\n!Monster !!Name !!ID !!Combat Level ') | |||
table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Hitpoints', type='skill'})) | |||
table.insert(tableParts, '!!' .. Icons.Icon({'Coins', notext=true, nolink=true}) .. ' Coins !!Avg. Kill Value!!Locations') | |||
-- Generate row per monster | |||
for i, monster in Shared.skpairs(MonsterData.Monsters) do | |||
local cmbLevel = p._getMonsterCombatLevel(monster) | |||
local gpRange = {0, 0} | |||
if monster.dropCoins ~= nil and monster.dropCoins[2] > 1 then | |||
gpRange = {monster.dropCoins[1], monster.dropCoins[2]} | |||
end | |||
local gpTxt = nil | |||
if gpRange[1] >= gpRange[2] then | |||
gpTxt = Shared.formatnum(gpRange[1]) | |||
else | |||
gpTxt = Shared.formatnum(gpRange[1]) .. ' - ' .. Shared.formatnum(gpRange[2]) | |||
end | |||
local lootVal = p._getMonsterLootValue(monster) | |||
local lootTxt = '0' | |||
if lootVal ~= 0 then | |||
lootTxt = Shared.formatnum(Shared.round(lootVal, 2, 2)) | |||
end | |||
table.insert(tableParts, '\r\n|-\r\n|style="text-align: center;" |' .. Icons.Icon({monster.name, type='monster', size=50, notext=true})) | |||
table.insert(tableParts, '\r\n|style="text-align:left" |' .. Icons.Icon({monster.name, type='monster', noicon=true})) | |||
table.insert(tableParts, '\r\n|style="text-align:right" |' .. monster.id) | |||
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="' .. p._getMonsterHP(monster) .. '" |' .. Shared.formatnum(p._getMonsterHP(monster))) | |||
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:right" data-sort-value="' .. lootVal .. '" |' .. lootTxt) | |||
table.insert(tableParts, '\r\n|style="text-align:right;width:190px" |' .. p._getMonsterAreas(monster, hideDungeons)) | |||
end | |||
table.insert(tableParts, '\r\n|}') | |||
return table.concat(tableParts) | |||
end | |||
function p.getMattMonsterTableV2(frame) | |||
--Making a single function for getting a table of monsters given a list of IDs. | |||
local tableParts = {} | |||
table.insert(tableParts, '{| class="wikitable sortable stickyHeader"') | |||
-- Second header row | |||
table.insert(tableParts, '\r\n|- class="headerRow-1"\r\n!Monster !!Name !!Combat Level ') | |||
table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Hitpoints', type='skill'})) | |||
table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Defence', type='skill', notext=true})) | |||
table.insert(tableParts, '!!Attack Speed (s) !!colspan="2"|Max Hit !!Accuracy ') | |||
-- table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Ranged', type='skill', notext=true})) | |||
-- table.insert(tableParts, '!!style="padding:0 1em 0 0"|' .. Icons.Icon({'Magic', type='skill', notext=true})) | |||
table.insert(tableParts, '!!' .. Icons.Icon({'Coins', notext=true, nolink=true}) .. ' Coins !!Avg. Kill Value !!Bones') | |||
-- Generate row per monster | |||
for i, monster in Shared.skpairs(MonsterData.Monsters) do | |||
local cmbLevel = p._getMonsterCombatLevel(monster) | |||
local gpRange = {0, 0} | |||
if monster.dropCoins ~= nil and monster.dropCoins[2] > 1 then | |||
gpRange = {monster.dropCoins[1], monster.dropCoins[2]} | |||
end | |||
local gpTxt = nil | |||
if gpRange[1] >= gpRange[2] then | |||
gpTxt = Shared.formatnum(gpRange[1]) | |||
else | |||
gpTxt = Shared.formatnum(gpRange[1]) .. ' - ' .. Shared.formatnum(gpRange[2]) | |||
end | |||
local lootVal = p._getMonsterLootValue(monster) | |||
local lootTxt = '0' | |||
if lootVal ~= 0 then | |||
lootTxt = Shared.formatnum(Shared.round(lootVal, 2, 2)) | |||
end | |||
local atkSpeed = p._getMonsterAttackSpeed(monster) | |||
local maxHit = p._getMonsterMaxHit(monster) | |||
local accR = p._getMonsterAR(monster) | |||
local evaR = {p._getMonsterER(monster, "Melee"), p._getMonsterER(monster, "Ranged"), p._getMonsterER(monster, "Magic")} | |||
local bones = p._getMonsterBones(monster) | |||
local boneTxt = (bones ~= nil and Icons.Icon({bones.name, type='item', notext=true})) or 'None' | |||
table.insert(tableParts, '\r\n|-\r\n|style="text-align: center;" |' .. Icons.Icon({monster.name, type='monster', size=50, notext=true})) | |||
table.insert(tableParts, '\r\n|style="text-align:left" |' .. Icons.Icon({monster.name, type='monster', noicon=true})) | |||
-- table.insert(tableParts, '\r\n|style="text-align:right" |' .. monster.id) | |||
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="' .. p._getMonsterHP(monster) .. '" |' .. Shared.formatnum(p._getMonsterHP(monster))) | |||
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="' .. atkSpeed .. '" |' .. Shared.round(atkSpeed, 1, 1)) | |||
table.insert(tableParts, '\r\n|style="text-align:center;border-right:hidden" |' .. p._getMonsterStyleIcon({monster, notext=true})) | |||
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[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="' .. (gpRange[1] + gpRange[2]) / 2 .. '" |' .. gpTxt) | |||
table.insert(tableParts, '\r\n|style="text-align:right" data-sort-value="' .. lootVal .. '" |' .. lootTxt) | |||
table.insert(tableParts, '\r\n|style="text-align:center" |' .. boneTxt) | |||
-- table.insert(tableParts, '\r\n|style="text-align:right;width:190px" |' .. p._getMonsterAreas(monster, hideDungeons)) | |||
end | end | ||
Line 1,301: | Line 1,472: | ||
function p.getSpecialAttackTable(frame) | function p.getSpecialAttackTable(frame) | ||
local spAttTable = {} | |||
for i, monster in ipairs(MonsterData.Monsters) do | |||
if monster.specialAttacks ~= nil and Shared.tableCount(monster.specialAttacks) > 0 then | |||
local overrideChance = (monster.overrideSpecialChances ~= nil and Shared.tableCount(monster.overrideSpecialChances) > 0) | |||
for j, spAtt in ipairs(monster.specialAttacks) do | |||
local attChance = (overrideChance and monster.overrideSpecialChances[j] or spAtt.defaultChance) | |||
if spAttTable[spAtt.id] == nil then | |||
spAttTable[spAtt.id] = { ['defn'] = spAtt, ['icons'] = {} } | |||
end | |||
if spAttTable[spAtt.id]['icons'][attChance] == nil then | |||
spAttTable[spAtt.id]['icons'][attChance] = {} | |||
end | end | ||
table.insert(spAttTable[spAtt.id]['icons'][attChance], Icons.Icon({ monster.name, type = 'monster' })) | |||
end | |||
end | end | ||
end | |||
local resultPart = {} | |||
table.insert(resultPart, '{|class="wikitable sortable stickyHeader"') | |||
table.insert(resultPart, '\r\n|- class="headerRow-0"') | |||
table.insert(resultPart, '\r\n!Name!!style="min-width:225px"|Monsters!!Chance!!Effect') | |||
for i, spAttData in Shared.skpairs(spAttTable) do | |||
local spAtt = spAttData.defn | |||
local firstRow = true | |||
local rowsSpanned = Shared.tableCount(spAttData.icons) | |||
local rowSuffix = '' | |||
if rowsSpanned > 1 then | |||
rowSuffix = '|rowspan="' .. rowsSpanned .. '"' | |||
end | |||
for chance, iconList in Shared.skpairs(spAttData.icons) do | |||
table.insert(resultPart, '\r\n|-') | |||
if firstRow then | |||
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.name) | |||
end | |||
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) .. '%') | |||
if firstRow then | |||
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.description) | |||
firstRow = false | |||
end | |||
end | end | ||
end | |||
table.insert(resultPart, '\r\n|}') | |||
return table.concat(resultPart) | |||
end | end | ||
return p | return p |