12,787
edits
(getMonsterAttacks: Include normal attack damage when a special attack deals normal damage, even if the normal attack chance is 0%) |
(Move logic from getSpecAttackMaxHit to _getMonsterMaxHit, as combo effects persist beyond the special attack which grants them) |
||
(One intermediate revision by the same user not shown) | |||
Line 343: | Line 343: | ||
end | end | ||
function p.getSpecAttackMaxHit(specAttack, normalMaxHit, | function p.getSpecAttackMaxHit(specAttack, normalMaxHit, monster) | ||
local bestHit = 0 | local bestHit = 0 | ||
for i, dmg in pairs(specAttack.damage) do | for i, dmg in pairs(specAttack.damage) do | ||
local thisHit = 0 | local thisHit = 0 | ||
Line 370: | Line 371: | ||
thisHit = normalMaxHit * 1.35 | thisHit = normalMaxHit * 1.35 | ||
elseif dmg.maxRoll == "MaxHitDR" then | elseif dmg.maxRoll == "MaxHitDR" then | ||
local monsterDR = 0 | |||
if monster ~= nil then | |||
monsterDR = p._getMonsterStat(monster, 'damageReduction') | |||
end | |||
thisHit = normalMaxHit * dmg.maxPercent * 0.01 * (1 + monsterDR * 0.01) | thisHit = normalMaxHit * dmg.maxPercent * 0.01 * (1 + monsterDR * 0.01) | ||
elseif Shared.contains({'Bleeding', 'Poisoned'}, dmg.maxRoll) then | elseif Shared.contains({'Bleeding', 'Poisoned'}, dmg.maxRoll) then | ||
Line 405: | 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 416: | 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 421: | Line 476: | ||
normalChance = normalChance - specAttack.defaultChance | normalChance = normalChance - specAttack.defaultChance | ||
end | end | ||
local thisMax = p.getSpecAttackMaxHit(specAttack, normalMaxHit, | local thisMax = p.getSpecAttackMaxHit(specAttack, normalMaxHit, monster) | ||
if not canStun and p.canSpecAttackApplyEffect(specAttack, 'Stun') then canStun = true end | if not canStun and p.canSpecAttackApplyEffect(specAttack, 'Stun') then canStun = true end | ||
if not canSleep and p.canSpecAttackApplyEffect(specAttack, 'Sleep') then canSleep = true end | if not canSleep and p.canSpecAttackApplyEffect(specAttack, 'Sleep') then canSleep = true end | ||
Line 436: | 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 | ||
local maxHit = math.floor(math.max(specialMaxHit, normalMaxHit) * dmgAdjust.percent / 100) + dmgAdjust.flat | |||
return math.floor(maxHit * damageMultiplier) | |||
end | end | ||