diff --git a/spec/System/TestAilments_spec.lua b/spec/System/TestAilments_spec.lua index 0940ac095b..e6fab51786 100644 --- a/spec/System/TestAilments_spec.lua +++ b/spec/System/TestAilments_spec.lua @@ -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") @@ -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) \ No newline at end of file + + 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) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 387ab4f047..015e10254b 100755 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -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} @@ -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} diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 0c24922df4..85ecb9f772 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -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 = { } @@ -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) diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 913b76127b..9aa020f744 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -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 @@ -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 diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index b8ec5bf741..69c9d15545 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -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 }, @@ -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 }, @@ -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 }, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 9b311b829f..ed1eaacc37 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -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"] = {