Skip to content

Commit 3c7c3bc

Browse files
PaliakLocalIdentity
andauthored
Add snipe to trigger rework (#6304)
* Add proper support for DPS with Channeled skills that use stages Channeling skills that used stages did not have their hit rate modified by the time it took to channel those stages This PR adds `hitTimeMultiplier` values for Scourge Arrow, Divine Ire, Flameblast and Incinerate Snipe is handled in it's own PR This shows the channel time in the sidebar along with the correct hit rate for these skills Adds boxes to the config page to set the number of nearby enemies for Divine Ire to calculate the correct charge rate * Add support for triggered skills with Snipe Support * Fix Snipe calcs for triggered skills and Assailum * Fix breakdowns * FEAT: impl snipe * FIX: simplify triggered skills count logic * FIX: use skill index from Snipe skill pool * FIX: breakdown using triggeredName instead of triggerName * FIX: remove unnecessary query for max stages * FIX: merge conflict and improve breakdown --------- Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent 1b07e97 commit 3c7c3bc

File tree

12 files changed

+179
-77
lines changed

12 files changed

+179
-77
lines changed

src/Data/SkillStatMap.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ return {
209209
skill("triggeredWhileChannelling", true, { type = "SkillType", skillType = SkillType.Triggerable }, { type = "SkillType", skillType = SkillType.Spell }),
210210
},
211211
["skill_triggered_by_snipe"] = {
212-
skill("triggered", true, { type = "SkillType", skillType = SkillType.Triggerable }),
212+
skill("triggeredBySnipe", true, { type = "SkillType", skillType = SkillType.Triggerable }),
213213
},
214214
["triggered_by_spiritual_cry"] = {
215215
skill("triggeredByGeneralsCry", true, { type = "SkillType", skillType = SkillType.Melee }, { type = "SkillType", skillType = SkillType.Attack }),
@@ -1716,11 +1716,11 @@ return {
17161716
["channelled_skill_damage_+%"] = {
17171717
mod("Damage", "INC", nil, 0, 0, { type = "SkillType", skillType = SkillType.Channel }),
17181718
},
1719-
["snipe_triggered_skill_hit_damage_+%_final_per_stage"] = {
1720-
mod("Damage", "MORE", nil, ModFlag.Hit, 0, { type = "Multiplier", var = "SnipeStage", limitVar = "SnipeStagesMax" }),
1721-
},
17221719
["snipe_triggered_skill_ailment_damage_+%_final_per_stage"] = {
1723-
mod("Damage", "MORE", nil, ModFlag.Ailment, 0, { type = "Multiplier", var = "SnipeStage", limitVar = "SnipeStagesMax" }),
1720+
mod("snipeAilmentMulti", "BASE", nil),
1721+
},
1722+
["snipe_triggered_skill_hit_damage_+%_final_per_stage"] = {
1723+
mod("snipeHitMulti", "BASE", nil),
17241724
},
17251725
["snipe_triggered_skill_damage_+%_final"] = {
17261726
mod("Damage", "MORE", nil),

src/Data/Skills/act_dex.lua

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7888,8 +7888,8 @@ skills["ScourgeArrow"] = {
78887888
},
78897889
statDescriptionScope = "skill_stat_descriptions",
78907890
castTime = 1,
7891-
initialFunc = function(activeSkill, output)
7892-
activeSkill.skillData.dpsMultiplier = 1 / math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:ScourgeArrowStage"), 1)
7891+
preDamageFunc = function(activeSkill, output)
7892+
activeSkill.skillData.hitTimeMultiplier = math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:ScourgeArrowStage") - 0.5, 0.5) --First stage takes 0.5x time to channel compared to subsequent stages
78937893
end,
78947894
parts = {
78957895
{
@@ -10797,9 +10797,6 @@ skills["ChannelledSnipe"] = {
1079710797
},
1079810798
statDescriptionScope = "skill_stat_descriptions",
1079910799
castTime = 1,
10800-
initialFunc = function(activeSkill, output)
10801-
activeSkill.skillData.dpsMultiplier = 1 / math.min(math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStage"), 1), activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStagesMax"))
10802-
end,
1080310800
statMap = {
1080410801
["snipe_max_stacks"] = {
1080510802
mod("Multiplier:SnipeStagesMax", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Buff", unscalable = true }),

src/Data/Skills/act_int.lua

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,6 +2790,11 @@ skills["DivineTempest"] = {
27902790
skillTypes = { [SkillType.Spell] = true, [SkillType.Area] = true, [SkillType.Damage] = true, [SkillType.Channel] = true, [SkillType.Lightning] = true, [SkillType.Totemable] = true, [SkillType.AreaSpell] = true, [SkillType.Physical] = true, },
27912791
statDescriptionScope = "skill_stat_descriptions",
27922792
castTime = 0.22,
2793+
preDamageFunc = function(activeSkill, output)
2794+
local skillCfg = activeSkill.skillCfg
2795+
local skillModList = activeSkill.skillModList
2796+
activeSkill.skillData.hitTimeMultiplier = math.max(skillModList:Sum("BASE", skillCfg, "Multiplier:DivineIreStage") / (1 + skillModList:Sum("BASE", skillCfg, "Multiplier:DivineIreUniqueEnemyCount") + skillModList:Sum("BASE", skillCfg, "NormalEnemyHitMultiplier") * skillModList:Sum("BASE", skillCfg, "Multiplier:DivineIreNormalEnemyCount")), 1)
2797+
end,
27932798
parts = {
27942799
{
27952800
name = "Channelling",
@@ -2811,13 +2816,16 @@ skills["DivineTempest"] = {
28112816
["divine_tempest_ailment_damage_+%_final_per_stage"] = {
28122817
mod("Damage", "MORE", nil, 0, KeywordFlag.Ailment, { type = "Multiplier", var = "DivineIreStageAfterFirst" }),
28132818
},
2819+
["divine_tempest_stage_on_hitting_normal_magic_%_chance"] = {
2820+
mod("NormalEnemyHitMultiplier", "BASE", nil),
2821+
div = 100
2822+
},
28142823
},
28152824
baseFlags = {
28162825
spell = true,
28172826
area = true,
28182827
},
28192828
baseMods = {
2820-
skill("showAverage", true, { type = "SkillPart", skillPart = 2 }),
28212829
mod("Multiplier:DivineIreMaxStages", "BASE", 20, 0, 0, { type = "SkillPart", skillPart = 2 }),
28222830
skill("radius", 38),
28232831
},
@@ -4060,6 +4068,9 @@ skills["Flameblast"] = {
40604068
skillTypes = { [SkillType.Spell] = true, [SkillType.Damage] = true, [SkillType.Area] = true, [SkillType.Totemable] = true, [SkillType.Fire] = true, [SkillType.Channel] = true, [SkillType.AreaSpell] = true, [SkillType.Cooldown] = true, },
40614069
statDescriptionScope = "skill_stat_descriptions",
40624070
castTime = 0.2,
4071+
preDamageFunc = function(activeSkill, output)
4072+
activeSkill.skillData.hitTimeMultiplier = math.max(activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:FlameblastStage") - activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:FlameblastMinimumStage"), 1)
4073+
end,
40634074
statMap = {
40644075
["charged_blast_spell_damage_+%_final_per_stack"] = {
40654076
mod("Damage", "MORE", nil, ModFlag.Hit, 0, { type = "Multiplier", var = "FlameblastStageAfterFirst" }),
@@ -4085,7 +4096,6 @@ skills["Flameblast"] = {
40854096
},
40864097
baseMods = {
40874098
skill("radius", 2),
4088-
skill("showAverage", true),
40894099
mod("PvpTvalueMultiplier", "MORE", 100, 0, 0, { type = "Multiplier", var = "FlameblastStageAfterFirst" }),
40904100
},
40914101
qualityStats = {
@@ -6186,6 +6196,9 @@ skills["ExpandingFireCone"] = {
61866196
skillTypes = { [SkillType.Spell] = true, [SkillType.Damage] = true, [SkillType.Totemable] = true, [SkillType.Fire] = true, [SkillType.Channel] = true, [SkillType.Area] = true, [SkillType.AreaSpell] = true, [SkillType.Cooldown] = true, },
61876197
statDescriptionScope = "skill_stat_descriptions",
61886198
castTime = 0.2,
6199+
preDamageFunc = function(activeSkill, output)
6200+
activeSkill.skillData.hitTimeMultiplier = math.max(activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:IncinerateStage") - activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:IncinerateMinimumStage") - 0.4175, 0.5825) --First stage takes 0.5825x time to channel compared to subsequent stages
6201+
end,
61896202
parts = {
61906203
{
61916204
name = "Channelling",
@@ -6231,7 +6244,6 @@ skills["ExpandingFireCone"] = {
62316244
area = true,
62326245
},
62336246
baseMods = {
6234-
skill("showAverage", true, { type = "SkillPart", skillPart = 2 }),
62356247
skill("radius", 25),
62366248
skill("radiusLabel", "Flame Length:"),
62376249
skill("radiusSecondary", 20),

src/Export/Skills/act_dex.txt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,8 +1484,8 @@ local skills, mod, flag, skill = ...
14841484

14851485
#skill ScourgeArrow
14861486
#flags attack projectile
1487-
initialFunc = function(activeSkill, output)
1488-
activeSkill.skillData.dpsMultiplier = 1 / math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:ScourgeArrowStage"), 1)
1487+
preDamageFunc = function(activeSkill, output)
1488+
activeSkill.skillData.hitTimeMultiplier = math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:ScourgeArrowStage") - 0.5, 0.5) --First stage takes 0.5x time to channel compared to subsequent stages
14891489
end,
14901490
parts = {
14911491
{
@@ -2032,9 +2032,6 @@ local skills, mod, flag, skill = ...
20322032

20332033
#skill ChannelledSnipe
20342034
#flags attack projectile
2035-
initialFunc = function(activeSkill, output)
2036-
activeSkill.skillData.dpsMultiplier = 1 / math.min(math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStage"), 1), activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStagesMax"))
2037-
end,
20382035
statMap = {
20392036
["snipe_max_stacks"] = {
20402037
mod("Multiplier:SnipeStagesMax", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Buff", unscalable = true }),

src/Export/Skills/act_int.txt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,11 @@ local skills, mod, flag, skill = ...
631631

632632
#skill DivineTempest
633633
#flags spell area
634+
preDamageFunc = function(activeSkill, output)
635+
local skillCfg = activeSkill.skillCfg
636+
local skillModList = activeSkill.skillModList
637+
activeSkill.skillData.hitTimeMultiplier = math.max(skillModList:Sum("BASE", skillCfg, "Multiplier:DivineIreStage") / (1 + skillModList:Sum("BASE", skillCfg, "Multiplier:DivineIreUniqueEnemyCount") + skillModList:Sum("BASE", skillCfg, "NormalEnemyHitMultiplier") * skillModList:Sum("BASE", skillCfg, "Multiplier:DivineIreNormalEnemyCount")), 1)
638+
end,
634639
parts = {
635640
{
636641
name = "Channelling",
@@ -652,8 +657,11 @@ local skills, mod, flag, skill = ...
652657
["divine_tempest_ailment_damage_+%_final_per_stage"] = {
653658
mod("Damage", "MORE", nil, 0, KeywordFlag.Ailment, { type = "Multiplier", var = "DivineIreStageAfterFirst" }),
654659
},
660+
["divine_tempest_stage_on_hitting_normal_magic_%_chance"] = {
661+
mod("NormalEnemyHitMultiplier", "BASE", nil),
662+
div = 100
663+
},
655664
},
656-
#baseMod skill("showAverage", true, { type = "SkillPart", skillPart = 2 })
657665
#baseMod mod("Multiplier:DivineIreMaxStages", "BASE", 20, 0, 0, { type = "SkillPart", skillPart = 2 })
658666
#baseMod skill("radius", 38)
659667
#mods
@@ -882,6 +890,9 @@ local skills, mod, flag, skill = ...
882890

883891
#skill Flameblast
884892
#flags spell area
893+
preDamageFunc = function(activeSkill, output)
894+
activeSkill.skillData.hitTimeMultiplier = math.max(activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:FlameblastStage") - activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:FlameblastMinimumStage"), 1)
895+
end,
885896
statMap = {
886897
["charged_blast_spell_damage_+%_final_per_stack"] = {
887898
mod("Damage", "MORE", nil, ModFlag.Hit, 0, { type = "Multiplier", var = "FlameblastStageAfterFirst" }),
@@ -902,7 +913,6 @@ local skills, mod, flag, skill = ...
902913
},
903914
},
904915
#baseMod skill("radius", 2)
905-
#baseMod skill("showAverage", true)
906916
#baseMod mod("PvpTvalueMultiplier", "MORE", 100, 0, 0, { type = "Multiplier", var = "FlameblastStageAfterFirst" })
907917
#mods
908918

@@ -1367,6 +1377,9 @@ local skills, mod, flag, skill = ...
13671377

13681378
#skill ExpandingFireCone
13691379
#flags spell area
1380+
preDamageFunc = function(activeSkill, output)
1381+
activeSkill.skillData.hitTimeMultiplier = math.max(activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:IncinerateStage") - activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "Multiplier:IncinerateMinimumStage") - 0.4175, 0.5825) --First stage takes 0.5825x time to channel compared to subsequent stages
1382+
end,
13701383
parts = {
13711384
{
13721385
name = "Channelling",
@@ -1407,7 +1420,6 @@ local skills, mod, flag, skill = ...
14071420
--Display Only
14081421
},
14091422
},
1410-
#baseMod skill("showAverage", true, { type = "SkillPart", skillPart = 2 })
14111423
#baseMod skill("radius", 25)
14121424
#baseMod skill("radiusLabel", "Flame Length:")
14131425
#baseMod skill("radiusSecondary", 20)

src/Modules/Build.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild)
244244
{ stat = "Speed", label = "Effective Trigger Rate", fmt = ".2f", compPercent = true, condFunc = function(v,o) return (o.TriggerTime or 0) ~= 0 end },
245245
{ stat = "WarcryCastTime", label = "Cast Time", fmt = ".2fs", compPercent = true, lowerIsBetter = true, flag = "warcry" },
246246
{ stat = "HitSpeed", label = "Hit Rate", fmt = ".2f", compPercent = true, condFunc = function(v,o) return not o.TriggerTime end },
247+
{ stat = "HitTime", label = "Channel Time", fmt = ".2fs", compPercent = true, condFunc = function(v,o) return not o.TriggerTime end },
247248
{ stat = "TrapThrowingTime", label = "Trap Throwing Time", fmt = ".2fs", compPercent = true, lowerIsBetter = true, },
248249
{ stat = "TrapCooldown", label = "Trap Cooldown", fmt = ".3fs", lowerIsBetter = true },
249250
{ stat = "MineLayingTime", label = "Mine Throwing Time", fmt = ".2fs", compPercent = true, lowerIsBetter = true, },

src/Modules/CalcActiveSkill.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ function calcs.buildActiveSkillModList(env, activeSkill)
455455
activeSkill.skillData.manaReservationPercent = level.manaReservationPercent
456456
end
457457
-- Handle multiple triggers situation and if triggered by a trigger skill save a reference to the trigger.
458-
local match = skillEffect.grantedEffect.addSkillTypes and activeSkill.skillTypes[SkillType.Triggerable] and (not skillFlags.disable)
458+
local match = skillEffect.grantedEffect.addSkillTypes and (not skillFlags.disable)
459459
if match and skillEffect.grantedEffect.isTrigger then
460460
if activeSkill.triggeredBy then
461461
skillFlags.disable = true

src/Modules/CalcOffence.lua

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -751,10 +751,6 @@ function calcs.offence(env, actor, activeSkill)
751751
end
752752
end
753753
end
754-
--Snipe doesn't grab the max stages multiplier from the gem when granted by Assailum so we add it back here
755-
if skillModList:Flag(nil, "TriggeredByAssailum") and activeSkill.skillTypes[SkillType.Triggerable] then
756-
skillModList:NewMod("Multiplier:SnipeStagesMax", "BASE", 6, "Snipe Max Stages", { type = "GlobalEffect", effectType = "Buff", unscalable = true })
757-
end
758754
if skillModList:Sum("BASE", nil, "CritMultiplierAppliesToDegen") > 0 then
759755
for i, value in ipairs(skillModList:Tabulate("BASE", skillCfg, "CritMultiplier")) do
760756
local mod = value.mod
@@ -1534,40 +1530,6 @@ function calcs.offence(env, actor, activeSkill)
15341530
skillModList:NewMod("PhysicalMax", "BASE", m_floor(output.ManaCost * multiplier), "Sacrificial Zeal", ModFlag.Spell)
15351531
end
15361532

1537-
-- account for Manaforged Arrows
1538-
if skillData.triggeredByManaPercentSpent and skillData.triggerSource then
1539-
local reqManaCostMulti = skillData.TriggerSkillManaSpentMultiRequirement
1540-
local uuid = cacheSkillUUID(skillData.triggerSource)
1541-
if GlobalCache.cachedData["CACHE"][uuid] then
1542-
local cachedTriggerData = GlobalCache.cachedData["CACHE"][uuid]
1543-
local manaThreshold = output.ManaCost * reqManaCostMulti
1544-
local manaSpendPerSec = cachedTriggerData.ManaCost * cachedTriggerData.Speed
1545-
local manaSpendTriggerRate = manaSpendPerSec / manaThreshold
1546-
output.SourceTriggerRate = manaSpendTriggerRate
1547-
local trigRate = m_min(manaSpendTriggerRate, skillData.triggerRate)
1548-
-- Account for chance to trigger
1549-
local manaforgeTriggerChance = 100.0
1550-
trigRate = trigRate * manaforgeTriggerChance / 100.0
1551-
if breakdown then
1552-
t_insert(breakdown.SimData, s_format(""))
1553-
t_insert(breakdown.SimData, s_format("and"))
1554-
t_insert(breakdown.SimData, s_format(""))
1555-
t_insert(breakdown.SimData, s_format("(%d ^8(trigger mana cost)", cachedTriggerData.ManaCost))
1556-
t_insert(breakdown.SimData, s_format("x %.2f) ^8(trigger attack speed)", cachedTriggerData.Speed))
1557-
t_insert(breakdown.SimData, s_format("/ (%d ^8(triggered skill mana cost)", output.ManaCost))
1558-
t_insert(breakdown.SimData, s_format("x %.2f) ^8(manaforge skill multiplier)", reqManaCostMulti))
1559-
t_insert(breakdown.SimData, s_format(""))
1560-
t_insert(breakdown.SimData, s_format("Trigger Skill Mana-spending trigger rate:"))
1561-
t_insert(breakdown.SimData, s_format("= %.2f ^8per second", manaSpendTriggerRate))
1562-
breakdown.ServerTriggerRate = {
1563-
s_format("%.2f ^8(smaller of 'cap' and 'skill' trigger rates)", trigRate),
1564-
}
1565-
end
1566-
activeSkill.skillData.triggerRate = trigRate
1567-
output.ServerTriggerRate = trigRate
1568-
end
1569-
end
1570-
15711533
runSkillFunc("preDamageFunc")
15721534

15731535
-- Handle corpse and enemy explosions
@@ -1982,7 +1944,7 @@ function calcs.offence(env, actor, activeSkill)
19821944
output.Speed = output.Speed * totemActionSpeed
19831945
output.CastRate = output.Speed
19841946
end
1985-
if output.Cooldown then
1947+
if output.Cooldown and not activeSkill.skillTypes[SkillType.Channel] then
19861948
output.Speed = m_min(output.Speed, 1 / output.Cooldown * output.Repeats)
19871949
end
19881950
if output.Cooldown and skillFlags.selfCast then
@@ -2036,9 +1998,14 @@ function calcs.offence(env, actor, activeSkill)
20361998
end
20371999
elseif skillData.hitTimeMultiplier and output.Time and not skillData.triggeredOnDeath then
20382000
output.HitTime = output.Time * skillData.hitTimeMultiplier
2039-
output.HitSpeed = 1 / output.HitTime
2001+
if output.Cooldown and skillData.triggered then
2002+
output.HitSpeed = 1 / (m_max(output.HitTime, output.Cooldown))
2003+
elseif output.Cooldown then
2004+
output.HitSpeed = 1 / (output.HitTime + output.Cooldown)
2005+
else
2006+
output.HitSpeed = 1 / output.HitTime
2007+
end
20402008
end
2041-
20422009
-- Other Misc DPS multipliers (like custom source)
20432010
skillData.dpsMultiplier = ( skillData.dpsMultiplier or 1 ) * ( 1 + skillModList:Sum("INC", cfg, "DPS") / 100 ) * skillModList:More(cfg, "DPS")
20442011
if env.configInput.repeatMode == "FINAL" or skillModList:Flag(nil, "OnlyFinalRepeat") then
@@ -2056,6 +2023,7 @@ function calcs.offence(env, actor, activeSkill)
20562023
combineStat("HitChance", "AVERAGE")
20572024
combineStat("Speed", "AVERAGE")
20582025
combineStat("HitSpeed", "OR")
2026+
combineStat("HitTime", "OR")
20592027
if output.Speed == 0 then
20602028
output.Time = 0
20612029
else
@@ -2073,6 +2041,47 @@ function calcs.offence(env, actor, activeSkill)
20732041
}
20742042
end
20752043
end
2044+
if skillData.hitTimeOverride and not skillData.triggeredOnDeath then
2045+
output.HitTime = skillData.hitTimeOverride
2046+
output.HitSpeed = 1 / output.HitTime
2047+
elseif skillData.hitTimeMultiplier and output.Time and not skillData.triggeredOnDeath then
2048+
output.HitTime = output.Time * skillData.hitTimeMultiplier
2049+
if output.Cooldown and skillData.triggered then
2050+
output.HitSpeed = 1 / (m_max(output.HitTime, output.Cooldown))
2051+
elseif output.Cooldown then
2052+
output.HitSpeed = 1 / (output.HitTime + output.Cooldown)
2053+
else
2054+
output.HitSpeed = m_min(1 / output.HitTime, data.misc.ServerTickRate)
2055+
end
2056+
end
2057+
end
2058+
if breakdown then
2059+
if skillData.hitTimeOverride and not skillData.triggeredOnDeath then
2060+
breakdown.HitSpeed = { }
2061+
t_insert(breakdown.HitSpeed, s_format("1 / %.2f ^8(hit time override)", output.HitTime))
2062+
t_insert(breakdown.HitSpeed, s_format("= %.2f", output.HitSpeed))
2063+
elseif skillData.hitTimeMultiplier and output.Time and not skillData.triggeredOnDeath then
2064+
breakdown.HitTime = { }
2065+
if m_floor(skillData.hitTimeMultiplier) ~= skillData.hitTimeMultiplier then
2066+
t_insert(breakdown.HitTime, s_format(colorCodes.CUSTOM.."NOTE: First stage has a %.2fx channel time multiplier", skillData.hitTimeMultiplier - m_floor(skillData.hitTimeMultiplier)))
2067+
end
2068+
if isAttack then
2069+
t_insert(breakdown.HitTime, s_format("%.2f ^8(attack time)", output.Time))
2070+
else
2071+
t_insert(breakdown.HitTime, s_format("%.2f ^8(cast time)", output.Time))
2072+
end
2073+
t_insert(breakdown.HitTime, s_format("x %.2f ^8(channel time multiplier)", skillData.hitTimeMultiplier))
2074+
t_insert(breakdown.HitTime, s_format("= %.2f", output.HitTime))
2075+
breakdown.HitSpeed = { }
2076+
if output.Cooldown and skillData.triggered then
2077+
t_insert(breakdown.HitSpeed, s_format("1 / min(%.2f, %.2f) ^8min(hit time, cooldown)", output.HitTime, output.Cooldown))
2078+
elseif output.Cooldown then
2079+
t_insert(breakdown.HitSpeed, s_format("1 / (%.2f + %.2f) ^8(hit time + cooldown)", output.HitTime, output.Cooldown))
2080+
else
2081+
t_insert(breakdown.HitSpeed, s_format("1 / %.2f ^8(hit time)", output.HitTime))
2082+
end
2083+
t_insert(breakdown.HitSpeed, s_format("= %.2f", output.HitSpeed))
2084+
end
20762085
end
20772086

20782087
-- Grab quantity multiplier

src/Modules/CalcSections.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,8 @@ return {
500500
{ label = "Skill Trigger Rate", flag = "triggered", notFlag = "focused", { format = "{2:output:SkillTriggerRate}", { breakdown = "SkillTriggerRate" }, { breakdown = "SimData" }, }, },
501501
{ label = "Skill Trigger Rate", flagList = {"triggered", "focused"}, { format = "{2:output:SkillTriggerRate}", { breakdown = "SkillTriggerRate" }, { breakdown = "SimData" }, { modName = "FocusCooldownRecovery", modType = "INC", cfg = "skill", }, }, },
502502
{ label = "Cast time", flag = "spell", notFlag = "triggered", { format = "{2:output:Time}s", }, },
503+
{ label = "Channel time", haveOutput = "HitTime", { format = "{2:output:HitTime}s", { breakdown = "HitTime" } }, },
504+
{ label = "Hit Rate", haveOutput = "HitSpeed", { format = "{2:output:HitSpeed}", { breakdown = "HitSpeed" } }, },
503505
} }
504506
} },
505507
{ 1, "Crit", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Crits", data = {

0 commit comments

Comments
 (0)