Skip to content
Open
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
6 changes: 5 additions & 1 deletion src/Data/Skills/act_int.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14013,7 +14013,11 @@ skills["PenanceBrandAltY"] = {
statDescriptionScope = "brand_skill_stat_descriptions",
castTime = 0.75,
preDamageFunc = function(activeSkill, output)
activeSkill.skillData.hitTimeOverride = activeSkill.skillData.repeatFrequency / (1 + activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "Speed", "BrandActivationFrequency") / 100) / activeSkill.skillModList:More(activeSkill.skillCfg, "BrandActivationFrequency")
-- Activating only spreads energy; damage is dealt once, when the brand detaches at the end
-- of its attached duration, so this brand hits once per cast rather than once per activation
activeSkill.skillData.brandActivationTime = activeSkill.skillData.repeatFrequency / (1 + activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "Speed", "BrandActivationFrequency") / 100) / activeSkill.skillModList:More(activeSkill.skillCfg, "BrandActivationFrequency")
activeSkill.skillData.hitTimeOverride = output.Duration or 0
activeSkill.skillData.hitTimeCappedByCastTime = true
end,
baseFlags = {
spell = true,
Expand Down
6 changes: 5 additions & 1 deletion src/Export/Skills/act_int.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3322,7 +3322,11 @@ local skills, mod, flag, skill = ...
#skill PenanceBrandAltY
#flags spell area duration brand
preDamageFunc = function(activeSkill, output)
activeSkill.skillData.hitTimeOverride = activeSkill.skillData.repeatFrequency / (1 + activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "Speed", "BrandActivationFrequency") / 100) / activeSkill.skillModList:More(activeSkill.skillCfg, "BrandActivationFrequency")
-- Activating only spreads energy; damage is dealt once, when the brand detaches at the end
-- of its attached duration, so this brand hits once per cast rather than once per activation
activeSkill.skillData.brandActivationTime = activeSkill.skillData.repeatFrequency / (1 + activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "Speed", "BrandActivationFrequency") / 100) / activeSkill.skillModList:More(activeSkill.skillCfg, "BrandActivationFrequency")
activeSkill.skillData.hitTimeOverride = output.Duration or 0
activeSkill.skillData.hitTimeCappedByCastTime = true
end,
#baseMod skill("radius", 28)
#baseMod skill("showAverage", true)
Expand Down
31 changes: 29 additions & 2 deletions src/Modules/CalcOffence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,10 @@ function calcs.offence(env, actor, activeSkill)
local storedMainHandAccuracy = nil
local storedMainHandAccuracyVsEnemy = nil
local storedSustainedTraumaBreakdown = { }
-- Skills flagged hitTimeCappedByCastTime hit once per use, so their total hit rate is limited by
-- how fast those uses can be created. Brands need one use per attached brand, matching the
-- AttachedBrandCount factor applied to dpsMultiplier below
local hitInstancesPerUse = (activeSkill.skillTypes[SkillType.Brand] and not skillData.countsAttachedBrandsInDamage and output.AttachedBrandCount) or 1
-- Calculate how often you hit (speed, accuracy, block, etc)
for _, pass in ipairs(passList) do
globalOutput, globalBreakdown = output, breakdown
Expand Down Expand Up @@ -2402,10 +2406,15 @@ function calcs.offence(env, actor, activeSkill)
end
if skillData.hitTimeOverride and not skillData.triggeredOnDeath then
output.HitTime = skillData.hitTimeOverride
if skillData.hitTimeCappedByCastTime and output.Time then
-- Skill hits once per use, so it cannot hit more often than those uses can be created
output.HitTime = m_max(output.HitTime, output.Time * hitInstancesPerUse)
end
output.HitSpeed = 1 / output.HitTime
--Brands always have hitTimeOverride
if activeSkill.skillTypes[SkillType.Brand] and not skillModList:Flag(nil, "UnlimitedBrandDuration") then
output.BrandTicks = m_floor(output.Duration * output.HitSpeed)
-- Brands that don't hit on every activation track their activation interval separately
output.BrandTicks = m_floor(output.Duration / (skillData.brandActivationTime or output.HitTime))
end
elseif skillData.hitTimeMultiplier and output.Time and not skillData.triggeredOnDeath then
output.HitTime = output.Time * skillData.hitTimeMultiplier
Expand Down Expand Up @@ -2473,6 +2482,10 @@ function calcs.offence(env, actor, activeSkill)
end
if skillData.hitTimeOverride and not skillData.triggeredOnDeath then
output.HitTime = skillData.hitTimeOverride
if skillData.hitTimeCappedByCastTime and output.Time then
-- Skill hits once per use, so it cannot hit more often than those uses can be created
output.HitTime = m_max(output.HitTime, output.Time * hitInstancesPerUse)
end
output.HitSpeed = 1 / output.HitTime
elseif skillData.hitTimeMultiplier and output.Time and not skillData.triggeredOnDeath then
output.HitTime = output.Time * skillData.hitTimeMultiplier
Expand All @@ -2488,7 +2501,21 @@ function calcs.offence(env, actor, activeSkill)
if breakdown then
if skillData.hitTimeOverride and not skillData.triggeredOnDeath then
breakdown.HitSpeed = { }
t_insert(breakdown.HitSpeed, s_format("1 / %.2f ^8(hit time override)", output.HitTime))
if skillData.hitTimeCappedByCastTime and output.Time then
local useType = isAttack and "attack" or "cast"
t_insert(breakdown.HitSpeed, "Skill only hits once per use:")
t_insert(breakdown.HitSpeed, s_format("%.2fs ^8(base hit time)", skillData.hitTimeOverride))
if hitInstancesPerUse > 1 then
t_insert(breakdown.HitSpeed, s_format("%.2fs ^8(%s time x %d attached brands)", output.Time * hitInstancesPerUse, useType, hitInstancesPerUse))
else
t_insert(breakdown.HitSpeed, s_format("%.2fs ^8(%s time)", output.Time, useType))
end
t_insert(breakdown.HitSpeed, s_format("= %.2fs ^8(hit time, higher of the two)", output.HitTime))
t_insert(breakdown.HitSpeed, s_format(""))
t_insert(breakdown.HitSpeed, s_format("1 / %.2f ^8(hit time)", output.HitTime))
else
t_insert(breakdown.HitSpeed, s_format("1 / %.2f ^8(hit time override)", output.HitTime))
end
t_insert(breakdown.HitSpeed, s_format("= %.2f", output.HitSpeed))
elseif skillData.hitTimeMultiplier and output.Time and not skillData.triggeredOnDeath then
breakdown.HitTime = { }
Expand Down
Loading