@@ -2265,6 +2265,100 @@ local skills, mod, flag, skill = ...
22652265
22662266#skill KineticFusillade
22672267#flags attack projectile area duration
2268+ parts = {
2269+ {
2270+ name = "1 Projectile"
2271+ },
2272+ {
2273+ name = "All Projectiles",
2274+ },
2275+ },
2276+ preDamageFunc = function(activeSkill, output, breakdown)
2277+ local skillData = activeSkill.skillData
2278+ local t_insert = table.insert
2279+ local s_format = string.format
2280+
2281+ if activeSkill.skillPart == 2 then
2282+ -- Set base dpsMultiplier for projectile count
2283+ activeSkill.skillData.dpsMultiplier = output.ProjectileCount
2284+
2285+ -- Calculate average damage scaling for sequential projectiles
2286+ -- Each projectile does more damage based on how many came before it
2287+ local moreDamagePerProj = skillData.KineticFusilladeSequentialDamage or 0
2288+ if moreDamagePerProj ~= 0 and output.ProjectileCount > 1 then
2289+ -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n
2290+ -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2
2291+ local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2
2292+ activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", ModFlag.Hit)
2293+
2294+ -- Store the average multiplier for display
2295+ output.KineticFusilladeAvgMoreMult = avgMoreMult
2296+
2297+ if breakdown then
2298+ local breakdownSequential = {}
2299+ t_insert(breakdownSequential, s_format("^8Each projectile deals^7 %d%%^8 more damage per previous projectile", moreDamagePerProj))
2300+ t_insert(breakdownSequential, s_format("^8With^7 %d^8 projectiles, damage progression is:^7", output.ProjectileCount))
2301+ for i = 1, output.ProjectileCount do
2302+ local projMult = moreDamagePerProj * (i - 1)
2303+ t_insert(breakdownSequential, s_format(" ^8Projectile %d:^7 %d%%^8 more damage", i, projMult))
2304+ end
2305+ t_insert(breakdownSequential, s_format("^8Average more multiplier:^7 %.1f%%", avgMoreMult))
2306+ breakdown.KineticFusilladeSequentialBreakdown = breakdownSequential
2307+ end
2308+ end
2309+ end
2310+ end,
2311+ postCritFunc = function(activeSkill, output, breakdown)
2312+ if activeSkill.skillPart == 2 then
2313+ local skillData = activeSkill.skillData
2314+ local t_insert = table.insert
2315+ local s_format = string.format
2316+
2317+ -- Calculate effective attack rate accounting for delayed projectile firing
2318+ -- Projectiles orbit for base_skill_effect_duration before firing
2319+ -- Recasting resets the timer, so attacking too fast wastes potential damage
2320+ local baseDuration = skillData.duration
2321+ local actualDuration = output.Duration or baseDuration
2322+ local ticksNeeded = math.ceil(actualDuration / data.misc.ServerTickTime)
2323+ local effectiveDelay = ticksNeeded * data.misc.ServerTickTime
2324+ local maxEffectiveAPS = 1 / effectiveDelay
2325+ local currentAPS = output.Speed
2326+
2327+ output.KineticFusilladeMaxEffectiveAPS = maxEffectiveAPS
2328+
2329+ if breakdown then
2330+ local breakdownAPS = {}
2331+ t_insert(breakdownAPS, s_format("^8Projectiles orbit for %.3fs before firing", actualDuration))
2332+ t_insert(breakdownAPS, s_format("^8Server tick time:^7 %.3fs", data.misc.ServerTickTime))
2333+ t_insert(breakdownAPS, s_format("^8Ticks needed:^7 %d ^8(rounded up)", ticksNeeded))
2334+ t_insert(breakdownAPS, s_format("^8Effective delay:^7 %.3fs", effectiveDelay))
2335+ t_insert(breakdownAPS, s_format("^8Max effective attack rate:^7 1 / %.3f = %.2f", effectiveDelay, maxEffectiveAPS))
2336+ if currentAPS and currentAPS > maxEffectiveAPS then
2337+ t_insert(breakdownAPS, "")
2338+ t_insert(breakdownAPS, s_format("^1Current attack rate (%.2f) exceeds max effective rate!", currentAPS))
2339+ t_insert(breakdownAPS, s_format("^1DPS is reduced by %.1f%%", (1 - maxEffectiveAPS / currentAPS) * 100))
2340+ elseif currentAPS then
2341+ t_insert(breakdownAPS, "")
2342+ t_insert(breakdownAPS, s_format("^2Current attack rate (%.2f) is within effective limits", currentAPS))
2343+ end
2344+ breakdown.KineticFusilladeMaxEffectiveAPS = breakdownAPS
2345+ end
2346+
2347+ -- Adjust dpsMultiplier if attacking too fast
2348+ if currentAPS and currentAPS > maxEffectiveAPS then
2349+ local efficiencyRatio = maxEffectiveAPS / currentAPS
2350+ local originalMultiplier = skillData.dpsMultiplier or output.ProjectileCount
2351+ skillData.dpsMultiplier = originalMultiplier * efficiencyRatio
2352+ end
2353+ end
2354+ end,
2355+ statMap = {
2356+ ["kinetic_fusillade_damage_+%_final_per_projectile_fired"] = {
2357+ skill("KineticFusilladeSequentialDamage", nil),
2358+ },
2359+ ["quality_display_kinetic_fusillade_is_gem"] = {
2360+ },
2361+ },
22682362#mods
22692363
22702364#skill KineticRain
0 commit comments