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
32 changes: 31 additions & 1 deletion spec/System/TestSkills_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,36 @@ describe("TestSkills", function()
assert.are.equals(warcryFirstDps, supportFirstDps)
end)

it("support-granted active skills inherit tree gem levels from the linked skill", function()
build.skillsTab:PasteSocketGroup("Despair 20/0 1\nDoedre's Undoing 1/0 1")
local socketGroup = build.skillsTab.socketGroupList[#build.skillsTab.socketGroupList]
recalculate()
local darkConsequences = selectActiveSkillById(socketGroup, "ChaosFrogExplosionPlayer")
assert.is_not_nil(darkConsequences)
assert.are.equals(20, darkConsequences.activeEffect.level)
assert.are.equals(20, build.calcsTab.mainOutput.GemLevel)
local baseDamage = build.calcsTab.mainOutput.AverageDamage

local chaosMasteryNode = build.spec.nodes[63074]
assert.are.equals("Dark Entries", chaosMasteryNode.dn)
assert.are.equals("+1 to Level of all Chaos Skills", chaosMasteryNode.sd[1])
chaosMasteryNode.alloc = true
build.spec.allocNodes[chaosMasteryNode.id] = chaosMasteryNode
recalculate()

darkConsequences = selectActiveSkillById(socketGroup, "ChaosFrogExplosionPlayer")
-- the support gem also matches "all Chaos Skills", but its own gem level modifiers
-- must not stack on top of the level inherited from Despair
assert.are.equals(21, darkConsequences.activeEffect.level)
assert.are.equals(21, build.calcsTab.mainOutput.GemLevel)
assert.True(build.calcsTab.mainOutput.AverageDamage > baseDamage)

local calcFunc, calcBase = build.calcsTab:GetMiscCalculator()
local withoutNode = calcFunc({ removeNodes = { [chaosMasteryNode] = true } })
assert.are.equals(21, calcBase.GemLevel)
assert.are.equals(20, withoutNode.GemLevel)
assert.True(withoutNode.AverageDamage < calcBase.AverageDamage)
end)
it("Flame Breath attack speed scales DPS and is not capped by its channel cooldown", function()
build.itemsTab:CreateDisplayItemFromRaw([[
New Item
Expand Down Expand Up @@ -2228,5 +2258,5 @@ describe("TestSkills", function()
local noParrySpellDmg = build.calcsTab.mainOutput.AverageDamage
assert.equals(withParrySpellDmg, noParrySpellDmg, "Parry should not affect spell damage")
end)

end)
15 changes: 11 additions & 4 deletions src/Modules/CalcActiveSkill.lua
Original file line number Diff line number Diff line change
Expand Up @@ -437,10 +437,15 @@ function calcs.buildActiveSkillModList(env, activeSkill)
skillFlags = activeEffect.statSet.skillFlags
end
-- Active skills granted by support gems inherit the level of the skill that support applied to.
local supportGrantedInheritedLevel
if activeEffect.gemData and activeEffect.gemData.grantedEffect.support then
for _, supportEffect in ipairs(activeSkill.supportList) do
if supportEffect.srcInstance == activeEffect.srcInstance and supportEffect.activeSkillLevel then
activeEffect.level = supportEffect.activeSkillLevel
for _, skill in ipairs(env.player.activeSkillList) do
local effect = skill.activeEffect
if effect ~= activeEffect and effect.level and skill.socketGroup == activeSkill.socketGroup
and not (effect.gemData and effect.gemData.grantedEffect.support) then
supportGrantedInheritedLevel = effect.level
activeEffect.level = effect.level
activeSkill.skillData.inheritsGemLevel = true
break
end
end
Expand Down Expand Up @@ -770,7 +775,9 @@ function calcs.buildActiveSkillModList(env, activeSkill)
end

-- Apply gem/quality modifiers from support gems
skillModList:NewMod("GemLevel", "BASE", activeSkill.activeEffect.srcInstance and activeSkill.activeEffect.srcInstance.level or activeSkill.activeEffect.level, "Max Level")
local gemMaxLevel = supportGrantedInheritedLevel or (activeSkill.activeEffect.srcInstance and activeSkill.activeEffect.srcInstance.level) or activeSkill.activeEffect.level
local gemMaxLevelSource = supportGrantedInheritedLevel and "Inherited Max Level" or "Max Level"
skillModList:NewMod("GemLevel", "BASE", gemMaxLevel, gemMaxLevelSource)
if activeSkill.activeEffect.srcInstance and activeSkill.activeEffect.srcInstance.corrupted and not (activeSkill.activeEffect.srcInstance.fromItem or activeSkill.activeEffect.srcInstance.fromTree or activeSkill.activeEffect.grantedEffect.fromItem or activeSkill.activeEffect.grantedEffect.fromTree) then
skillModList:NewMod("GemCorruptionLevel", "BASE", activeSkill.activeEffect.srcInstance.corruptLevel, "Corruption")
activeSkill.skillCfg.skillCond["GemCorrupted"] = true
Expand Down
26 changes: 15 additions & 11 deletions src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3658,22 +3658,26 @@ function calcs.perform(env, skipEHP)
local totalSupportLevel = mainSkill.skillModList:Sum("BASE", mainSkill.skillCfg, "GemSupportLevel")
local totalCorruptionLevel = mainSkill.skillModList:Sum("BASE", mainSkill.skillCfg, "GemCorruptionLevel")

local inheritsLevel = mainSkill.skillData.inheritsGemLevel
output.GemHasLevel = true
output.GemLevel = m_max(baseLevel + totalSupportLevel + totalItemLevel + totalCorruptionLevel, 1)
output.GemLevel = m_max(inheritsLevel and baseLevel or (baseLevel + totalSupportLevel + totalItemLevel + totalCorruptionLevel), 1)

if env.player.breakdown then
env.player.breakdown.GemLevel = {}
t_insert(env.player.breakdown.GemLevel, s_format("%d ^8(level from gem)", baseLevel))
if totalSupportLevel > 0 then
t_insert(env.player.breakdown.GemLevel, s_format("+ %d ^8(level from support)", totalSupportLevel))
end
if totalItemLevel > 0 then
t_insert(env.player.breakdown.GemLevel, s_format("+ %d ^8(level from items)", totalItemLevel))
end
if totalCorruptionLevel > 0 then
t_insert(env.player.breakdown.GemLevel, s_format("+ %d ^8(level from corruption)", totalCorruptionLevel))
elseif totalCorruptionLevel < 0 then
t_insert(env.player.breakdown.GemLevel, s_format("%d ^8(level from corruption)", totalCorruptionLevel))
-- support gems inherit levels from the parent gem, which means showing level modifiers is pointless
if not inheritsLevel then
if totalSupportLevel > 0 then
t_insert(env.player.breakdown.GemLevel, s_format("+ %d ^8(level from support)", totalSupportLevel))
end
if totalItemLevel > 0 then
t_insert(env.player.breakdown.GemLevel, s_format("+ %d ^8(level from items)", totalItemLevel))
end
if totalCorruptionLevel > 0 then
t_insert(env.player.breakdown.GemLevel, s_format("+ %d ^8(level from corruption)", totalCorruptionLevel))
elseif totalCorruptionLevel < 0 then
t_insert(env.player.breakdown.GemLevel, s_format("%d ^8(level from corruption)", totalCorruptionLevel))
end
end
t_insert(env.player.breakdown.GemLevel, s_format("= %d", output.GemLevel))
end
Expand Down
2 changes: 1 addition & 1 deletion src/Modules/CalcSections.lua
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ return {
} }
} },
{ 1, "SkillTypeStats", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Skill type-specific Stats", data = {
{ label = "Gem Level", notFlag = "thorns", haveOutput = "GemHasLevel", { format = "{0:output:GemLevel}", { breakdown = "GemLevel" }, { modName = { "GemLevel" }, cfg = "skill" },{ modName = { "GemSupportLevel" }, cfg = "skill" }, { modName = { "GemItemLevel" }, cfg = "skill" }, { modName = { "GemCorruptionLevel" }, cfg = "skill" } }, },
{ label = "Gem Level", notFlag = "thorns", haveOutput = "GemHasLevel", { format = "{0:output:GemLevel}", { breakdown = "GemLevel" }, { modName = { "GemLevel" }, cfg = "skill" }, { modName = { "GemSupportLevel" }, cfg = "skill", notSkillData = "inheritsGemLevel" }, { modName = { "GemItemLevel" }, cfg = "skill", notSkillData = "inheritsGemLevel" }, { modName = { "GemCorruptionLevel" }, cfg = "skill", notSkillData = "inheritsGemLevel" } }, },
{ label = "Spirit Cost", color = colorCodes.SPIRIT, haveOutput = "SpiritHasCost", { format = "{0:output:SpiritCost}", { breakdown = "SpiritCost" }, { modName = { "SpiritCost", "Cost", "SpiritCostNoMult" }, cfg = "skill" }, }, },
{ label = "Spirit % Cost", color = colorCodes.SPIRIT, haveOutput = "SpiritPercentHasCost", { format = "{0:output:SpiritPercentCost}", { breakdown = "SpiritPercentCost" }, { modName = { "SpiritCost", "Cost", "SpiritCostNoMult" }, cfg = "skill" }, }, },
{ label = "Mana Cost", color = colorCodes.MANA, haveOutput = "ManaHasCost", { format = "{0:output:ManaCost}", { breakdown = "ManaCost" }, { modName = { "ManaCost", "Cost", "ManaCostNoMult" }, cfg = "skill" }, }, },
Expand Down
10 changes: 10 additions & 0 deletions src/Modules/CalcSetup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2454,8 +2454,18 @@ function calcs.initEnv(build, mode, override, specEnv)
t_insert(env.player.activeSkillList, env.player.mainSkill)
end

-- some active skills, like those granted by support gems depend on the stats of other gems,
-- which means we have to do them last.
local deferredActiveSkills = {}
-- Build skill modifier lists
for _, activeSkill in pairs(env.player.activeSkillList) do
if activeSkill.activeEffect.gemData and activeSkill.activeEffect.gemData.grantedEffect.support then
table.insert(deferredActiveSkills, activeSkill)
else
calcs.buildActiveSkillModList(env, activeSkill)
end
end
for _, activeSkill in ipairs(deferredActiveSkills) do
calcs.buildActiveSkillModList(env, activeSkill)
end

Expand Down
Loading