4,951
edits
Falterfire (talk | contribs) (establishing baseline. Copying Monsters and gonna edit from there to get v0.21 compatability) |
Falterfire (talk | contribs) (Updated a bunch of stuff for v0.21) |
||
Line 33: | Line 33: | ||
result.id = ID | result.id = ID | ||
return result | return result | ||
end | end | ||
Line 69: | Line 51: | ||
function p.getPassiveByID(ID) | function p.getPassiveByID(ID) | ||
return MonsterData.Passives[ID + 1] | return MonsterData.Passives[ID + 1] | ||
end | |||
function p._getMonsterStat(monster, statName) | |||
if statName == 'HP' then | |||
return p._getMonsterHP(monster) | |||
elseif statName == 'maxHit' then | |||
return p._getMonsterMaxHit(monster) | |||
elseif statName == 'accuracyRating' then | |||
return p._getMonsterAR(monster) | |||
elseif statName == 'meleeEvasionRating' then | |||
return p._getMonsterER(monster, 'Melee') | |||
elseif statName == 'rangedEvasionRating' then | |||
return p._getMonsterER(monster, 'Ranged') | |||
elseif statName == 'magicEvasionRating' then | |||
return p._getMonsterER(monster, 'Magic') | |||
end | |||
return monster[StatName] | |||
end | end | ||
Line 79: | Line 79: | ||
end | end | ||
return p._getMonsterStat(monster, StatName) | |||
end | end | ||
Line 103: | Line 89: | ||
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 | elseif monster.attackType == 'ranged' then | ||
iconText = Icons.Icon({'Ranged', type='skill', notext=notext, nolink=nolink}) | iconText = Icons.Icon({'Ranged', type='skill', notext=notext, nolink=nolink}) | ||
elseif | elseif 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 128: | Line 114: | ||
function p._getMonsterHP(monster) | function p._getMonsterHP(monster) | ||
return monster | return 10 * p.getMonsterLevel(monster, 'Hitpoints') | ||
end | end | ||
Line 139: | Line 125: | ||
return "ERROR: No monster with that name found[[Category:Pages with script errors]]" | return "ERROR: No monster with that name found[[Category:Pages with script errors]]" | ||
end | end | ||
end | |||
function p.getMonsterLevel(monster, skillName) | |||
local result = 0 | |||
if monster.levels[skillName] ~= nil then | |||
result = monster.levels[skillName] | |||
end | |||
return result | |||
end | |||
function p.getEquipmentStat(monster, statName) | |||
local result = 0 | |||
for i, stat in Shared.skpairs(monster.equipmentStats) do | |||
if stat.key == statName then | |||
result = stat.value | |||
break | |||
end | |||
end | |||
return result | |||
end | |||
function p.calculateStandardStat(effectiveLevel, bonus) | |||
--Based on calculateStandardStat in Characters.js | |||
return (effectiveLevel + 9) * (bonus + 64) | |||
end | |||
function p.calculateStandardMaxHit(baseLevel, strengthBonus) | |||
--Based on calculateStandardMaxHit in Characters.js | |||
local effectiveLevel = baseLevel + 9 | |||
return math.floor(10 * (1.3 + effectiveLevel / 10 + strengthBonus / 80 + effectiveLevel * strengthBonus / 640)) | |||
end | end | ||
function p._getMonsterAttackSpeed(monster) | function p._getMonsterAttackSpeed(monster) | ||
return monster | return p._getEquipmentStat(monster, 'attackSpeed') / 1000 | ||
end | end | ||
Line 156: | Line 172: | ||
function p._getMonsterCombatLevel(monster) | function p._getMonsterCombatLevel(monster) | ||
local base = 0.25 * (monster. | local base = 0.25 * (p.getMonsterLevel(monster, 'Defence') + p.getMonsterLevel(monster, 'Hitpoints')) | ||
local melee = 0.325 * (monster. | local melee = 0.325 * (p.getMonsterLevel(monster, 'Attack') + p.getMonsterLevel(monster, 'Strength')) | ||
local range = 0.325 * (1.5 * monster | local range = 0.325 * (1.5 * p.getMonsterLevel(monster, 'Ranged')) | ||
local magic = 0.325 * (1.5 * monster | local magic = 0.325 * (1.5 * p.getMonsterLevel(monster, 'Magic')) | ||
if melee > range and melee > magic then | if melee > range and melee > magic then | ||
return math.floor(base + melee) | return math.floor(base + melee) | ||
Line 181: | Line 197: | ||
function p._getMonsterAR(monster) | function p._getMonsterAR(monster) | ||
local | local baseLevel = 0 | ||
local | local bonus = 0 | ||
if | if monster.attackType == 'melee' then | ||
baseLevel = p.getMonsterLevel(monster, 'Attack') | |||
bonus = p.getEquipmentStat(monster, 'stabAttackBonus') | |||
elseif | elseif monster.attackType == 'ranged' then | ||
baseLevel = p.getMonsterLevel(monster, 'Ranged') | |||
bonus = p.getEquipmentStat(monster, 'rangedAttackBonus') | |||
elseif | elseif monster.attackType == 'magic' then | ||
baseLevel = p.getMonsterLevel(monster, 'Magic') | |||
bonus = p.getEquipmentStat(monster, 'magicAttackBonus') | |||
else | else | ||
return "ERROR: This monster has an invalid attack type somehow[[Category:Pages with script errors]]" | return "ERROR: This monster has an invalid attack type somehow[[Category:Pages with script errors]]" | ||
end | end | ||
return | return p.calculateStandardStat(baseLevel, bonus) | ||
end | end | ||
Line 210: | Line 226: | ||
end | end | ||
function p._getMonsterER( | function p._getMonsterER(monster, style) | ||
local | local baseLevel= 0 | ||
local | local bonus = 0 | ||
if style == "Melee" then | if style == "Melee" then | ||
baseLevel = p.getMonsterLevel(monster, 'Defence') | |||
bonus = p.getEquipmentStat(monster, 'meleeDefenceBonus') | |||
elseif style == "Ranged" then | elseif style == "Ranged" then | ||
baseLevel = p.getMonsterLevel(monster, 'Defence') | |||
bonus = p.getEquipmentStat(monster, 'rangedDefenceBonus') | |||
elseif style == "Magic" then | elseif style == "Magic" then | ||
baseLevel = math.floor(p.getMonsterLevel(monster, 'Magic') * 0.7 + p.getMonsterLevel(monster, 'Defence') * 0.3) | |||
bonus = p.getEquipmentStat(monster, 'magicDefenceBonus') | |||
else | else | ||
return "ERROR: Must choose Melee, Ranged, or Magic[[Category:Pages with script errors]]" | return "ERROR: Must choose Melee, Ranged, or Magic[[Category:Pages with script errors]]" | ||
end | end | ||
return | |||
return p.calculateStandardStat(baseLevel, bonus) | |||
end | end | ||
Line 242: | Line 256: | ||
end | end | ||
return p._getMonsterER( | return p._getMonsterER(monster, style) | ||
end | end | ||
Line 294: | Line 308: | ||
return p._getMonsterAreas(monster, hideDungeons) | return p._getMonsterAreas(monster, hideDungeons) | ||
end | |||
function p.getSpecAttackMaxHit(specAttack, normalMaxHit) | |||
local result = 0 | |||
for i, dmg in pairs(specAttack.damage) do | |||
if dmg.maxRoll == 'Fixed' then | |||
result = dmg.maxPercent * 10 | |||
elseif dmgRoll == "MaxHit" then | |||
if dmg.character == 'Target' then | |||
--Confusion applied damage based on the player's max hit. Gonna just ignore that one | |||
result = 0 | |||
else | |||
result = dmg.maxPercent * normalMaxHit | |||
end | |||
end | |||
end | |||
return result | |||
end | |||
function p.canSpecAttackApplyEffect(specAttack, effectType) | |||
local result = false | |||
for i, effect in pairs(specAttack.prehitEffects) do | |||
if effect.type == effectType then | |||
result = true | |||
break | |||
end | |||
end | |||
for i, effect in pairs(specAttack.onhitEffects) do | |||
if effect.type == effectType then | |||
result = true | |||
break | |||
end | |||
end | |||
return result | |||
end | end | ||
Line 310: | Line 359: | ||
local hasActiveBuffSpec = false | local hasActiveBuffSpec = false | ||
local damageMultiplier = 1 | local damageMultiplier = 1 | ||
if monster. | if monster.specialAttacks[1] ~= nil then | ||
local canStun = false | local canStun = false | ||
local canSleep = false | local canSleep = false | ||
for i, | for i, specAttack in pairs(monster.specialAttacks) do | ||
if monster.overrideSpecialChances ~= nil then | if monster.overrideSpecialChances ~= nil then | ||
normalChance = normalChance - monster.overrideSpecialChances[i] | normalChance = normalChance - monster.overrideSpecialChances[i] | ||
else | else | ||
normalChance = normalChance - specAttack. | normalChance = normalChance - specAttack.defaultChance | ||
end | end | ||
local thisMax = | local thisMax = p.getSpecAttackMaxHit(specAttack, normalMaxHit) | ||
if p.canSpecAttackApplyEffect(specAttack, 'Stun') then canStun = true end | |||
if p.canSpecAttackApplyEffect(specAttack, 'Sleep') then canSleep = true end | |||
if | |||
if | |||
if thisMax > specialMaxHit then specialMaxHit = thisMax end | if thisMax > specialMaxHit then specialMaxHit = thisMax end | ||
if | if Shared.contains(string.upper(specAttack.description), 'NORMAL ATTACK INSTEAD') then | ||
hasActiveBuffSpec = true | hasActiveBuffSpec = true | ||
end | end | ||
end | end | ||
mw.log(canStun) | |||
if canSleep and doStuns then damageMultiplier = damageMultiplier * 1.2 end | |||
if canStun and doStuns then damageMultiplier = damageMultiplier * 1.3 end | if canStun and doStuns then damageMultiplier = damageMultiplier * 1.3 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 | ||
Line 356: | Line 400: | ||
function p._getMonsterBaseMaxHit(monster) | function p._getMonsterBaseMaxHit(monster) | ||
--8/27/21 - Now references p.calculateStandardMaxHit for Melee & Ranged | |||
local | local result = 0 | ||
if | if monster.attackType == 'melee' then | ||
local baseLevel = p.getMonsterLevel(monster, 'Strength') | |||
local bonus = p.getEquipmentStat(monster, 'meleeStrengthBonus') | |||
elseif | result = p.calculateStandardMaxHit(baseLevel, bonus) | ||
elseif monster.attackType == 'ranged' then | |||
local baseLevel = p.getMonsterLevel(monster, 'Ranged') | |||
elseif | local bonus = p.getEquipmentStat(monster, 'rangedStrengthBonus') | ||
result = p.calculateStandardMaxHit(baseLevel, bonus) | |||
elseif 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 | ||
local bonus = p.getEquipmentStat(monster, 'magicDamageBonus') | |||
local baseLevel = p.getMonsterLevel(monster, 'Magic') | |||
result = math.floor(10 * mSpell.maxHit * (1 + bonus / 100) * (1 + (baseLevel + 1) / 200)) | |||
else | else | ||
return "ERROR: This monster has an invalid attack type somehow[[Category:Pages with script errors]]" | return "ERROR: This monster has an invalid attack type somehow[[Category:Pages with script errors]]" | ||
end | end | ||
return result | |||
return | |||
end | end | ||
Line 403: | Line 448: | ||
local iconText = '' | local iconText = '' | ||
local typeText = '' | local typeText = '' | ||
if | if monster.attackType == 'melee' then | ||
iconText = Icons.Icon({'Melee', notext=true}) | iconText = Icons.Icon({'Melee', notext=true}) | ||
typeText = 'Melee' | typeText = 'Melee' | ||
elseif | elseif monster.attackType == 'ranged' then | ||
iconText = Icons.Icon({'Ranged', type='skill', notext=true}) | iconText = Icons.Icon({'Ranged', type='skill', notext=true}) | ||
typeText = 'Ranged' | typeText = 'Ranged' | ||
elseif | elseif 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 418: | Line 463: | ||
local normalAttackChance = 100 | local normalAttackChance = 100 | ||
if monster. | if monster.specialAttacks[1] ~= nil then | ||
for i, | for i, specAttack in pairs(monster.specialAttacks) do | ||
local attChance = 0 | local attChance = 0 | ||
if monster.overrideSpecialChances ~= nil then | if monster.overrideSpecialChances ~= nil then | ||
attChance = monster.overrideSpecialChances[i] | attChance = monster.overrideSpecialChances[i] | ||
else | else | ||
attChance = specAttack. | attChance = specAttack.defaultChance | ||
end | end | ||
normalAttackChance = normalAttackChance - attChance | normalAttackChance = normalAttackChance - attChance | ||
Line 431: | Line 475: | ||
result = result..'\r\n* '..attChance..'% '..iconText..' '..specAttack.name..'\r\n** '..specAttack.description | result = result..'\r\n* '..attChance..'% '..iconText..' '..specAttack.name..'\r\n** '..specAttack.description | ||
if | if Shared.contains(string.upper(specAttack.description), 'NORMAL ATTACK INSTEAD') then | ||
table.insert(buffAttacks, specAttack.name) | table.insert(buffAttacks, specAttack.name) | ||
hasActiveBuffSpec = true | hasActiveBuffSpec = true | ||
Line 444: | Line 488: | ||
--If the monster normally has a 0% chance of doing a normal attack but some special attacks can't be repeated, include it | --If the monster normally has a 0% chance of doing a normal attack but some special attacks can't be repeated, include it | ||
--(With a note about when it does it) | --(With a note about when it does it) | ||
result = '* '..iconText..' 1 - '..p._getMonsterBaseMaxHit(monster)..' '..typeText..' Damage (Instead of repeating '..table.concat(buffAttacks, ' or ')..' while the | result = '* '..iconText..' 1 - '..p._getMonsterBaseMaxHit(monster)..' '..typeText..' Damage (Instead of repeating '..table.concat(buffAttacks, ' or ')..' while the effect is already active)'..result | ||
end | end | ||
Line 485: | Line 529: | ||
local result = '[[Category:Monsters]]' | local result = '[[Category:Monsters]]' | ||
if | if monster.attackType == 'melee' then | ||
result = result..'[[Category:Melee Monsters]]' | result = result..'[[Category:Melee Monsters]]' | ||
elseif | elseif monster.attackType == 'ranged' then | ||
result = result..'[[Category:Ranged Monsters]]' | result = result..'[[Category:Ranged Monsters]]' | ||
elseif | elseif monster.attackType == 'magic' then | ||
result = result..'[[Category:Magic Monsters]]' | result = result..'[[Category:Magic Monsters]]' | ||
end | end | ||
if monster. | if monster.specialAttacks[1] ~= nil then | ||
result = result..'[[Category:Monsters with Special Attacks]]' | result = result..'[[Category:Monsters with Special Attacks]]' | ||
end | end |