Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions spec/System/TestDebuffs_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
describe("TestAilments", function()
before_each(function()
newBuild()
end)

teardown(function()
-- newBuild() takes care of resetting everything in setup()
end)

it("correctly applies effects dependent on 'Condition:Slowed'", function()
build.skillsTab:PasteSocketGroup("Chaos Bolt 1/0 1\n")
runCallback("OnFrame")

local defaultDmg = build.calcsTab.mainOutput.TotalDPS
assert.True(defaultDmg > 0, "build should deal damage")

build.configTab.input.customMods = "100% increased damage against slowed enemies"
build.configTab:BuildModList()
runCallback("OnFrame")

-- no effect yet
local nonSlowedDmg = build.calcsTab.mainOutput.TotalDPS
assert.are.equals(nonSlowedDmg, defaultDmg, "damage should be unchanged until enemy is slowed")

-- action speed
build.configTab.input.customMods = [[
100% increased damage against slowed enemies
Nearby enemies have 10% reduced action speed
]]

build.configTab:BuildModList()
runCallback("OnFrame")
local actionSlowedDmg = build.calcsTab.mainOutput.TotalDPS
assert.True(actionSlowedDmg > nonSlowedDmg, "damage should be higher vs. reduced action speed")

-- movement speed
build.configTab.input.customMods = [[
100% increased damage against slowed enemies
Nearby enemies have 10% reduced movement speed
]]

build.configTab:BuildModList()
runCallback("OnFrame")
local movementSlowedDmg = build.calcsTab.mainOutput.TotalDPS
assert.True(movementSlowedDmg > nonSlowedDmg, "damage should be higher vs. reduced movement speed")

-- specific slowing debuffs checks
-- NOTE: there might be more conditions that should be checked here, feel free to add more
for _, debuff in ipairs({"chilled", "maimed", "hindered"}) do
build.configTab.input.customMods = [[
100% increased damage against slowed enemies
nearby enemies are ]] .. debuff .. [[
]]

build.configTab:BuildModList()
runCallback("OnFrame")
local debuffSlowedDmg = build.calcsTab.mainOutput.TotalDPS
assert.True(debuffSlowedDmg > nonSlowedDmg, "damage should be higher vs. " .. debuff .. " enemies")
end

-- temporal chains curse
build.configTab.input.customMods = [[
100% increased damage against slowed enemies
]]
build.skillsTab:PasteSocketGroup("Temporal Chains 20/0 1\n")
build.configTab:BuildModList()
runCallback("OnFrame")
local temporalChainsSlowedDmg = build.calcsTab.mainOutput.TotalDPS
assert.True(temporalChainsSlowedDmg > nonSlowedDmg, "damage should be higher with Temporal Chains curse")
end)
end)
17 changes: 17 additions & 0 deletions src/Classes/ModStore.lua
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,23 @@ function ModStoreClass:SumPositiveValues(modType, cfg, modName, ...)
return total
end

--- Returns the value of all negative modifiers to a mod added together, ignoring any negative modifiers.
--- Works by creating a table using Tabulate and then filtering for negative values.
---
--- @param modType string # the mod type for which we want to create the table, e.g. "INC" or "MORE"
--- @param cfg table | nil # passed configuration, may be nil
--- @param modName string # the name of the mod for which we want to create the table, e.g. "FlaskRecoveryRate", "ActionSpeed", ...
function ModStoreClass:SumNegativeValues(modType, cfg, modName, ...)
local total = 0
local modTable = self:Tabulate(modType, cfg, modName)
for i = 1, #modTable do
if modTable[i].value < 0 then
total = total + modTable[i].value
end
end
return total
end

function ModStoreClass:More(cfg, ...)
local flags, keywordFlags = 0, 0
local source
Expand Down
6 changes: 3 additions & 3 deletions src/Data/ModCache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2636,7 +2636,7 @@ c["35% increased Elemental Ailment Threshold"]={{[1]={flags=0,keywordFlags=0,nam
c["35% increased Flask Life Recovery rate"]={{[1]={flags=0,keywordFlags=0,name="FlaskLifeRecoveryRate",type="INC",value=35}},nil}
c["35% increased Freeze Buildup"]={{[1]={flags=0,keywordFlags=0,name="EnemyFreezeBuildup",type="INC",value=35}},nil}
c["35% increased Life and Mana Recovery from Flasks"]={{[1]={flags=0,keywordFlags=0,name="FlaskLifeRecovery",type="INC",value=35},[2]={flags=0,keywordFlags=0,name="FlaskManaRecovery",type="INC",value=35}},nil}
c["35% increased Magnitude of Ignite against Poisoned enemies"]={{}," Magnitude of Ignite "}
c["35% increased Magnitude of Ignite against Poisoned enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Poisoned"},flags=0,keywordFlags=8388608,name="AilmentMagnitude",type="INC",value=35}},nil}
c["35% increased Mana Regeneration Rate"]={{[1]={flags=0,keywordFlags=0,name="ManaRegen",type="INC",value=35}},nil}
c["35% increased Mana Regeneration Rate while stationary"]={{[1]={[1]={type="Condition",var="Stationary"},flags=0,keywordFlags=0,name="ManaRegen",type="INC",value=35}},nil}
c["35% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=35}},nil}
Expand Down Expand Up @@ -2757,7 +2757,7 @@ c["40% increased Damage with Bow Skills"]={{[1]={flags=0,keywordFlags=1024,name=
c["40% increased Damage with Hits against Ignited Enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Ignited"},flags=0,keywordFlags=262144,name="Damage",type="INC",value=40}},nil}
c["40% increased Damage with Two Handed Weapons"]={{[1]={flags=34359738372,keywordFlags=0,name="Damage",type="INC",value=40}},nil}
c["40% increased Damage with Warcries"]={{[1]={flags=0,keywordFlags=4,name="Damage",type="INC",value=40}},nil}
c["40% increased Duration of Poisons you inflict against Slowed Enemies"]={{[1]={flags=0,keywordFlags=0,name="EnemyPoisonDuration",type="INC",value=40}}," against Slowed Enemies "}
c["40% increased Duration of Poisons you inflict against Slowed Enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Slowed"},flags=0,keywordFlags=0,name="EnemyPoisonDuration",type="INC",value=40}},nil}
c["40% increased Electrocute Buildup"]={{[1]={flags=0,keywordFlags=0,name="EnemyElectrocuteBuildup",type="INC",value=40}},nil}
c["40% increased Elemental Ailment Application if you have Shapeshifted to an Animal form Recently"]={{}," Elemental Ailment Application "}
c["40% increased Elemental Ailment Threshold"]={{[1]={flags=0,keywordFlags=0,name="AilmentThreshold",type="INC",value=40}},nil}
Expand Down Expand Up @@ -3101,7 +3101,7 @@ c["50% reduced Evasion Rating"]={{[1]={flags=0,keywordFlags=0,name="Evasion",typ
c["50% reduced Freeze Duration on you"]={{[1]={flags=0,keywordFlags=0,name="SelfFreezeDuration",type="INC",value=-50}},nil}
c["50% reduced Ignite Duration on Enemies"]={{[1]={flags=0,keywordFlags=0,name="EnemyIgniteDuration",type="INC",value=-50}},nil}
c["50% reduced Ignite Duration on you"]={{[1]={flags=0,keywordFlags=0,name="SelfIgniteDuration",type="INC",value=-50}},nil}
c["50% reduced Magnitude of Bleeding on You"]={{}," Magnitude of Bleeding on You "}
c["50% reduced Magnitude of Bleeding on You"]={{[1]={flags=0,keywordFlags=0,name="SelfBleedEffect",type="INC",value=-50}},nil}
c["50% reduced Magnitude of Ignite on you"]={{[1]={flags=0,keywordFlags=0,name="SelfIgniteEffect",type="INC",value=-50}},nil}
c["50% reduced Poison Duration on you"]={{[1]={flags=0,keywordFlags=0,name="SelfPoisonDuration",type="INC",value=-50}},nil}
c["50% reduced Presence Area of Effect"]={{[1]={flags=0,keywordFlags=0,name="PresenceArea",type="INC",value=-50}},nil}
Expand Down
11 changes: 11 additions & 0 deletions src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,17 @@ local function doActorMisc(env, actor)

-- Process enemy modifiers
applyEnemyModifiers(actor)

-- Check enemy "Slowed" conditions
-- NOTE: check is done based on negative speed modifiers as the list of possible slowing effects is very large
if actor ~= env.player and actor ~= env.minion and (not modDB:Flag(nil, "UnaffectedBySlows")) then
local slowEffect = modDB:SumNegativeValues("INC", nil, "ActionSpeed") or 0
slowEffect = slowEffect + modDB:SumNegativeValues("INC", nil, "MovementSpeed") or 0
slowEffect = slowEffect + modDB:SumNegativeValues("INC", nil, "TemporalChainsActionSpeed") or 0
if slowEffect ~= 0 then
modDB:NewMod("Condition:Slowed", "FLAG", true)
end
end
end

-- Process charges
Expand Down
1 change: 1 addition & 0 deletions src/Modules/CalcSetup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function calcs.initModDB(env, modDB)
modDB:NewMod("ScorchStacksMax", "BASE", 1, "Base")
modDB:NewMod("MovementSpeed", "INC", -30, "Base", { type = "Condition", var = "Maimed" })
modDB:NewMod("Evasion", "INC", -15, "Base", { type = "Condition", var = "Maimed" })
modDB:NewMod("MovementSpeed", "INC", -30, "Base", { type = "Condition", var = "Hindered" })
modDB:NewMod("AilmentThreshold", "BASE", 50, "Base", { type = "PercentStat", stat = "Life", percent = 1 })
modDB:NewMod("PoiseThreshold", "BASE", 50, "Base", { type = "PercentStat", stat = "Life", percent = 1 })
modDB:NewMod("DamageTaken", "INC", 10, "Base", { type = "Condition", var = "Intimidated"})
Expand Down
14 changes: 13 additions & 1 deletion src/Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -777,15 +777,23 @@ local modNameList = {
["chance to ignite"] = "EnemyIgniteChance",
["to freeze, shock and ignite"] = { "EnemyFreezeChance", "EnemyShockChance", "EnemyIgniteChance" },
["flammability magnitude"] = "EnemyIgniteChance",
["magnitude of shock"] = "EnemyShockMagnitude",
["magnitude of shock you inflict"] = "EnemyShockMagnitude",
["magnitude of chill"] = "EnemyChillMagnitude",
["magnitude of chill you inflict"] = "EnemyChillMagnitude",
["magnitude of jagged ground you create"] = "EnemyJaggedGroundMagnitude",
["magnitude of bleeding"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Bleed },
["magnitude of bleeding you inflict"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Bleed },
["magnitude of ignite you inflict"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Ignite },
["magnitude of ignite"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Ignite },
["magnitude of ignite [you inflict]"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Ignite },
["ignite magnitude"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Ignite },
["bleed magnitude"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Bleed },
["magnitude of poison"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Poison },
["magnitude of poisons"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Poison },
["magnitude of poison you inflict"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Poison },
["magnitude of poisons you inflict"] = { "AilmentMagnitude", keywordFlags = KeywordFlag.Poison },
["effect of poison you inflict"] = { "AilmentEffect", keywordFlags = KeywordFlag.Poison },
["effect of poisons you inflict"] = { "AilmentEffect", keywordFlags = KeywordFlag.Poison },
["magnitude of ailments"] = "AilmentMagnitude",
["magnitude of ailments you inflict"] = "AilmentMagnitude",
["magnitude of damaging ailments you inflict"] = { "AilmentMagnitude", keywordFlags = bor(KeywordFlag.Poison, KeywordFlag.Bleed, KeywordFlag.Ignite) },
Expand Down Expand Up @@ -850,6 +858,7 @@ local modNameList = {
["bleed duration on you"] = "SelfBleedDuration",
["bleeding duration on you"] = "SelfBleedDuration",
["duration of bleeding on you"] = "SelfBleedDuration",
["magnitude of bleeding on you"] = "SelfBleedEffect",
["to blind enemies on hit"] = { "BlindChance" },
["curse magnitudes"] = { "CurseEffect" },
["aura magnitudes"] = { "AuraEffect" },
Expand Down Expand Up @@ -2129,6 +2138,7 @@ local modTagList = {
["by s?l?a?i?n? ?shocked enemies"] = { tag = { type = "ActorCondition", actor = "enemy", var = "Shocked" } },
["against enemies further than (%d+)m"] = function(num) return { tag = { type = "MultiplierThreshold", var = "enemyDistance", threshold = num * 10 } } end,
["against enemies within (%d+) ?me?t?r?e?s?"] = function(num) return { tag = { type = "MultiplierThreshold", var = "enemyDistance", threshold = num * 10, upper = true } } end,
["against slowed enemies"] = { tag = { type = "ActorCondition", actor = "enemy", var = "Slowed" } },
-- Enemy multipliers
["per freeze, shock [ao][nr]d? ignite on enemy"] = { tag = { type = "Multiplier", var = "FreezeShockIgniteOnEnemy" } },
["per (%d+)%% chill magnitude on enemy"] = function(num) return { tag = { type = "Multiplier", var = "ChillEffect", actor = "enemy", div = num } } end,
Expand Down Expand Up @@ -6304,7 +6314,9 @@ local flagTypes = {
["no life regeneration"] = "NoLifeRegen",
["no inherent mana regeneration"] = "Condition:NoInherentManaRegen",
["hexproof"] = { name = "CurseEffectOnSelf", value = -100, type = "MORE" },
["maimed"] = "Condition:Maimed",
["hindered,? with (%d+)%% reduced movement speed"] = "Condition:Hindered",
["hindered"] = "Condition:Hindered",
["unnerved"] = "Condition:Unnerved",
["malediction"] = "HasMalediction",
}
Expand Down
Loading