Skip to content

Commit 42be41e

Browse files
author
Steve
committed
Auto-calculate Verglas Ice Crystal Life
1 parent b1e9324 commit 42be41e

4 files changed

Lines changed: 65 additions & 4 deletions

File tree

spec/System/TestSkills_spec.lua

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ describe("TestSkills", function()
536536
build.itemsTab:AddDisplayItem()
537537
build.skillsTab:PasteSocketGroup("Quarterstaff Strike 20/0 1\nVerglas 1/0 1")
538538
build.skillsTab:PasteSocketGroup("Leap Slam 20/0 1")
539+
build.skillsTab:PasteSocketGroup("Frost Wall 20/20 1")
539540
build.skillsTab.socketGroupList[1].includeInFullDPS = true
540541
runCallback("OnFrame")
541542

@@ -544,7 +545,6 @@ describe("TestSkills", function()
544545
assert.True(baseFullDPS > 0)
545546

546547
build.configTab.input.conditionDestroyedIceCrystalPast6Seconds = true
547-
build.configTab.input.multiplierDestroyedIceCrystalLife = 2000
548548
build.configTab:BuildModList()
549549
runCallback("OnFrame")
550550

@@ -557,10 +557,25 @@ describe("TestSkills", function()
557557
end
558558
local linkedSkill = findSkillForGroup(build.skillsTab.socketGroupList[1])
559559
local unlinkedSkill = findSkillForGroup(build.skillsTab.socketGroupList[2])
560+
local frostWallSkill = findSkillForGroup(build.skillsTab.socketGroupList[3])
560561
assert.is_not_nil(linkedSkill)
561562
assert.is_not_nil(unlinkedSkill)
562-
assert.are.equals(1, linkedSkill.skillModList:Sum("BASE", linkedSkill.skillCfg, "DamageGainAsCold"))
563+
assert.is_not_nil(frostWallSkill)
564+
local frostWallLife = frostWallSkill.skillModList:Sum("BASE", frostWallSkill.skillCfg, "IceCrystalLifeBase") * calcLib.mod(frostWallSkill.skillModList, frostWallSkill.skillCfg, "IceCrystalLife")
565+
assert.are.equals(frostWallLife, build.calcsTab.mainEnv.player.automaticDestroyedIceCrystalLife)
566+
assert.are.equals(frostWallLife, build.calcsTab.mainEnv.player.destroyedIceCrystalLife)
567+
assert.are.equals(tostring(math.floor(frostWallLife + 0.5)), build.configTab.varControls.multiplierDestroyedIceCrystalLife.placeholder)
568+
assert.are.equals(math.floor(frostWallLife / 2000), linkedSkill.skillModList:Sum("BASE", linkedSkill.skillCfg, "DamageGainAsCold"))
563569
assert.are.equals(0, unlinkedSkill.skillModList:Sum("BASE", unlinkedSkill.skillCfg, "DamageGainAsCold"))
570+
local automaticFullDPS = build.calcsTab.mainOutput.FullDPS
571+
assert.True(automaticFullDPS > baseFullDPS)
572+
573+
build.configTab.input.multiplierDestroyedIceCrystalLife = 2000
574+
build.configTab:BuildModList()
575+
runCallback("OnFrame")
576+
577+
linkedSkill = findSkillForGroup(build.skillsTab.socketGroupList[1])
578+
assert.are.equals(1, linkedSkill.skillModList:Sum("BASE", linkedSkill.skillCfg, "DamageGainAsCold"))
564579

565580
build.configTab.input.multiplierDestroyedIceCrystalLife = 3999
566581
build.configTab:BuildModList()
@@ -586,6 +601,19 @@ describe("TestSkills", function()
586601
linkedSkill = findSkillForGroup(build.skillsTab.socketGroupList[1])
587602
assert.are.equals(135, linkedSkill.skillModList:Sum("BASE", linkedSkill.skillCfg, "DamageGainAsCold"))
588603

604+
build.configTab.input.multiplierDestroyedIceCrystalLife = nil
605+
build.configTab:BuildModList()
606+
runCallback("OnFrame")
607+
608+
linkedSkill = findSkillForGroup(build.skillsTab.socketGroupList[1])
609+
assert.are.equals(math.floor(frostWallLife / 2000), linkedSkill.skillModList:Sum("BASE", linkedSkill.skillCfg, "DamageGainAsCold"))
610+
assert.are.near(automaticFullDPS, build.calcsTab.mainOutput.FullDPS, automaticFullDPS * 0.001)
611+
612+
local calcFunc, baseOutput = LoadModule("Modules/Calcs").getMiscCalculator(build)
613+
local advancedThaumaturgy = build.spec.nodes[14429]
614+
local qualityOutput = calcFunc({ addNodes = { [advancedThaumaturgy] = true } }, true, { fullDPSOnly = true })
615+
assert.True(qualityOutput.FullDPS > baseOutput.FullDPS)
616+
589617
build.configTab.input.conditionDestroyedIceCrystalPast6Seconds = false
590618
build.configTab:BuildModList()
591619
runCallback("OnFrame")

src/Modules/CalcSetup.lua

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ local t_insert = table.insert
1111
local t_remove = table.remove
1212
local m_min = math.min
1313
local m_max = math.max
14+
local m_floor = math.floor
1415
local band = AND64
1516

1617
local tempTable1 = { }
@@ -2093,6 +2094,35 @@ function calcs.initEnv(build, mode, override, specEnv)
20932094
end
20942095
end
20952096

2097+
-- Verglas uses the maximum Life of the Ice Crystal that granted its buff.
2098+
-- Prefer the highest value from enabled Ice Crystal skills in the build, while
2099+
-- retaining the Config value as an explicit override for other crystal sources.
2100+
local automaticDestroyedIceCrystalLife = 0
2101+
for _, activeSkill in pairs(env.player.activeSkillList) do
2102+
local socketGroup = activeSkill.socketGroup
2103+
if (not socketGroup or (socketGroup.enabled and socketGroup.slotEnabled)) and activeSkill.skillModList then
2104+
local baseLife = activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "IceCrystalLifeBase")
2105+
if baseLife > 0 then
2106+
automaticDestroyedIceCrystalLife = m_max(automaticDestroyedIceCrystalLife, baseLife * calcLib.mod(activeSkill.skillModList, activeSkill.skillCfg, "IceCrystalLife"))
2107+
end
2108+
end
2109+
end
2110+
local configuredDestroyedIceCrystalLife = tonumber(env.configInput.multiplierDestroyedIceCrystalLife) or 0
2111+
local resolvedDestroyedIceCrystalLife = configuredDestroyedIceCrystalLife > 0 and configuredDestroyedIceCrystalLife or automaticDestroyedIceCrystalLife
2112+
env.player.automaticDestroyedIceCrystalLife = automaticDestroyedIceCrystalLife
2113+
env.player.destroyedIceCrystalLife = resolvedDestroyedIceCrystalLife
2114+
if configuredDestroyedIceCrystalLife <= 0 and automaticDestroyedIceCrystalLife > 0 then
2115+
env.modDB.multipliers.DestroyedIceCrystalLife = automaticDestroyedIceCrystalLife
2116+
else
2117+
env.modDB.multipliers.DestroyedIceCrystalLife = nil
2118+
end
2119+
if mode == "MAIN" then
2120+
local control = build.configTab.varControls.multiplierDestroyedIceCrystalLife
2121+
if control then
2122+
control:SetPlaceholder(automaticDestroyedIceCrystalLife > 0 and m_floor(automaticDestroyedIceCrystalLife + 0.5) or "", false)
2123+
end
2124+
end
2125+
20962126
env.virtuousMoteSkillCount = virtuousMoteSkillCount
20972127
env.modDB.multipliers.StrengthMoteSkillCount = virtuousMoteSkillCount.Str
20982128
env.modDB.multipliers.DexterityMoteSkillCount = virtuousMoteSkillCount.Dex

src/Modules/Calcs.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ end
225225
local exposureElements = { "Fire", "Cold", "Lightning", "Chaos" }
226226
local function captureCouplingSurface(env)
227227
local surface = { mods = { }, meta = { } }
228+
-- Automatic Verglas scaling is derived from another active skill (usually
229+
-- Frost Wall), so it must participate in Full-DPS cache invalidation.
230+
surface.meta[#surface.meta + 1] = "destroyedIceCrystalLife/" .. tostring(env.player.destroyedIceCrystalLife or 0)
228231
for _, skill in ipairs(env.player.activeSkillList) do
229232
for _, buff in ipairs(skill.buffList or { }) do
230233
surface.meta[#surface.meta + 1] = tostring(buff.type) .. "/" .. tostring(buff.name)

src/Modules/ConfigOptions.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,10 +1172,10 @@ Huge sets the radius to 11.
11721172
{ var = "conditionKilledLast3Seconds", type = "check", label = "Have you Killed in the last 3 Seconds?", ifCond = "KilledLast3Seconds", implyCond = "KilledRecently", tooltip = "This also implies that you have Killed Recently.", apply = function(val, modList, enemyModList)
11731173
modList:NewMod("Condition:KilledLast3Seconds", "FLAG", true, "Config", { type = "Condition", var = "Combat" })
11741174
end },
1175-
{ var = "conditionDestroyedIceCrystalPast6Seconds", type = "check", label = "Have you Destroyed an Ice Crystal in the past 6 Seconds?", ifCond = "DestroyedIceCrystalPast6Seconds", apply = function(val, modList, enemyModList)
1175+
{ var = "conditionDestroyedIceCrystalPast6Seconds", type = "check", label = "Destroyed an Ice Crystal in past 6s?", ifCond = "DestroyedIceCrystalPast6Seconds", apply = function(val, modList, enemyModList)
11761176
modList:NewMod("Condition:DestroyedIceCrystalPast6Seconds", "FLAG", true, "Config", { type = "Condition", var = "Combat" })
11771177
end },
1178-
{ var = "multiplierDestroyedIceCrystalLife", type = "count", label = "Maximum Life of the Destroyed Ice Crystal:", ifOption = "conditionDestroyedIceCrystalPast6Seconds", ifMult = "DestroyedIceCrystalLife", tooltip = "Enter the maximum Life of the Ice Crystal that granted the current Verglas buff.", apply = function(val, modList, enemyModList)
1178+
{ var = "multiplierDestroyedIceCrystalLife", type = "count", label = "Ice Crystal Life override:", ifOption = "conditionDestroyedIceCrystalPast6Seconds", ifMult = "DestroyedIceCrystalLife", tooltip = "Automatically uses the highest maximum Life from enabled Ice Crystal skills.\nEnter a value to override it for another Ice Crystal source.", apply = function(val, modList, enemyModList)
11791179
modList:NewMod("Multiplier:DestroyedIceCrystalLife", "BASE", val, "Config", { type = "Condition", var = "Combat" })
11801180
end },
11811181
{ var = "conditionKilledPoisonedLast2Seconds", type = "check", label = "Killed a poisoned enemy in the last 2 Seconds?", ifCond = "KilledPoisonedLast2Seconds", implyCond = "KilledRecently", tooltip = "This also implies that you have Killed Recently.", apply = function(val, modList, enemyModList)

0 commit comments

Comments
 (0)