Module:Monsters: Difference between revisions

Move logic from getSpecAttackMaxHit to _getMonsterMaxHit, as combo effects persist beyond the special attack which grants them
(getSpecAttackMaxHit: Account for modifiers which adjust the max hit when present in on hit/pre-hit effects or monster passives)
(Move logic from getSpecAttackMaxHit to _getMonsterMaxHit, as combo effects persist beyond the special attack which grants them)
Line 345: Line 345:
function p.getSpecAttackMaxHit(specAttack, normalMaxHit, monster)
function p.getSpecAttackMaxHit(specAttack, normalMaxHit, monster)
local bestHit = 0
local bestHit = 0
local dmgAdjust = { ["percent"] = 100, ["flat"] = 0 }
-- Check effects that apply pre or on hit for damage modifiers
local dmgMods = {
-- List of modifiers which affect damage dealt, and whether they are percentage or flat adjustments
["increasedMaxHitPercent"] = { type = 'percent', mult = 1 },
["increasedMeleeMaxHit"] = { type = 'percent', mult = 1 },
["increasedRangedMaxHit"] = { type = 'percent', mult = 1 },
["increasedMagicMaxHit"] = { type = 'percent', mult = 1 },
["increasedMeleeMaxHitFlat"] = { type = 'flat', mult = 1 },
["increasedRangedMaxHitFlat"] = { type = 'flat', mult = 1 },
["increasedMagicMaxHitFlat"] = { type = 'flat', mult = 1 },
["increasedRage"] = { type = 'percent', mult = 2, maxStacks = 10 }
}
local effectKeys = { 'prehitEffects', 'onhitEffects' }
for i, effectKey in ipairs(effectKeys) do
if type(specAttack[effectKey]) == 'table' then
for j, effect in ipairs(specAttack[effectKey]) do
local countsOnPlayer = (effect.countsOn == nil or effect.countsOn == 'Attacker')
if countsOnPlayer and type(effect.modifiers) == 'table' then
for modName, modMagnitude in pairs(effect.modifiers) do
local mod = dmgMods[modName]
if mod ~= nil then
-- The modifier is one which affects damage dealt
local maxStacks = mod.maxStacks or effect.maxStacks or 1
dmgAdjust[mod.type] = dmgAdjust[mod.type] + modMagnitude * mod.mult * maxStacks
end
end
end
end
end
end
-- Check monster passives for modifiers which affect damage dealt
if monster ~= nil and type(monster.passives) ~= nil then
for i, passiveID in ipairs(monster.passives) do
local passive = p.getPassiveByID(passiveID)
if passive ~= nil and type(passive.modifiers) == 'table' then
for modName, modMagnitude in pairs(passive.modifiers) do
local mod = dmgMods[modName]
if mod ~= nil then
-- The modifier is one which affects damage dealt
local maxStacks = mod.maxStacks or 1
dmgAdjust[mod.type] = dmgAdjust[mod.type] + modMagnitude * mod.mult * maxStacks
end
end
end
end
end
for i, dmg in pairs(specAttack.damage) do
for i, dmg in pairs(specAttack.damage) do
Line 432: Line 385:
end
end
end
end
return math.floor(bestHit * dmgAdjust.percent / 100) + dmgAdjust.flat
return bestHit
end
end


Line 457: Line 410:
elseif type(doStuns) == 'string' then
elseif type(doStuns) == 'string' then
doStuns = string.upper(doStuns) == 'TRUE'
doStuns = string.upper(doStuns) == 'TRUE'
end
local dmgAdjust = { ["percent"] = 100, ["flat"] = 0 }
-- Check passives & effects that apply pre or on hit for damage modifiers
local dmgMods = {
-- List of modifiers which affect damage dealt, and whether they are percentage or flat adjustments
["increasedMaxHitPercent"] = { type = 'percent', mult = 1 },
["increasedMeleeMaxHit"] = { type = 'percent', mult = 1 },
["increasedRangedMaxHit"] = { type = 'percent', mult = 1 },
["increasedMagicMaxHit"] = { type = 'percent', mult = 1 },
["increasedMeleeMaxHitFlat"] = { type = 'flat', mult = 1 },
["increasedRangedMaxHitFlat"] = { type = 'flat', mult = 1 },
["increasedMagicMaxHitFlat"] = { type = 'flat', mult = 1 },
["increasedRage"] = { type = 'percent', mult = 2, maxStacks = 10 }
}
local effectKeys = { 'prehitEffects', 'onhitEffects' }
-- Check monster passives for modifiers which affect damage dealt
if monster ~= nil and type(monster.passives) ~= nil then
for i, passiveID in ipairs(monster.passives) do
local passive = p.getPassiveByID(passiveID)
if passive ~= nil and type(passive.modifiers) == 'table' then
for modName, modMagnitude in pairs(passive.modifiers) do
local mod = dmgMods[modName]
if mod ~= nil then
-- The modifier is one which affects damage dealt
local maxStacks = mod.maxStacks or 1
dmgAdjust[mod.type] = dmgAdjust[mod.type] + modMagnitude * mod.mult * maxStacks
end
end
end
end
end
end


Line 468: Line 452:
for i, specAttackID in pairs(monster.specialAttacks) do
for i, specAttackID in pairs(monster.specialAttacks) do
             local specAttack = GameData.getEntityByID('attacks', specAttackID)
             local specAttack = GameData.getEntityByID('attacks', specAttackID)
-- Check for pre or on hit effects for modifiers which affect damage dealt
for i, effectKey in ipairs(effectKeys) do
if type(specAttack[effectKey]) == 'table' then
for j, effect in ipairs(specAttack[effectKey]) do
local countsOnPlayer = (effect.countsOn == nil or effect.countsOn == 'Attacker')
if countsOnPlayer and type(effect.modifiers) == 'table' then
for modName, modMagnitude in pairs(effect.modifiers) do
local mod = dmgMods[modName]
if mod ~= nil then
-- The modifier is one which affects damage dealt
local maxStacks = mod.maxStacks or effect.maxStacks or 1
dmgAdjust[mod.type] = dmgAdjust[mod.type] + modMagnitude * mod.mult * maxStacks
end
end
end
end
end
end
if monster.overrideSpecialChances ~= nil then
if monster.overrideSpecialChances ~= nil then
normalChance = normalChance - monster.overrideSpecialChances[i]
normalChance = normalChance - monster.overrideSpecialChances[i]
Line 488: Line 491:
--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 and not hasActiveBuffSpec then normalMaxHit = 0 end
if normalChance == 0 and not hasActiveBuffSpec then normalMaxHit = 0 end
return math.floor(math.max(specialMaxHit, normalMaxHit) * damageMultiplier)
local maxHit = math.floor(math.max(specialMaxHit, normalMaxHit) * dmgAdjust.percent / 100) + dmgAdjust.flat
return math.floor(maxHit * damageMultiplier)
end
end