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
67 changes: 62 additions & 5 deletions spec/System/TestAilments_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ describe("TestAilments", function()
-- newBuild() takes care of resetting everything in setup()
end)

local function rebuild()
build.configTab:BuildModList()
runCallback("OnFrame")
end

it("maximum shock value", function()
-- Shock Nova
build.skillsTab:PasteSocketGroup("Slot: Weapon 1\nShock Nova 4/0 1\n")
Expand All @@ -27,16 +32,68 @@ describe("TestAilments", function()
build.configTab.input.customMods = "\z
attacks have 10% chance to cause bleeding\n\z
"
build.configTab:BuildModList()
runCallback("OnFrame")
rebuild()
local badDps = build.calcsTab.mainOutput.BleedDPS

build.configTab.input.customMods = "\z
attacks have 100% chance to cause bleeding\n\z
"
build.configTab:BuildModList()
runCallback("OnFrame")
rebuild()
local goodDps = build.calcsTab.mainOutput.BleedDPS
assert.True(goodDps > badDps)
end)
end)

it("scales hit ailments with target ailment effect", function()
build.skillsTab:PasteSocketGroup("Slot: Weapon 1\nShock Nova 20/0 1\n")
build.configTab.input.customMods = "Drop Brine Ground while moving, lasting 4 seconds"
rebuild()

assert.are.equals(1, build.calcsTab.mainOutput.ShockEffectMod)

build.configTab.input.conditionEnemyOnBrineGround = true
rebuild()

assert.are.near(1.3, build.calcsTab.mainOutput.ShockEffectMod, 10 ^ -9)
end)

it("scales minion ailment duration with Barnacles", function()
build.skillsTab:PasteSocketGroup("Slot: Weapon 1\nSummon Ice Golem 20/0 1\n")
build.configTab.input.customMods = "Inflict Barnacles on nearby Enemies every second\nMinions gain 100% of Physical Damage as Extra Cold Damage"
rebuild()
local baseFreezeDurationMod = build.calcsTab.mainEnv.minion.output.FreezeDurationMod
local baseChillDuration = build.calcsTab.mainEnv.minion.output.ChillDuration

build.configTab.input.multiplierBarnacleStacks = 10
rebuild()

assert.are.near(baseChillDuration * 1.5, build.calcsTab.mainEnv.minion.output.ChillDuration, 10 ^ -9)
assert.are.near(baseFreezeDurationMod * 1.5, build.calcsTab.mainEnv.minion.output.FreezeDurationMod, 10 ^ -9)
assert.are.equals(50, build.calcsTab.mainEnv.enemyDB:Sum("BASE", nil, "PhysicalDamageConvertToCold"))
end)

it("scales chilling area duration with Barnacles", function()
build.skillsTab:PasteSocketGroup("Slot: Weapon 1\nCold Snap 20/0 1\n")
build.configTab.input.customMods = "Inflict Barnacles on nearby Enemies every second"
rebuild()

assert.are.equals(1, build.calcsTab.mainOutput.ChillDurationMod)

build.configTab.input.multiplierBarnacleStacks = 10
rebuild()

assert.are.equals(1.5, build.calcsTab.mainOutput.ChillDurationMod)
end)

it("scales guaranteed ailments with target ailment effect", function()
build.skillsTab:PasteSocketGroup("Summon Skitterbots 1/0 1\n")
build.configTab.input.customMods = "Drop Brine Ground while moving, lasting 4 seconds"
rebuild()

assert.are.equals(15, build.calcsTab.mainOutput.CurrentShock)

build.configTab.input.conditionEnemyOnBrineGround = true
rebuild()

assert.are.equals(19, build.calcsTab.mainOutput.CurrentShock)
end)
end)
4 changes: 2 additions & 2 deletions src/Data/ModCache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8423,7 +8423,7 @@ c["Does not delay Inherent Loss of Rage Regenerate 1 Rage per second for every 3
c["Does not delay Inherent Loss of Rage Skills Cost +3 Rage"]={{[1]={flags=0,keywordFlags=0,name="RageCostNoMult",type="BASE",value=3}},"Does not delay Inherent Loss of Rage "}
c["Does not inflict Mana Burn over time"]={nil,"Does not inflict Mana Burn over time "}
c["Does not inflict Mana Burn over time Inflicts Mana Burn on you when you Hit an Enemy with a Melee Weapon"]={nil,"Does not inflict Mana Burn over time Inflicts Mana Burn on you when you Hit an Enemy with a Melee Weapon "}
c["Drop Brine Ground while moving, lasting 4 seconds"]={nil,"Drop Brine Ground while moving, lasting 4 seconds "}
c["Drop Brine Ground while moving, lasting 4 seconds"]={{[1]={flags=0,keywordFlags=0,name="CanCreateBrineGround",type="FLAG",value=true}},nil}
c["Drops Scorched Ground while moving, lasting 4 seconds"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="OnScorchedGround"},flags=0,keywordFlags=0,name="ScorchBase",type="BASE",value=10}},nil}
c["Drops Shocked Ground while moving, lasting 2 seconds"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="OnShockedGround"},flags=0,keywordFlags=0,name="ShockBase",type="BASE",value=15}},nil}
c["Dual Wielding does not inherently grant chance to Block Attack Damage"]={{[1]={flags=0,keywordFlags=0,name="Condition:NoInherentBlock",type="FLAG",value=true}},nil}
Expand Down Expand Up @@ -9592,7 +9592,7 @@ c["Inflict 3 additional Poisons on the same Target when you inflict Poison with
c["Inflict 5 additional Impales on Enemies you Impale"]={nil,"Inflict 5 additional Impales on Enemies you Impale "}
c["Inflict 5 additional Impales on Enemies you Impale For 5 seconds after you Impale Enemies, they cannot be Impaled again, and Impales cannot be Called from them"]={nil,"Inflict 5 additional Impales on Enemies you Impale For 5 seconds after you Impale Enemies, they cannot be Impaled again, and Impales cannot be Called from them "}
c["Inflict 5 additional Impales on Enemies you Impale For 5 seconds after you Impale Enemies, they cannot be Impaled again, and Impales cannot be Called from them Limited to 1 Keystone Tattoo"]={nil,"Inflict 5 additional Impales on Enemies you Impale For 5 seconds after you Impale Enemies, they cannot be Impaled again, and Impales cannot be Called from them Limited to 1 Keystone Tattoo "}
c["Inflict Barnacles on nearby Enemies every second"]={nil,"Inflict Barnacles on nearby Enemies every second "}
c["Inflict Barnacles on nearby Enemies every second"]={{[1]={flags=0,keywordFlags=0,name="CanInflictBarnacles",type="FLAG",value=true}},nil}
c["Inflict Brittle on Enemies when you Block their Damage"]={nil,"Inflict Brittle on Enemies when you Block their Damage "}
c["Inflict Brittle on Enemies when you Block their Damage 67% increased Chance to Block"]={nil,"Inflict Brittle on Enemies when you Block their Damage 67% increased Chance to Block "}
c["Inflict Decay on Enemies you Curse with Hex Skills, dealing 700 Chaos Damage per Second for 8 Seconds"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Cursed"},flags=0,keywordFlags=0,name="SkillData",type="LIST",value={key="decay",merge="MAX",value=700}}},nil}
Expand Down
8 changes: 5 additions & 3 deletions src/Modules/CalcOffence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5154,8 +5154,10 @@ function calcs.offence(env, actor, activeSkill)
skillFlags.chill = true
local incChill = skillModList:Sum("INC", cfg, "EnemyChillEffect")
local moreChill = skillModList:More(cfg, "EnemyChillEffect")
output.ChillEffectMod = (1 + incChill / 100) * moreChill
output.ChillDurationMod = 1 + skillModList:Sum("INC", cfg, "EnemyChillDuration", "EnemyAilmentDuration", "EnemyElementalAilmentDuration") / 100
output.ChillEffectMod = (1 + incChill / 100) * moreChill * calcLib.mod(enemyDB, nil, "SelfChillEffect")
local incChillDuration = skillModList:Sum("INC", cfg, "EnemyChillDuration", "EnemyAilmentDuration", "EnemyElementalAilmentDuration") + enemyDB:Sum("INC", nil, "SelfChillDuration", "SelfAilmentDuration", "SelfElementalAilmentDuration")
local moreChillDuration = skillModList:More(cfg, "EnemyChillDuration", "EnemyAilmentDuration", "EnemyElementalAilmentDuration") * enemyDB:More(nil, "SelfChillDuration", "SelfAilmentDuration", "SelfElementalAilmentDuration")
output.ChillDurationMod = (1 + incChillDuration / 100) * moreChillDuration
output.ChillSourceEffect = m_min(skillModList:Override(nil, "ChillMax") or ailmentData.Chill.max, m_floor(ailmentData.Chill.default * output.ChillEffectMod))
if breakdown then
breakdown.DotChill = { }
Expand Down Expand Up @@ -5208,7 +5210,7 @@ function calcs.offence(env, actor, activeSkill)
local moreDur = skillModList:More(cfg, "Enemy"..ailment.."Duration", "EnemyElementalAilmentDuration", "EnemyAilmentDuration") * enemyDB:More(nil, "Self"..ailment.."Duration", "SelfElementalAilmentDuration", "SelfAilmentDuration")
output[ailment.."Duration"] = ailmentData[ailment].duration * (1 + incDur / 100) * moreDur * debuffDurationMult
-- Line Controls Crit Conditional for Crit Mastery
output[ailment.."EffectMod"] = calcLib.mod(skillModList, cfg, "Enemy"..ailment.."Effect")
output[ailment.."EffectMod"] = calcLib.mod(skillModList, cfg, "Enemy"..ailment.."Effect") * calcLib.mod(enemyDB, nil, "Self"..ailment.."Effect")
if breakdown then
local maximum = globalOutput["Maximum"..ailment] or ailmentData[ailment].max
local current = m_max(m_min(globalOutput["Current"..ailment] or 0, maximum), 0)
Expand Down
6 changes: 5 additions & 1 deletion src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3497,10 +3497,11 @@ function calcs.perform(env, skipEHP)
for _, value in ipairs(modDB:Tabulate("BASE", nil, ailment.."Base", ailment.."Override", ailment.."Minimum")) do
local mod = value.mod
local effect = mod.value
local scalesWithSource = mod.name == ailment.."Base" or mod.name == ailment.."Minimum"
if mod.name == ailment.."Override" then
enemyDB:NewMod("Condition:"..val.condition, "FLAG", true, mod.source)
end
if mod.name == ailment.."Base" or mod.name == ailment.."Minimum" then
if scalesWithSource then
-- If the main skill can inflict the ailment, the ailment is inflicted with a hit, and we have a node allocated that checks what our highest damage is, then
-- use the skill's ailment modifiers
-- if not, use the generic modifiers
Expand All @@ -3510,6 +3511,9 @@ function calcs.perform(env, skipEHP)
else
effect = effect * calcLib.mod(modDB, nil, "Enemy"..ailment.."Effect")
end
end
effect = effect * calcLib.mod(enemyDB, nil, "Self"..ailment.."Effect")
if scalesWithSource then
modDB:NewMod(ailment.."Override", "BASE", effect, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
if mod.name == ailment.."Minimum" then
minimum = minimum + effect
Expand Down
28 changes: 27 additions & 1 deletion src/Modules/ConfigOptions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,16 @@ Huge sets the radius to 11.
{ var = "minionConditionOnProfaneGround", type = "check", label = "Minion on Profane Ground?", ifMinionCond = "OnProfaneGround", apply = function(val, modList, enemyModList)
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("Condition:OnProfaneGround", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) })
end },
{ var = "conditionOnBrineGround", type = "check", label = "Are you on Brine Ground?", ifFlag = "CanCreateBrineGround", tooltip = "Allies on your Brine Ground gain 10% of Physical Damage as extra Cold Damage and as extra Lightning Damage", apply = function(val, modList, enemyModList)
modList:NewMod("Condition:OnBrineGround", "FLAG", true, "Config", { type = "Condition", var = "Combat" })
modList:NewMod("PhysicalDamageGainAsCold", "BASE", 10, "Config", { type = "Condition", var = "OnBrineGround" })
modList:NewMod("PhysicalDamageGainAsLightning", "BASE", 10, "Config", { type = "Condition", var = "OnBrineGround" })
end },
{ var = "minionConditionOnBrineGround", type = "check", label = "Minion on Brine Ground?", ifFlag = "CanCreateBrineGround", tooltip = "Allies on your Brine Ground gain 10% of Physical Damage as extra Cold Damage and as extra Lightning Damage", apply = function(val, modList, enemyModList)
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("Condition:OnBrineGround", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) })
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("PhysicalDamageGainAsCold", "BASE", 10, "Config", { type = "Condition", var = "OnBrineGround" }) })
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("PhysicalDamageGainAsLightning", "BASE", 10, "Config", { type = "Condition", var = "OnBrineGround" }) })
end },
{ var = "conditionOnCausticGround", type = "check", label = "Are you on Caustic Ground?", ifCond = "OnCausticGround", apply = function(val, modList, enemyModList)
modList:NewMod("Condition:OnCausticGround", "FLAG", true, "Config", { type = "Condition", var = "Combat" })
end },
Expand Down Expand Up @@ -1871,6 +1881,12 @@ Huge sets the radius to 11.
{ var = "HoarfrostStacks", type = "count", label = "^x3F6DB3Hoarfrost ^7Stacks", ifFlag = "HitsCanInflictHoarfrost", tooltip = "Amount of stacks of ^x3F6DB3Hoarfrost ^7applied to the enemy.", apply = function(val, modList, enemyModList)
enemyModList:NewMod("HoarfrostFreezeDuration", "INC", val * 20, "Config", { type = "Condition", var = "Effective" })
end },
{ var = "multiplierBarnacleStacks", type = "count", label = "^x3F6DB3Barnacle ^7Stacks", ifFlag = "CanInflictBarnacles", tooltip = "Amount of stacks of ^x3F6DB3Barnacle ^7applied to the enemy.\n\n^8(Enemies affected by Barnacles Convert 5% of Physical Damage to Cold and have 5% increased duration of Chill and Freeze on them.\nEach instance of Barnacles lasts 30 seconds and can be inflicted up to 10 times)", apply = function(val, modList, enemyModList)
enemyModList:NewMod("Multiplier:BarnacleStack", "BASE", m_min(val, 10), "Config", { type = "Condition", var = "Effective" })
enemyModList:NewMod("SelfFreezeDuration", "INC", 5, "Config", { type = "Multiplier", var = "BarnacleStack" }, { type = "Condition", var = "Effective" } )
enemyModList:NewMod("SelfChillDuration", "INC", 5, "Config", { type = "Multiplier", var = "BarnacleStack" }, { type = "Condition", var = "Effective" } )
enemyModList:NewMod("PhysicalDamageConvertToCold", "BASE", 5, "Config", { type = "Multiplier", var = "BarnacleStack" }, { type = "Condition", var = "Effective" } )
end },
{ var = "conditionEnemyFrozen", type = "check", label = "Is the enemy ^x3F6DB3Frozen?", ifEnemyCond = "Frozen", apply = function(val, modList, enemyModList)
enemyModList:NewMod("Condition:Frozen", "FLAG", true, "Config", { type = "Condition", var = "Effective" })
end },
Expand Down Expand Up @@ -1973,9 +1989,19 @@ Huge sets the radius to 11.
{ var = "multiplierEnemyAffectedByGraspingVines", type = "count", label = "# of Grasping Vines affecting enemy:", ifMult = "GraspingVinesAffectingEnemy", apply = function(val, modList, enemyModList)
modList:NewMod("Multiplier:GraspingVinesAffectingEnemy", "BASE", val, "Config", { type = "Condition", var = "Effective" })
end },
{ var = "conditionEnemyOnFungalGround", type = "check", label = "Is the enemy on Fungal Ground?", ifCond = { "OnFungalGround", "CreateFungalGround" }, tooltip = "Enemies on your Fungal Ground have -10% to all Resistances.", apply = function(val, modList, enemyModList)
{ var = "conditionEnemyOnFungalGround", type = "check", label = "Is the enemy on Fungal Ground?", ifCond = { "OnFungalGround", "CreateFungalGround" }, tooltip = "Enemies on your Fungal Ground have -10% to all Resistances", apply = function(val, modList, enemyModList)
enemyModList:NewMod("Condition:OnFungalGround", "FLAG", true, "Config", { type = "Condition", var = "Effective" })
end },
{ var = "conditionEnemyOnBrineGround", type = "check", label = "Is the enemy on Brine Ground?", ifFlag = "CanCreateBrineGround", tooltip = "Enemies on your Brine Ground have \n30% increased effect of Lightning and Cold Ailments on them and \nhave 25% reduced Armour and Evasion Rating.", apply = function(val, modList, enemyModList)
enemyModList:NewMod("Condition:OnBrineGround", "FLAG", true, "Config", { type = "Condition", var = "Effective" })
enemyModList:NewMod("SelfChillEffect", "INC", 30, "Config", { type = "Condition", var = "OnBrineGround" })
enemyModList:NewMod("SelfBrittleEffect", "INC", 30, "Config", { type = "Condition", var = "OnBrineGround" })
enemyModList:NewMod("SelfShockEffect", "INC", 30, "Config", { type = "Condition", var = "OnBrineGround" })
enemyModList:NewMod("SelfSapEffect", "INC", 30, "Config", { type = "Condition", var = "OnBrineGround" })
enemyModList:NewMod("Armour", "INC", -25, "Config", { type = "Condition", var = "OnBrineGround" })
enemyModList:NewMod("Evasion", "INC", -25, "Config", { type = "Condition", var = "OnBrineGround" })

end },
{ var = "conditionEnemyInChillingArea", type = "check", label = "Is the enemy in a ^x3F6DB3Chilling ^7area?", ifEnemyCond = "InChillingArea", apply = function(val, modList, enemyModList)
enemyModList:NewMod("Condition:InChillingArea", "FLAG", true, "Config", { type = "Condition", var = "Effective" })
end },
Expand Down
3 changes: 3 additions & 0 deletions src/Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3027,6 +3027,9 @@ local specialModList = {
mod("ChaosMax", "BASE", 1, { type = "PercentStat", stat = "LifeCost", percent = num }, { type = "StatThreshold", stat = "LifeUnreserved", thresholdStat = "LifeCost", thresholdPercent = num }),
} end,
["lose all rage on reaching maximum rage and gain wild savagery for 1 second per 10 rage lost this way"] = { flag("WildSavagery") },
-- Velka Bloodline
["inflict barnacles on nearby enemies every second"] = { flag("CanInflictBarnacles") },
["drop brine ground while moving, lasting 4 seconds"] = { flag("CanCreateBrineGround"), },
-- Item local modifiers
["has no sockets"] = { flag("NoSockets") },
["reflects your o[tp][hp][eo][rs]i?t?e? ring"] = {
Expand Down
Loading