Skip to content

Commit 73482fe

Browse files
authored
Cap Doom Blast expiration mode and use charge based calcs for skills that ignore tick rate (#6720)
* FIX: cap expiration mode by cast rate * FIX: use charge based calcs if ignoring tick rate * FEAT: add a warning if vixen's gloves not equipped * FEAT: implement hexblast replacement mode
1 parent 8a2aadc commit 73482fe

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

src/Modules/Build.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,9 @@ function buildMode:AddDisplayStatList(statList, actor)
14531453
if actor.output.VixensTooMuchCastSpeedWarn then
14541454
InsertIfNew(self.controls.warnings.lines, "You may have too much cast speed or too little cooldown reduction to effectively use Vixen's Curse replacement")
14551455
end
1456+
if actor.output.VixenModeNoVixenGlovesWarn then
1457+
InsertIfNew(self.controls.warnings.lines, "Vixen's calculation mode for Doom Blast is selected but you do not have Vixen's Entrapment Embroidered Gloves equipped")
1458+
end
14561459
end
14571460

14581461
function buildMode:InsertItemWarnings()

src/Modules/CalcTriggers.lua

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -594,12 +594,33 @@ local function defaultTriggerHandler(env, config)
594594
if actionCooldownTickRounded ~= 0 then
595595
output.TriggerRateCap = 1 / actionCooldownTickRounded
596596
end
597-
598597
if config.triggerName == "Doom Blast" and env.build.configTab.input["doomBlastSource"] == "expiration" then
599-
trigRate = 1 / GlobalCache.cachedData["CACHE"][uuid].Env.player.output.Duration
598+
local expirationRate = 1 / GlobalCache.cachedData["CACHE"][uuid].Env.player.output.Duration
600599
if breakdown and breakdown.EffectiveSourceRate then
601600
breakdown.EffectiveSourceRate[1] = s_format("1 / %.2f ^8(source curse duration)", GlobalCache.cachedData["CACHE"][uuid].Env.player.output.Duration)
602601
end
602+
if expirationRate > trigRate then
603+
env.player.modDB:NewMod("UsesCurseOverlaps", "FLAG", true, "Config")
604+
if breakdown and breakdown.EffectiveSourceRate then
605+
t_insert(breakdown.EffectiveSourceRate, 2, s_format("max(%.2f, %.2f) ^8(If a curse expires instantly curse expiration is equivalent to curse replacement)", expirationRate, trigRate))
606+
t_insert(breakdown.EffectiveSourceRate, 2, s_format("%.2f ^8(%s cast rate)", trigRate, source.activeEffect.grantedEffect.name))
607+
end
608+
else
609+
trigRate = expirationRate
610+
end
611+
elseif config.triggerName == "Doom Blast" and env.build.configTab.input["doomBlastSource"] == "hexblast" then
612+
local hexBlast, rate
613+
for _, skill in ipairs(env.player.activeSkillList) do
614+
if skill.activeEffect.grantedEffect.name == "Hexblast" and not isTriggered(skill) and skill ~= actor.mainSkill then
615+
hexBlast, rate, uuid = findTriggerSkill(env, skill, hexBlast, rate)
616+
end
617+
end
618+
if hexBlast then
619+
if breakdown then
620+
breakdown.EffectiveSourceRate[1] = s_format("1 / (%.2f + %.2f) ^8(sum of triggered curse and hexblast cast time)", 1/trigRate, 1/rate)
621+
end
622+
trigRate = 1/ (1/trigRate + 1/rate)
623+
end
603624
end
604625

605626
if breakdown then
@@ -763,6 +784,11 @@ local function defaultTriggerHandler(env, config)
763784
end
764785

765786
if env.player.mainSkill.activeEffect.grantedEffect.name == "Doom Blast" and env.build.configTab.input["doomBlastSource"] == "vixen" then
787+
if not env.player.itemList["Gloves"] or env.player.itemList["Gloves"].title ~= "Vixen's Entrapment" then
788+
output.VixenModeNoVixenGlovesWarn = true
789+
end
790+
791+
env.player.modDB:NewMod("UsesCurseOverlaps", "FLAG", true, "Config")
766792
local vixens = env.data.skills["SupportUniqueCastCurseOnCurse"]
767793
local vixensCD = vixens and vixens.levels[1].cooldown / icdr
768794
output.EffectiveSourceRate = calcMultiSpellRotationImpact(env, {{ uuid = cacheSkillUUID(env.player.mainSkill, env), icdr = icdr}}, trigRate, vixensCD)
@@ -784,19 +810,25 @@ local function defaultTriggerHandler(env, config)
784810

785811
local skillName = (source and source.activeEffect.grantedEffect.name) or (actor.mainSkill.triggeredBy and actor.mainSkill.triggeredBy.grantedEffect.name) or actor.mainSkill.activeEffect.grantedEffect.name
786812

787-
--If spell count is missing the skill likely comes from a unique and /or triggers it self
788813
if output.EffectiveSourceRate ~= 0 then
789-
if env.player.mainSkill.activeEffect.grantedEffect.name == "Doom Blast" and env.build.configTab.input["doomBlastSource"] == "vixen" then
790-
local overlaps = m_max(env.player.modDB:Sum("BASE", nil, "Multiplier:CurseOverlaps") or 1, 1)
791-
output.SkillTriggerRate = m_min(output.TriggerRateCap, output.EffectiveSourceRate * overlaps)
814+
-- If the current triggered skill ignores tick rate and is the only triggered skill by this trigger use charge based calcs
815+
if actor.mainSkill.skillData.ignoresTickRate and ( not config.triggeredSkillCond or (triggeredSkills and #triggeredSkills == 1 and triggeredSkills[1] == packageSkillDataForSimulation(actor.mainSkill, env)) ) then
816+
local overlaps = config.stagesAreOverlaps and env.player.mainSkill.skillPart == config.stagesAreOverlaps and env.player.mainSkill.activeEffect.srcInstance.skillStageCount or config.overlaps
817+
output.SkillTriggerRate = m_min(output.TriggerRateCap, output.EffectiveSourceRate * (overlaps or 1))
792818
if breakdown then
793-
breakdown.SkillTriggerRate = {
794-
s_format("min(%.2f, %.2f * %d)", output.TriggerRateCap, output.EffectiveSourceRate, overlaps)
795-
}
819+
if overlaps then
820+
breakdown.SkillTriggerRate = {
821+
s_format("min(%.2f, %.2f * %d) ^8(%d overlaps)", output.TriggerRateCap, output.EffectiveSourceRate, overlaps, overlaps)
822+
}
823+
else
824+
breakdown.SkillTriggerRate = {
825+
s_format("min(%.2f, %.2f)", output.TriggerRateCap, output.EffectiveSourceRate)
826+
}
827+
end
796828
end
797-
elseif actor.mainSkill.skillFlags.globalTrigger and not config.triggeredSkillCond then
829+
elseif actor.mainSkill.skillFlags.globalTrigger and not config.triggeredSkillCond then -- Trigger does not use source rate breakpoints for one reason or another
798830
output.SkillTriggerRate = output.EffectiveSourceRate
799-
else
831+
else -- Triggers like Cast on Crit go through simulation to calculate the trigger rate of each skill in the trigger group
800832
output.SkillTriggerRate, simBreakdown = calcMultiSpellRotationImpact(env, config.triggeredSkillCond and triggeredSkills or {packageSkillDataForSimulation(actor.mainSkill, env)}, output.EffectiveSourceRate, (not actor.mainSkill.skillData.triggeredByBrand and ( triggerCD or triggeredCD ) or 0) / icdr, actor)
801833
local triggerBotsEffective = actor.modDB:Flag(nil, "HaveTriggerBots") and actor.mainSkill.skillTypes[SkillType.Spell]
802834
if triggerBotsEffective then
@@ -1206,9 +1238,12 @@ local configTable = {
12061238
triggerSkillCond = function(env, skill) return skill.skillTypes[SkillType.Attack] and band(skill.skillCfg.flags, ModFlag.Bow) > 0 end}
12071239
end,
12081240
["doom blast"] = function(env)
1241+
if env.build.configTab.input["doomBlastSource"] == "replacement" then
1242+
env.player.modDB:NewMod("UsesCurseOverlaps", "FLAG", true, "Config")
1243+
end
12091244
env.player.mainSkill.skillData.ignoresTickRate = true
1210-
env.player.mainSkill.skillData.sourceRateIsFinal = true
12111245
return {useCastRate = true,
1246+
overlaps = #env.player.modDB:Tabulate("BASE", nil, "Multiplier:CurseOverlaps") > 0 and m_max(env.player.modDB:Sum("BASE", nil, "Multiplier:CurseOverlaps"), 1),
12121247
customTriggerName = "Doom Blast triggering Hex: ",
12131248
triggerSkillCond = function(env, skill) return skill.skillTypes[SkillType.Hex] and slotMatch(env, skill) end}
12141249
end,

src/Modules/ConfigOptions.lua

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,7 @@ return {
352352
modList:NewMod("SkillData", "LIST", { key = "skeletonLife", value = val }, "Config", { type = "SkillName", skillName = "Dark Pact" })
353353
end },
354354
{ label = "Doom Blast:", ifSkill = "Doom Blast" },
355-
{ var = "doomBlastSource", type = "list", label = "Doom Blast Trigger Source:", ifSkill = "Doom Blast", list = {{val="expiration",label="Curse Expiration"},{val="replacement",label="Curse Replacement"},{val="vixen",label="Vixen's Curse"}}, defaultIndex = 3, apply = function(val, modList, enemyModList)
356-
if val == "vixen" then
357-
modList:NewMod("UsesCurseOverlaps", "FLAG", true, "Config")
358-
end
359-
end },
355+
{ var = "doomBlastSource", type = "list", label = "Doom Blast Trigger Source:", ifSkill = "Doom Blast", list = {{val="expiration",label="Curse Expiration"},{val="replacement",label="Curse Replacement"},{val="vixen",label="Vixen's Curse"},{val="hexblast",label="Hexblast Replacement"}}, defaultIndex = 3},
360356
{ var = "curseOverlaps", type = "count", label = "Curse overlaps:", ifSkill = "Doom Blast", ifFlag = "UsesCurseOverlaps", apply = function(val, modList, enemyModList)
361357
modList:NewMod("Multiplier:CurseOverlaps", "BASE", val, "Config", { type = "Condition", var = "Effective" })
362358
end },

0 commit comments

Comments
 (0)