Skip to content
Closed
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
37 changes: 37 additions & 0 deletions src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2419,6 +2419,43 @@ function calcs.perform(env, avoidCache)
end
end

local supportedByPhantasm = false
if env.player.mainSkill.socketGroup ~= nil and env.player.mainSkill.socketGroup.gemList ~= nil then
for _, gem in ipairs(env.player.mainSkill.socketGroup.gemList) do
if gem.nameSpec == "Summon Phantasm" then
supportedByPhantasm = true
end
end
end

if supportedByPhantasm and not env.player.mainSkill.marked then
local calcMode = env.mode == "CALCS" and "CALCS" or "MAIN"
-- First, create a copy of the main skill that is supported by phantasm
local newSkill, newEnv = calcs.copyActiveSkill(env, calcMode, env.player.mainSkill)
-- Override srcInstance with a copy to break the link with UI changes
newSkill.activeEffect.srcInstance = copyTable(newSkill.activeEffect.srcInstance, true)
-- Override selected active minion and minion skill
newSkill.activeEffect.srcInstance.skillMinion = "SummonedPhantasm"
newSkill.activeEffect.srcInstance.skillMinionSkill = 2 -- Physical Projectile
-- Now we need to copy it again to trigger newEnv.minion recalculation for phantasms
newSkill, newEnv = calcs.copyActiveSkill(env, calcMode, newSkill)

-- Assign as a main skill and perform calc
newEnv.player.mainSkill = newSkill
-- mark it so we don't recurse infinitely
newSkill.marked = true
newEnv.dontCache = true
calcs.perform(newEnv)

-- Store the output for later display
env.player.mainSkill.phantasm = { }
env.player.mainSkill.phantasm.count = newEnv.player.output.ActiveMinionLimit -- Correctly handles bonuses from Replica Midnight Bargain and gem level
env.player.mainSkill.phantasm.name = "Summoned Phantasm"
env.player.mainSkill.phantasm.source = env.player.mainSkill.activeEffect.grantedEffect.name -- Source skill name
env.player.mainSkill.phantasm.minion = {}
env.player.mainSkill.phantasm.minion.output = newEnv.minion.output
end

-- Mirage Archer Support
-- This creates and populates env.player.mainSkill.mirage table
if env.player.mainSkill.skillData.triggeredByMirageArcher and not env.player.mainSkill.skillFlags.minion and not env.player.mainSkill.marked then
Expand Down
30 changes: 30 additions & 0 deletions src/Modules/Calcs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,36 @@ function calcs.calcFullDPS(build, mode, override, specEnv)
end
end

if activeSkill.phantasm then
if activeSkill.phantasm.minion.output.TotalDPS and activeSkill.phantasm.minion.output.TotalDPS > 0 then
t_insert(fullDPS.skills, { name = activeSkill.phantasm.name, dps = activeSkill.phantasm.minion.output.TotalDPS, count = activeSkill.phantasm.count, trigger = activeSkill.infoTrigger, skillPart = "Summoned by: "..activeSkill.phantasm.source })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Summon Phantasm supporting a player skill, addMinionList = { "SummonedPhantasm" } already makes the generic minion block above emit the selected Phantasm contribution. This added row then emits the same group again. The exact-HEAD fixture produced hit rows of 7 x 2 and 7 x 5 (plus the distinct source's 3 x 2), yielding 55 instead of the deduplicated 41. Skipping the generic row only when it represents that same selected SummonedPhantasm removed the duplicate while preserving a distinct source minion.

AI-assisted review disclosure: This finding was identified during a review using OpenAI Codex and confirmed with a focused reproduction.

fullDPS.combinedDPS = fullDPS.combinedDPS + activeSkill.phantasm.minion.output.TotalDPS * activeSkill.phantasm.count
end
if activeSkill.phantasm.minion.output.BleedDPS and activeSkill.phantasm.minion.output.BleedDPS > fullDPS.bleedDPS then
fullDPS.bleedDPS = activeSkill.phantasm.minion.output.BleedDPS
bleedSource = activeSkill.activeEffect.grantedEffect.name
end
if activeSkill.phantasm.minion.output.IgniteDPS and activeSkill.phantasm.minion.output.IgniteDPS > fullDPS.igniteDPS then
fullDPS.igniteDPS = activeSkill.phantasm.minion.output.IgniteDPS
igniteSource = activeSkill.activeEffect.grantedEffect.name
end
if activeSkill.phantasm.minion.output.PoisonDPS and activeSkill.phantasm.minion.output.PoisonDPS > 0 then
fullDPS.poisonDPS = fullDPS.poisonDPS + activeSkill.phantasm.minion.output.PoisonDPS * (activeSkill.phantasm.minion.output.TotalPoisonStacks or 1) * activeSkillCount
end
if activeSkill.phantasm.minion.output.ImpaleDPS and activeSkill.phantasm.minion.output.ImpaleDPS > 0 then
fullDPS.impaleDPS = fullDPS.impaleDPS + activeSkill.phantasm.minion.output.ImpaleDPS * activeSkillCount
Comment on lines +236 to +239

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here activeSkillCount is the count of the source socket group, whereas the Phantasm cap calculated by this PR is stored in activeSkill.phantasm.count. In an asymmetric reproduction on this exact HEAD (source count 2, Phantasm count 5), this block contributes poison and impale using x2 rather than x5, so those components are not included at the maximum Phantasm limit promised by the PR. Using activeSkill.phantasm.count for both explicit accumulators produced the expected per-Phantasm totals in the focused reproduction.

AI-assisted review disclosure: This finding was identified during a review using OpenAI Codex and confirmed with a focused reproduction.

end
if activeSkill.phantasm.minion.output.DecayDPS and activeSkill.phantasm.minion.output.DecayDPS > 0 then
fullDPS.decayDPS = fullDPS.decayDPS + activeSkill.phantasm.minion.output.DecayDPS
end
if activeSkill.phantasm.minion.output.TotalDot and activeSkill.phantasm.minion.output.TotalDot > 0 then
fullDPS.dotDPS = fullDPS.dotDPS + activeSkill.phantasm.minion.output.TotalDot
end
if activeSkill.phantasm.minion.output.CullMultiplier and activeSkill.phantasm.minion.output.CullMultiplier > 1 and activeSkill.phantasm.minion.output.CullMultiplier > fullDPS.cullingMulti then
fullDPS.cullingMulti = activeSkill.phantasm.minion.output.CullMultiplier
end
end

if activeSkill.mirage then
local mirageCount = (activeSkill.mirage.count or 1) * activeSkillCount
if activeSkill.mirage.output.TotalDPS and activeSkill.mirage.output.TotalDPS > 0 then
Expand Down