* add support for 3.26 shaper of winter * add unit tests for enemy damage lessened by chill effect
1180 lines
51 KiB
Lua
1180 lines
51 KiB
Lua
describe("TestDefence", function()
|
|
before_each(function()
|
|
newBuild()
|
|
end)
|
|
|
|
teardown(function()
|
|
-- newBuild() takes care of resetting everything in setup()
|
|
end)
|
|
|
|
-- a small helper function to calculate damage taken from limited test parameters
|
|
local function takenHitFromTypeMaxHit(type, enemyDamageMulti)
|
|
return build.calcsTab.calcs.takenHitFromDamage(build.calcsTab.calcsOutput[type.."MaximumHitTaken"] * (enemyDamageMulti or 1), type, build.calcsTab.calcsEnv.player)
|
|
end
|
|
|
|
local function poolsRemainingAfterTypeMaxHit(type, enemyDamageMulti)
|
|
local _, takenDamages = takenHitFromTypeMaxHit(type, enemyDamageMulti)
|
|
return build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player)
|
|
end
|
|
|
|
-- boring part
|
|
it("no armour max hits", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
assert.are.equals(60, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(38, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(38, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(38, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(38, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
200% additional Physical Damage Reduction\n\z
|
|
"
|
|
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(240, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(240, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(240, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(240, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
200% additional Physical Damage Reduction\n\z
|
|
"
|
|
build.configTab.input.enemyPhysicalOverwhelm = 15 -- should result 75% DR
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(240, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(120, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(1200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(1200, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(1200, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(1200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(240, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(2400, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(2400, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(2400, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(2400, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(300, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
local poolsRemaining = poolsRemainingAfterTypeMaxHit("Lightning", 0.8)
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
Gain 100% of life as extra maximum energy shield\n\z
|
|
intelligence provides no bonus to energy shield\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Lightning", 0.8)
|
|
assert.are.equals(0, floor(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
end)
|
|
|
|
-- a small helper function to calculate damage taken from limited test parameters
|
|
local function takenHitFromTypeMaxHit(type, enemyDamageMulti)
|
|
return build.calcsTab.calcs.takenHitFromDamage(build.calcsTab.calcsOutput[type.."MaximumHitTaken"] * (enemyDamageMulti or 1), type, build.calcsTab.calcsEnv.player)
|
|
end
|
|
|
|
it("progenesis and petrified blood", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
-- Petrified blood
|
|
build.skillsTab:PasteSocketGroup("\z
|
|
Petrified Blood 20/0 Default 1\n\z
|
|
Arrogance 21/0 Default 1\n\z
|
|
") -- 50% petrified effect, when exactly half of the life is reserved, should make the life pool be equivalent to no petrified effect and full life.
|
|
build.skillsTab:ProcessSocketGroup(build.skillsTab.socketGroupList[1])
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
40% increased reservation efficiency\n\z
|
|
25% increased effect of buffs on you\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(300, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
build.skillsTab.socketGroupList = {}
|
|
|
|
build.skillsTab:PasteSocketGroup("\z
|
|
Petrified Blood 20/0 Default 1\n\z
|
|
Arrogance 21/0 Default 1\n\z
|
|
")
|
|
build.skillsTab:ProcessSocketGroup(build.skillsTab.socketGroupList[1])
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
100% less intelligence\n\z
|
|
+60 to maximum energy shield\n\z
|
|
40% increased reservation efficiency\n\z
|
|
25% increased effect of buffs on you\n\z
|
|
" -- petrified blood should not interact with pools other than life.
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(3000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
build.skillsTab.socketGroupList = {}
|
|
|
|
build.skillsTab:PasteSocketGroup("\z
|
|
Petrified Blood 20/0 Default 1\n\z
|
|
") -- 80% petrified effect, starting from full life, should make the life pool be equivalent to 0.5 * life (unprotected upper half) and then 5 * 0.5 * life (protected lower half), making it 3* bigger in total
|
|
build.skillsTab:ProcessSocketGroup(build.skillsTab.socketGroupList[1])
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
100% increased effect of buffs on you\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(900, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
build.skillsTab.socketGroupList = {}
|
|
|
|
-- Progenesis
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
When Hit during effect, 50% of Life loss from Damage taken occurs over 4 seconds instead\n\z
|
|
" -- 50% progenesis should just simply double the life pool
|
|
build.configTab.input.conditionUsingFlask = true
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
When Hit during effect, 50% of Life loss from Damage taken occurs over 4 seconds instead\n\z
|
|
100% less intelligence\n\z
|
|
+60 to maximum energy shield\n\z
|
|
" -- progenesis should not interact with pools other than life.
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(900, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
-- Progenesis + petrified blood
|
|
build.skillsTab:PasteSocketGroup("\z
|
|
Petrified Blood 20/0 Default 1\n\z
|
|
Arrogance 21/0 Default 1\n\z
|
|
")
|
|
build.skillsTab:ProcessSocketGroup(build.skillsTab.socketGroupList[1])
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
When Hit during effect, 50% of Life loss from Damage taken occurs over 4 seconds instead\n\z
|
|
40% increased reservation efficiency\n\z
|
|
25% increased effect of buffs on you\n\z
|
|
" -- With half of life reserved, both effects are active and multiplicative with each other, making the effective life pool 4 * half life = 2 * life (or same as no petrified, no reserve and 50% progenesis)
|
|
build.configTab.input.conditionUsingFlask = true
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(600, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(6000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
build.skillsTab.socketGroupList = {}
|
|
|
|
build.skillsTab:PasteSocketGroup("\z
|
|
Petrified Blood 20/0 Default 1\n\z
|
|
")
|
|
build.skillsTab:ProcessSocketGroup(build.skillsTab.socketGroupList[1])
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
When Hit during effect, 50% of Life loss from Damage taken occurs over 4 seconds instead\n\z
|
|
25% increased effect of buffs on you\n\z
|
|
" -- With no life reserved, progenesis first doubles the pool of life above low, then both progenesis and petrified quadruple the pool of life below low, so effective pool is 3 * life
|
|
build.configTab.input.conditionUsingFlask = true
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(900, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(9000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
build.skillsTab.socketGroupList = {}
|
|
|
|
build.skillsTab:PasteSocketGroup("\z
|
|
Petrified Blood 20/0 Default 1\n\z
|
|
")
|
|
build.skillsTab:ProcessSocketGroup(build.skillsTab.socketGroupList[1])
|
|
build.configTab.input.customMods = "\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
Nearby enemies deal 20% less damage\n\z
|
|
When Hit during effect, 60% of Life loss from Damage taken occurs over 4 seconds instead\n\z
|
|
100% less intelligence\n\z
|
|
+60 to maximum energy shield\n\z
|
|
" -- wonkier numbers to test the pool reduction function
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1300, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(13000, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(13000, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(13000, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(10000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
local _, takenDamages = takenHitFromTypeMaxHit("Fire", 0.8)
|
|
local poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player)
|
|
assert.are.equals(0, poolsRemaining.EnergyShield)
|
|
assert.are.equals(0, poolsRemaining.Life)
|
|
assert.are.equals(120, poolsRemaining.LifeLossLostOverTime)
|
|
assert.are.equals(20, poolsRemaining.LifeBelowHalfLossLostOverTime)
|
|
|
|
build.skillsTab:PasteSocketGroup("\z
|
|
Petrified Blood 20/0 Default 1\n\z
|
|
")
|
|
build.skillsTab:ProcessSocketGroup(build.skillsTab.socketGroupList[1])
|
|
build.configTab.input.customMods = "\z
|
|
+1950 to life\n\z
|
|
+2960 to mana\n\z
|
|
+3000 to energy shield\n\z
|
|
100% less attributes\n\z
|
|
100% less mana reserved\n\z
|
|
+60% to all resistances\n\z
|
|
chaos damage does not bypass energy shield\n\z
|
|
mind over matter\n\z
|
|
eldritch battery\n\z
|
|
10% of lightning damage is taken from mana before life\n\z
|
|
chaos damage is taken from mana before life\n\z
|
|
When Hit during effect, 50% of Life loss from Damage taken occurs over 4 seconds instead\n\z
|
|
25% increased effect of buffs on you\n\z
|
|
"
|
|
build.configTab.input.conditionUsingFlask = true
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
_, takenDamages = takenHitFromTypeMaxHit("Fire")
|
|
poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player)
|
|
assert.are.equals(0, poolsRemaining.Life)
|
|
assert.are.equals(0, poolsRemaining.EnergyShield)
|
|
assert.is.not_false(poolsRemaining.Mana > 0)
|
|
|
|
_, takenDamages = takenHitFromTypeMaxHit("Lightning")
|
|
poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player)
|
|
assert.are.equals(0, poolsRemaining.Life)
|
|
assert.are.equals(0, poolsRemaining.EnergyShield)
|
|
assert.are.equals(0, poolsRemaining.Mana)
|
|
|
|
_, takenDamages = takenHitFromTypeMaxHit("Chaos")
|
|
poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player)
|
|
assert.are.equals(0, poolsRemaining.Life)
|
|
assert.are.equals(0, poolsRemaining.EnergyShield)
|
|
assert.are.equals(0, poolsRemaining.Mana)
|
|
|
|
build.skillsTab.socketGroupList = {}
|
|
end)
|
|
|
|
-- fun part
|
|
it("armoured max hits", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+10000 to armour\n\z
|
|
" -- hit of 2000 on 10000 armour results in 50% DR which reduces the damage to 1000 - total HP
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Physical"))
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+100000 to armour\n\z
|
|
" -- hit of 5000 on 100000 armour results in 80% DR which reduces the damage to 1000 - total HP
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Physical"))
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+1000000000 to armour\n\z
|
|
" -- 90% DR cap
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Physical"))
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+1000000000 to armour\n\z
|
|
" -- 90% DR cap
|
|
build.configTab.input.enemyPhysicalOverwhelm = 15 -- should result 75% DR
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Physical"))
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ColdMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+10000 to armour\n\z
|
|
+60% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
" -- with no resistances results should be same as physical
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1000, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Fire"))
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Cold"))
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Lightning"))
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
" -- max hit should be 4000
|
|
-- [max] [res] [armour] [armour] [max] [res]
|
|
-- 4000 * 0.5 * (1 - 10000 / (10000 + 5 * 4000 * 0.5)) = 1000
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1000, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Fire"))
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Cold"))
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Lightning"))
|
|
assert.are.equals(625, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
50% less damage taken\n\z
|
|
" -- max hit should be 6472
|
|
-- [max] [res] [armour] [armour] [max] [res] [less]
|
|
-- 6472 * 0.5 * (1 - 10000 / (10000 + 5 * 6472 * 0.5)) * 0.5 = 1000
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(2000, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Fire"))
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Cold"))
|
|
assert.are.equals(1000, takenHitFromTypeMaxHit("Lightning"))
|
|
assert.are.equals(1250, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
end)
|
|
|
|
describe("Energy shield increased by spell block chance", function()
|
|
|
|
it("energy shield increased by spell block chance if corresponding 'maximum es' flag is present", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
build.configTab.input.customMods = "\z
|
|
You have no intelligence\n\z
|
|
100 Energy shield \n\z
|
|
maximum energy shield is increased by chance to block spell damage\n\z
|
|
50% chance to block spell damage\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
assert.are.equals(0, build.calcsTab.calcsOutput.SpellBlockChanceOverCap )
|
|
assert.are.equals(50, build.calcsTab.calcsOutput.SpellBlockChance)
|
|
assert.are.equals(150, build.calcsTab.calcsOutput.EnergyShield)
|
|
end)
|
|
|
|
it("energy shield increased by spell block chance if corresponding 'maximum es' flag is present should be capped to max block", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
|
|
build.configTab.input.customMods = "\z
|
|
You have no intelligence\n\z
|
|
100 Energy shield \n\z
|
|
maximum energy shield is increased by chance to block spell damage\n\z
|
|
100% chance to block spell damage\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
assert.are.equals(25, build.calcsTab.calcsOutput.SpellBlockChanceOverCap )
|
|
assert.are.equals(75, build.calcsTab.calcsOutput.SpellBlockChance)
|
|
assert.are.equals(175, build.calcsTab.calcsOutput.EnergyShield)
|
|
end)
|
|
|
|
end)
|
|
|
|
describe("enemy damage lessened by half of chill effect", function ()
|
|
it("enemy damage lessened by half of chill effect if the corresponding conditions are fulfilled", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
build.configTab.input.conditionEnemyChilled = true
|
|
-- default max chill effect
|
|
build.configTab.input.conditionEnemyChilledEffect = 30
|
|
build.configTab.input.customMods = "\z
|
|
enemies chilled by your hits lessen their damage dealt by half of chill effect\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- 15% less since it's half of current chill effect
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.PhysicalEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.LightningEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.ColdEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.FireEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.ChaosEnemyDamageMult)
|
|
end)
|
|
|
|
it("enemy damage is not lessened if the enemy is not chilled", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
build.configTab.input.customMods = "\z
|
|
enemies chilled by your hits lessen their damage dealt by half of chill effect\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
assert.are.equals(1, build.calcsTab.calcsOutput.PhysicalEnemyDamageMult)
|
|
assert.are.equals(1, build.calcsTab.calcsOutput.LightningEnemyDamageMult)
|
|
assert.are.equals(1, build.calcsTab.calcsOutput.ColdEnemyDamageMult)
|
|
assert.are.equals(1, build.calcsTab.calcsOutput.FireEnemyDamageMult)
|
|
assert.are.equals(1, build.calcsTab.calcsOutput.ChaosEnemyDamageMult)
|
|
end)
|
|
|
|
it("lessened enemy damage respects chill cap", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
build.configTab.input.conditionEnemyChilled = true
|
|
-- default max chill effect is 30%, so this shouldn't affect the resulting enemy damage multiplier beyond the cap
|
|
build.configTab.input.conditionEnemyChilledEffect = 100
|
|
build.configTab.input.customMods = "\z
|
|
enemies chilled by your hits lessen their damage dealt by half of chill effect\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.PhysicalEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.LightningEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.ColdEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.FireEnemyDamageMult)
|
|
assert.are.equals(0.85, build.calcsTab.calcsOutput.ChaosEnemyDamageMult)
|
|
end)
|
|
end)
|
|
|
|
local function withinTenPercent(value, otherValue)
|
|
local ratio = otherValue / value
|
|
return 0.9 < ratio and ratio < 1.1
|
|
end
|
|
it("damage conversion max hits", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
50% of physical damage taken as fire\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Physical")))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+200 to all resistances\n\z
|
|
+200 to all maximum resistances\n\z
|
|
50% reduced damage taken\n\z
|
|
50% less damage taken\n\z
|
|
50% of physical damage taken as fire\n\z
|
|
50% of cold damage taken as fire\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Physical")))
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Cold")))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
50% of physical damage taken as fire\n\z
|
|
50% of cold damage taken as fire\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Physical")))
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Cold")))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
50% of physical damage taken as fire\n\z
|
|
50% of cold damage taken as fire\n\z
|
|
50% less fire damage taken\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Physical")))
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Cold")))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+10000 to armour\n\z
|
|
+110% to fire resistance\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of cold damage taken as fire\n\z
|
|
50% of lightning damage taken as fire\n\z
|
|
50% less fire damage taken\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Physical")))
|
|
assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Cold")))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+99 to energy shield\n\z
|
|
100% less attributes\n\z
|
|
+60% to all elemental resistances\n\z
|
|
25% of Elemental Damage from Hits taken as Chaos Damage\n\z
|
|
Chaos Inoculation\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
local poolsRemaining = poolsRemainingAfterTypeMaxHit("Cold")
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
end)
|
|
|
|
it("damage conversion to different size pools", function()
|
|
-- conversion into a smaller pool
|
|
build.configTab.input.customMods = "\z
|
|
+40 to maximum life\n\z
|
|
+950 to mana\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of Lightning Damage is taken from Mana before Life\n\z
|
|
10% of lightning damage taken as cold damage\n\z
|
|
" -- Small amount of conversion into a smaller pool leads to the higher pool damage type (lightning) draining it's own excess pool (mana), and then joining back on the shared pools (life)
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
local poolsRemaining = poolsRemainingAfterTypeMaxHit("Lightning")
|
|
assert.are.equals(0, floor(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+40 to maximum life\n\z
|
|
+950 to mana\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of Lightning Damage is taken from Mana before Life\n\z
|
|
20% of lightning damage taken as cold damage\n\z
|
|
" -- This is a case where cold damage drains the whole life pool and lightning damage drains the entire mana pool, leaving nothing
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Lightning")
|
|
assert.are.equals(0, floor(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+40 to maximum life\n\z
|
|
+1950 to mana\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of Lightning Damage is taken from Mana before Life\n\z
|
|
20% of lightning damage taken as cold damage\n\z
|
|
" -- Any extra mana in this case will not help and be left over after death, since life hits 0 from the cold damage alone
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Lightning")
|
|
assert.are.equals(1000, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- conversion into a bigger pool
|
|
build.configTab.input.customMods = "\z
|
|
+40 to maximum life\n\z
|
|
+950 to mana\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of Lightning Damage is taken from Mana before Life\n\z
|
|
90% of cold damage taken as lightning damage\n\z
|
|
" -- With inverted conversion amounts the behaviour of converting into a bigger pool should be exactly the same as converting into a lower one.
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Cold")
|
|
assert.are.equals(0, floor(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+40 to maximum life\n\z
|
|
+950 to mana\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of Lightning Damage is taken from Mana before Life\n\z
|
|
80% of cold damage taken as lightning damage\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Cold")
|
|
assert.are.equals(0, floor(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+40 to maximum life\n\z
|
|
+1950 to mana\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of Lightning Damage is taken from Mana before Life\n\z
|
|
80% of cold damage taken as lightning damage\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Cold")
|
|
assert.are.equals(1000, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
build.configTab.input.customMods = "\z
|
|
+940 to maximum life\n\z
|
|
+950 to mana\n\z
|
|
+1000 to energy shield\n\z
|
|
+10000 to armour\n\z
|
|
+110% to all elemental resistances\n\z
|
|
Armour applies to Fire, Cold and Lightning Damage taken from Hits instead of Physical Damage\n\z
|
|
100% of Lightning Damage is taken from Mana before Life\n\z
|
|
80% of cold damage taken as lightning damage\n\z
|
|
50% of fire damage taken as chaos damage\n\z
|
|
"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Cold")
|
|
assert.are.equals(0, floor(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.not_false(0 < floor(poolsRemaining.EnergyShield))
|
|
assert.are.equals(1000, floor(poolsRemaining.Mana))
|
|
assert.are.not_false(1 >= floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
end)
|
|
|
|
it("energy shield bypass tests #pet", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
-- Mastery
|
|
build.configTab.input.customMods = [[
|
|
+40 to maximum life
|
|
+200 to energy shield
|
|
50% of chaos damage taken does not bypass energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
local poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(100, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
assert.are.equals(300, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
-- Negative overrides positive
|
|
build.configTab.input.customMods = [[
|
|
+40 to maximum life
|
|
+100 to energy shield
|
|
physical damage taken bypasses energy shield
|
|
Chaos damage does not bypass energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(100, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Physical")
|
|
assert.are.equals(100, floor(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(0, floor(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
-- Chaos damage should still bypass
|
|
build.configTab.input.customMods = build.configTab.input.customMods .. "\nAll damage taken bypasses energy shield"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(100, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken)
|
|
assert.are.equals(100, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(100, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
|
|
-- Make sure we can't reach over 100% bypass
|
|
build.configTab.input.customMods = [[
|
|
+40 to maximum life
|
|
+100 to energy shield
|
|
Chaos damage does not bypass energy shield
|
|
50% of chaos damage taken does not bypass energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
-- Chaos damage should still bypass
|
|
build.configTab.input.customMods = build.configTab.input.customMods .. "\nAll damage taken bypasses energy shield"
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(100, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(100, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Physical")
|
|
assert.are.equals(100, floor(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(100, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- Bypass + MoM
|
|
build.configTab.input.customMods = [[
|
|
+40 to maximum life
|
|
+50 to mana
|
|
+200 to energy shield
|
|
50% of non-chaos damage taken bypasses energy shield
|
|
50% of chaos damage taken does not bypass energy shield
|
|
50% of Lightning Damage is taken from Mana before Life
|
|
intelligence provides no bonus to energy shield
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(400, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(100, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(100, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Lightning")
|
|
assert.are.equals(0, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
build.configTab.input.customMods = [[
|
|
+40 to maximum life
|
|
+150 to mana
|
|
+300 to energy shield
|
|
50% of non-chaos damage taken bypasses energy shield
|
|
50% of chaos damage taken does not bypass energy shield
|
|
50% of Lightning Damage is taken from Mana before Life
|
|
intelligence provides no bonus to energy shield
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(400, build.calcsTab.calcsOutput.LightningMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(200, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(200, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Lightning")
|
|
assert.are.equals(100, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(100, floor(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
end)
|
|
|
|
it("Unbreakable + Iron Reflexes", function()
|
|
build.configTab.input.customMods = [[
|
|
you have no dexterity
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- Get the base to make this test more adaptable to changes
|
|
local baseArmour = build.calcsTab.mainOutput.Armour
|
|
local baseEvasion = build.calcsTab.mainOutput.Evasion
|
|
|
|
build.configTab.input.customMods = [[
|
|
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
|
|
you have no dexterity
|
|
]]
|
|
build.itemsTab:CreateDisplayItemFromRaw([[
|
|
New Item
|
|
Shabby Jerkin
|
|
Quality: 20
|
|
]])
|
|
build.itemsTab:AddDisplayItem()
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- Get the base + Shabby Jerkin to make this test more adaptable to changes
|
|
local ironReflexesArmour = build.calcsTab.mainOutput.Armour - baseArmour - baseEvasion
|
|
|
|
print("build.calcsTab.mainOutput.Armour:" .. build.calcsTab.mainOutput.Armour)
|
|
|
|
build.configTab.input.customMods = [[
|
|
Armour from Equipped Body Armour is doubled
|
|
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
|
|
you have no dexterity
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- Evasion from Body Armour is converted to Armour before being doubled
|
|
assert.are.equals(2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
|
|
|
|
build.configTab.input.customMods = [[
|
|
Armour from Equipped Body Armour is doubled
|
|
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
|
|
Gain no armour from equipped body armour
|
|
you have no dexterity
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- Only the base armour from the chest is affected.
|
|
-- Armour converted with Iron Reflexes still applies
|
|
assert.are.equals(2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
|
|
build.configTab.input.customMods = [[
|
|
Armour from Equipped Body Armour is doubled
|
|
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
|
|
Gain no armour from equipped body armour
|
|
defences from equipped body armour are doubled if it has no socketed gems
|
|
you have no dexterity
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- Oath Of Maji double defences stack with Unbreakable
|
|
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
|
|
|
|
build.configTab.input.customMods = [[
|
|
Armour from Equipped Body Armour is doubled
|
|
Armour from Equipped Body Armour is doubled
|
|
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
|
|
Gain no armour from equipped body armour
|
|
defences from equipped body armour are doubled if it has no socketed gems
|
|
you have no dexterity
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- Mod form unbreakable should apply only once
|
|
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
|
|
|
|
build.configTab.input.customMods = [[
|
|
Armour from Equipped Body Armour is doubled
|
|
Armour from Equipped Body Armour is doubled
|
|
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
|
|
Gain no armour from equipped body armour
|
|
defences from equipped body armour are doubled if it has no socketed gems
|
|
defences from equipped body armour are doubled if it has no socketed gems
|
|
you have no dexterity
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
|
|
-- Oath Of Maji should apply only once
|
|
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
|
|
end)
|
|
|
|
it("MoM + EB", function()
|
|
build.configTab.input.enemyIsBoss = "None"
|
|
-- enough mana and es, 0% and 100% bypass
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
+40 to maximum life
|
|
+1960 to mana
|
|
+2000 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
local poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(2000, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(1900, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(1900, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(2000, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- enough mana and es, 50% bypass
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
50% of non-chaos damage taken bypasses energy shield
|
|
+40 to maximum life
|
|
+1960 to mana
|
|
+2000 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(1950, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(1950, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- es bottleneck, 0% and 100% bypass
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
+40 to maximum life
|
|
+1960 to mana
|
|
+50 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(50, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(1900, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(0, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(1950, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- es bottleneck, 50% bypass
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
50% of non-chaos damage taken bypasses energy shield
|
|
+40 to maximum life
|
|
+1960 to mana
|
|
+40 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(0, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(1940, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- mana bottleneck, 0% and 100% bypass
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
+40 to maximum life
|
|
+2000 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(200, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(140, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(2000, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(1900, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(40, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- mana bottleneck, 50% bypass
|
|
-- taking 160 damage in this scenario:
|
|
-- 160 damage is split to 80 damage straight to life, 80 damage to MoM pools
|
|
-- 50% of the 80 MoM pool damage is taken by ES and 50% bypasses
|
|
-- pool of 20 mana takes 40 damage, gets depleted and the remaining damage continues on to life, for a total of 100 damage to life
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
50% of non-chaos damage taken bypasses energy shield
|
|
+40 to maximum life
|
|
-20 to mana
|
|
+2000 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(160, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(1960, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- mana+es bottleneck, 0% and 100% bypass
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
+940 to maximum life
|
|
+50 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1090, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
assert.are.equals(1040, build.calcsTab.calcsOutput.ChaosMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Chaos")
|
|
assert.are.equals(50, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(0, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
|
|
-- mana+es bottleneck, 50% bypass
|
|
build.configTab.input.customMods = [[
|
|
50% of damage is taken from mana before life
|
|
energy shield protects mana instead of life
|
|
50% of non-chaos damage taken bypasses energy shield
|
|
+940 to maximum life
|
|
+50 to energy shield
|
|
You have no intelligence
|
|
+60% to all resistances
|
|
]]
|
|
build.configTab:BuildModList()
|
|
runCallback("OnFrame")
|
|
assert.are.equals(1090, build.calcsTab.calcsOutput.FireMaximumHitTaken)
|
|
poolsRemaining = poolsRemainingAfterTypeMaxHit("Fire")
|
|
assert.are.equals(0, round(poolsRemaining.EnergyShield))
|
|
assert.are.equals(0, round(poolsRemaining.Mana))
|
|
assert.are.equals(0, floor(poolsRemaining.Life))
|
|
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
|
|
end)
|
|
end) |