Skip to content

Commit dc9bb24

Browse files
author
LocalIdentity
committed
Kinetic Fusilade export
1 parent c2ee5eb commit dc9bb24

File tree

2 files changed

+117
-5
lines changed

2 files changed

+117
-5
lines changed

src/Data/Skills/act_int.lua

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11142,9 +11142,117 @@ skills["KineticFusillade"] = {
1114211142
},
1114311143
statDescriptionScope = "skill_stat_descriptions",
1114411144
castTime = 1,
11145+
parts = {
11146+
{
11147+
name = "All Projectiles",
11148+
},
11149+
{
11150+
name = "1 Projectile"
11151+
},
11152+
},
11153+
preDamageFunc = function(activeSkill, output, breakdown)
11154+
local skillData = activeSkill.skillData
11155+
local t_insert = table.insert
11156+
local s_format = string.format
11157+
11158+
if activeSkill.skillPart == 1 then
11159+
-- Set base dpsMultiplier for projectile count
11160+
activeSkill.skillData.dpsMultiplier = output.ProjectileCount
11161+
11162+
-- Calculate average damage scaling for sequential projectiles
11163+
-- Each projectile does more damage based on how many came before it
11164+
local moreDamagePerProj = skillData.damagePerProjectile or 0
11165+
if moreDamagePerProj ~= 0 and output.ProjectileCount > 1 then
11166+
-- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n
11167+
-- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2
11168+
local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2
11169+
activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", ModFlag.Hit)
11170+
11171+
-- Store the average multiplier for display
11172+
output.KineticFusilladeAvgMoreMult = avgMoreMult
11173+
11174+
if breakdown then
11175+
local breakdownSequential = {}
11176+
t_insert(breakdownSequential, s_format("^8Each projectile deals^7 %d%%^8 more damage per previous projectile", moreDamagePerProj))
11177+
t_insert(breakdownSequential, s_format("^8With^7 %d^8 projectiles, damage progression is:^7", output.ProjectileCount))
11178+
for i = 1, output.ProjectileCount do
11179+
local projMult = moreDamagePerProj * (i - 1)
11180+
t_insert(breakdownSequential, s_format(" ^8Projectile %d:^7 %d%%^8 more damage", i, projMult))
11181+
end
11182+
t_insert(breakdownSequential, s_format("^8Average more multiplier:^7 %.1f%%", avgMoreMult))
11183+
breakdown.KineticFusilladeSequentialBreakdown = breakdownSequential
11184+
end
11185+
end
11186+
end
11187+
end,
11188+
postCritFunc = function(activeSkill, output, breakdown)
11189+
local skillData = activeSkill.skillData
11190+
local t_insert = table.insert
11191+
local s_format = string.format
11192+
11193+
local baseDelayBetweenProjectiles = skillData.delayPerProjectile
11194+
local projectileCount = 1
11195+
11196+
if activeSkill.skillPart == 1 then
11197+
projectileCount = output.ProjectileCount
11198+
end
11199+
11200+
-- Calculate effective attack rate accounting for delayed projectile firing
11201+
-- Projectiles orbit for base_skill_effect_duration before firing
11202+
-- Recasting resets the timer, so attacking too fast wastes potential damage
11203+
local baseDuration = skillData.duration
11204+
local actualDuration = output.Duration or baseDuration
11205+
local ticksNeededForInitialDelay = math.ceil(actualDuration / data.misc.ServerTickTime)
11206+
local timePerProjectile = baseDelayBetweenProjectiles * output.DurationMod
11207+
local timeForAllProjectiles = timePerProjectile * projectileCount
11208+
local effectiveDelay = ticksNeededForInitialDelay * data.misc.ServerTickTime + math.ceil(timeForAllProjectiles / data.misc.ServerTickTime) * data.misc.ServerTickTime
11209+
local maxEffectiveAPS = 1 / effectiveDelay
11210+
local currentAPS = output.Speed
11211+
11212+
output.KineticFusilladeMaxEffectiveAPS = maxEffectiveAPS
11213+
11214+
if breakdown then
11215+
local breakdownAPS = {}
11216+
t_insert(breakdownAPS, s_format("^1(These calculations are speculative and best-effort)", actualDuration))
11217+
t_insert(breakdownAPS, s_format("^8Delay of^7 %.3fs ^8before projectiles start firing", actualDuration))
11218+
t_insert(breakdownAPS, s_format("^8Each projectile fires sequentially with a^7 %.3fs ^8delay between each projectile", timePerProjectile))
11219+
t_insert(breakdownAPS, s_format("^8Server tick time:^7 %.3fs", data.misc.ServerTickTime))
11220+
t_insert(breakdownAPS, s_format("^8Ticks needed:^7 %d ^8(rounded up)", ticksNeededForInitialDelay + math.ceil(timeForAllProjectiles / data.misc.ServerTickTime)))
11221+
t_insert(breakdownAPS, s_format("^8Effective delay:^7 %.3fs", effectiveDelay))
11222+
t_insert(breakdownAPS, s_format("^8Max effective attack rate:^7 1 / %.3f = %.2f", effectiveDelay, maxEffectiveAPS))
11223+
if currentAPS and currentAPS > maxEffectiveAPS then
11224+
t_insert(breakdownAPS, "")
11225+
t_insert(breakdownAPS, s_format("^1Current attack rate (%.2f) exceeds max effective rate!", currentAPS))
11226+
t_insert(breakdownAPS, s_format("^1DPS is reduced by %.1f%%", (1 - maxEffectiveAPS / currentAPS) * 100))
11227+
elseif currentAPS then
11228+
t_insert(breakdownAPS, "")
11229+
t_insert(breakdownAPS, s_format("^2Current attack rate (%.2f) is within effective limits", currentAPS))
11230+
end
11231+
breakdown.KineticFusilladeMaxEffectiveAPS = breakdownAPS
11232+
end
11233+
11234+
-- Adjust dpsMultiplier if attacking too fast (only for "All Projectiles" mode)
11235+
if activeSkill.skillPart == 1 then
11236+
if currentAPS and currentAPS > maxEffectiveAPS then
11237+
local efficiencyRatio = maxEffectiveAPS / currentAPS
11238+
local originalMultiplier = skillData.dpsMultiplier or output.ProjectileCount
11239+
skillData.dpsMultiplier = originalMultiplier * efficiencyRatio
11240+
end
11241+
end
11242+
end,
11243+
statMap = {
11244+
["kinetic_fusillade_damage_+%_final_per_projectile_fired"] = {
11245+
skill("damagePerProjectile", nil),
11246+
},
11247+
["kinetic_fusillade_base_delay_between_projectiles_ms+%_final_per_projectile_fired"] = {
11248+
skill("delayPerProjectile", nil),
11249+
div = 1000,
11250+
},
11251+
["quality_display_kinetic_fusillade_is_gem"] = {
11252+
},
11253+
},
1114511254
baseFlags = {
1114611255
attack = true,
11147-
projectile = true,
1114811256
area = true,
1114911257
duration = true,
1115011258
},

src/Export/Skills/act_int.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,7 +2264,7 @@ local skills, mod, flag, skill = ...
22642264
#mods
22652265

22662266
#skill KineticFusillade
2267-
#flags attack projectile area duration
2267+
#flags attack area duration
22682268
parts = {
22692269
{
22702270
name = "All Projectiles",
@@ -2284,7 +2284,7 @@ local skills, mod, flag, skill = ...
22842284

22852285
-- Calculate average damage scaling for sequential projectiles
22862286
-- Each projectile does more damage based on how many came before it
2287-
local moreDamagePerProj = skillData.KineticFusilladeSequentialDamage or 0
2287+
local moreDamagePerProj = skillData.damagePerProjectile or 0
22882288
if moreDamagePerProj ~= 0 and output.ProjectileCount > 1 then
22892289
-- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n
22902290
-- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2
@@ -2313,7 +2313,7 @@ local skills, mod, flag, skill = ...
23132313
local t_insert = table.insert
23142314
local s_format = string.format
23152315

2316-
local baseDelayBetweenProjectiles = 0.05
2316+
local baseDelayBetweenProjectiles = skillData.delayPerProjectile
23172317
local projectileCount = 1
23182318

23192319
if activeSkill.skillPart == 1 then
@@ -2365,7 +2365,11 @@ local skills, mod, flag, skill = ...
23652365
end,
23662366
statMap = {
23672367
["kinetic_fusillade_damage_+%_final_per_projectile_fired"] = {
2368-
skill("KineticFusilladeSequentialDamage", nil),
2368+
skill("damagePerProjectile", nil),
2369+
},
2370+
["kinetic_fusillade_base_delay_between_projectiles_ms+%_final_per_projectile_fired"] = {
2371+
skill("delayPerProjectile", nil),
2372+
div = 1000,
23692373
},
23702374
["quality_display_kinetic_fusillade_is_gem"] = {
23712375
},

0 commit comments

Comments
 (0)