From 2ab933db903a94a28807a16e0a4425ca4c82cb07 Mon Sep 17 00:00:00 2001 From: Bobastic Date: Sat, 7 Feb 2026 11:15:41 +0100 Subject: [PATCH 1/2] fix: fixed KF damage calcs --- src/Data/Skills/act_int.lua | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua index dbba37c151..cd26b6f533 100644 --- a/src/Data/Skills/act_int.lua +++ b/src/Data/Skills/act_int.lua @@ -11202,12 +11202,11 @@ skills["KineticFusillade"] = { -- Calculate effective attack rate accounting for delayed projectile firing -- Projectiles orbit for base_skill_effect_duration before firing -- Recasting resets the timer, so attacking too fast wastes potential damage - local baseDuration = skillData.duration - local actualDuration = output.Duration or baseDuration - local ticksNeededForInitialDelay = math.ceil(actualDuration / data.misc.ServerTickTime) - local timePerProjectile = baseDelayBetweenProjectiles * output.DurationMod - local timeForAllProjectiles = timePerProjectile * projectileCount - local effectiveDelay = ticksNeededForInitialDelay * data.misc.ServerTickTime + math.ceil(timeForAllProjectiles / data.misc.ServerTickTime) * data.misc.ServerTickTime + -- Formula: totalTime = (hoverDelay + delayBetweenProj * nProj) * durationMod + local hoverDelay = skillData.duration + local durationMod = output.DurationMod + local baseTimeForAllProjectiles = baseDelayBetweenProjectiles * projectileCount + local effectiveDelay = (hoverDelay + baseTimeForAllProjectiles) * durationMod local maxEffectiveAPS = 1 / effectiveDelay local currentAPS = output.Speed @@ -11216,12 +11215,12 @@ skills["KineticFusillade"] = { if breakdown then local breakdownAPS = {} t_insert(breakdownAPS, s_format("^1(These calculations are speculative and best-effort)", actualDuration)) - t_insert(breakdownAPS, s_format("^8Delay of^7 %.3fs ^8before projectiles start firing", actualDuration)) - t_insert(breakdownAPS, s_format("^8Each projectile fires sequentially with a^7 %.3fs ^8delay between each projectile", timePerProjectile)) - t_insert(breakdownAPS, s_format("^8Server tick time:^7 %.3fs", data.misc.ServerTickTime)) - t_insert(breakdownAPS, s_format("^8Ticks needed:^7 %d ^8(rounded up)", ticksNeededForInitialDelay + math.ceil(timeForAllProjectiles / data.misc.ServerTickTime))) - t_insert(breakdownAPS, s_format("^8Effective delay:^7 %.3fs", effectiveDelay)) - t_insert(breakdownAPS, s_format("^8Max effective attack rate:^7 1 / %.3f = %.2f", effectiveDelay, maxEffectiveAPS)) + t_insert(breakdownAPS, s_format("^8Base hover delay:^7 %.3fs", hoverDelay)) + t_insert(breakdownAPS, s_format("^8Base delay between projectiles:^7 %.3fs", baseDelayBetweenProjectiles)) + t_insert(breakdownAPS, s_format("^8Base time for^7 %d ^8projectiles:^7 %.3fs x %d = %.3fs", projectileCount, baseDelayBetweenProjectiles, projectileCount, baseTimeForAllProjectiles)) + t_insert(breakdownAPS, s_format("^8Duration modifier:^7 %.4f", durationMod)) + t_insert(breakdownAPS, s_format("^8Effective delay:^7 (%.3f + %.3f) x %.4f = %.4fs", hoverDelay, baseTimeForAllProjectiles, durationMod, effectiveDelay)) + t_insert(breakdownAPS, s_format("^8Max effective attack rate:^7 1 / %.4f = %.2f", effectiveDelay, maxEffectiveAPS)) if currentAPS and currentAPS > maxEffectiveAPS then t_insert(breakdownAPS, "") t_insert(breakdownAPS, s_format("^1Current attack rate (%.2f) exceeds max effective rate!", currentAPS)) From 84fde2a76274f88555b2e12b825748ab8273b1c3 Mon Sep 17 00:00:00 2001 From: Bobastic Date: Sat, 7 Feb 2026 11:40:18 +0100 Subject: [PATCH 2/2] feat: gave attack speed indicators to reach the breakpoints --- src/Data/Skills/act_int.lua | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua index cd26b6f533..d49701ea0a 100644 --- a/src/Data/Skills/act_int.lua +++ b/src/Data/Skills/act_int.lua @@ -11214,20 +11214,26 @@ skills["KineticFusillade"] = { if breakdown then local breakdownAPS = {} - t_insert(breakdownAPS, s_format("^1(These calculations are speculative and best-effort)", actualDuration)) + t_insert(breakdownAPS, s_format("^1(These calculations are speculative and best-effort)")) t_insert(breakdownAPS, s_format("^8Base hover delay:^7 %.3fs", hoverDelay)) t_insert(breakdownAPS, s_format("^8Base delay between projectiles:^7 %.3fs", baseDelayBetweenProjectiles)) t_insert(breakdownAPS, s_format("^8Base time for^7 %d ^8projectiles:^7 %.3fs x %d = %.3fs", projectileCount, baseDelayBetweenProjectiles, projectileCount, baseTimeForAllProjectiles)) t_insert(breakdownAPS, s_format("^8Duration modifier:^7 %.4f", durationMod)) t_insert(breakdownAPS, s_format("^8Effective delay:^7 (%.3f + %.3f) x %.4f = %.4fs", hoverDelay, baseTimeForAllProjectiles, durationMod, effectiveDelay)) t_insert(breakdownAPS, s_format("^8Max effective attack rate:^7 1 / %.4f = %.2f", effectiveDelay, maxEffectiveAPS)) - if currentAPS and currentAPS > maxEffectiveAPS then - t_insert(breakdownAPS, "") - t_insert(breakdownAPS, s_format("^1Current attack rate (%.2f) exceeds max effective rate!", currentAPS)) - t_insert(breakdownAPS, s_format("^1DPS is reduced by %.1f%%", (1 - maxEffectiveAPS / currentAPS) * 100)) - elseif currentAPS then + if currentAPS then + local currentInc = activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "Speed") + local neededInc = ((maxEffectiveAPS / currentAPS) * (1 + currentInc / 100) - 1) * 100 + local additionalInc = neededInc - currentInc t_insert(breakdownAPS, "") - t_insert(breakdownAPS, s_format("^2Current attack rate (%.2f) is within effective limits", currentAPS)) + if currentAPS > maxEffectiveAPS then + t_insert(breakdownAPS, s_format("^1Current attack rate (%.2f) exceeds max effective rate!", currentAPS)) + t_insert(breakdownAPS, s_format("^1Reduce attack speed by at least^7 %d%% ^1", math.ceil(-additionalInc))) + t_insert(breakdownAPS, s_format("^1DPS is reduced by %.1f%%", (1 - maxEffectiveAPS / currentAPS) * 100)) + else + t_insert(breakdownAPS, s_format("^2Current attack rate (%.2f) is within effective limits", currentAPS)) + t_insert(breakdownAPS, s_format("^2You can add up to^7 %d%% ^2increased attack speed", math.floor(additionalInc))) + end end breakdown.KineticFusilladeMaxEffectiveAPS = breakdownAPS end