Skip to content

Commit 51804d4

Browse files
LocalIdentityLocalIdentity
andauthored
Fix gem level supports not working properly with some skills (#2279)
Gem level supports were currently only applying their effect to the granted effect of the skill part that they matched. This causes issues when you have a skill like Apocalypse that has multiple granted effects Fire Mastery was only increasing the gem level for the meteor instead of the actual gem itself Now mods that use `SupportedGemProperty` apply to all the granted effects on a gem and go through their own loop We now have a `GemTag` mod type too that makes it easier to apply for future scenarios Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent d550ec2 commit 51804d4

6 files changed

Lines changed: 102 additions & 13 deletions

File tree

spec/System/TestSkills_spec.lua

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,41 @@ describe("TestSkills", function()
2828
end
2929
end
3030

31+
local function assertGemSupportLevel(gemName, expectedLevel, expectedCount)
32+
local count = 0
33+
for _, activeSkill in ipairs(build.calcsTab.calcsEnv.player.activeSkillList) do
34+
if activeSkill.activeEffect.gemData and activeSkill.activeEffect.gemData.name == gemName then
35+
count = count + 1
36+
assert.are.equals(expectedLevel, activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "GemSupportLevel"))
37+
end
38+
end
39+
assert.are.equals(expectedCount, count)
40+
end
41+
42+
it("evaluates GemTag mod tags against active skill gem tags", function()
43+
local modDB = build.calcsTab.mainEnv.modDB
44+
45+
modDB:NewMod("Damage", "INC", 10, "Test Fire GemTag", { type = "GemTag", gemTag = "Fire" })
46+
modDB:NewMod("Damage", "INC", 20, "Test Elemental GemTagList", { type = "GemTag", gemTagList = { "Cold", "Lightning" } })
47+
modDB:NewMod("Damage", "INC", 40, "Test Not Minion GemTag", { type = "GemTag", gemTag = "Minion", neg = true })
48+
49+
assert.are.equals(50, modDB:Sum("INC", { skillGem = { tags = { fire = true } } }, "Damage"))
50+
assert.are.equals(60, modDB:Sum("INC", { skillGem = { tags = { cold = true } } }, "Damage"))
51+
assert.are.equals(0, modDB:Sum("INC", { skillGem = { tags = { minion = true } } }, "Damage"))
52+
end)
53+
54+
it("applies Fire Mastery level to Apocalypse through the source gem tag", function()
55+
build.skillsTab:PasteSocketGroup("Apocalypse 20/0 1\nFire Mastery 1/0 1")
56+
runCallback("OnFrame")
57+
assertGemSupportLevel("Apocalypse", 1, 4)
58+
end)
59+
60+
it("evaluates conditional gem levels using the source gem support count", function()
61+
build.skillsTab:PasteSocketGroup("Apocalypse 20/0 1\nFire Mastery 1/0 1\nUhtred's Omen 1/0 1")
62+
runCallback("OnFrame")
63+
assertGemSupportLevel("Apocalypse", 3, 4)
64+
end)
65+
3166

3267
it("uses granted effect minion list when active skill minion list is missing", function()
3368
local srcInstance = { statSet = { }, skillPart = { }, nameSpec = "Spectre: Test" }

src/Classes/CalcBreakdownControl.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,8 @@ function CalcBreakdownClass:AddModSection(sectionData, modList)
481481
else
482482
desc = "Skill type: "..(tag.neg and "Not " or "")..self:FormatModName(SkillTypeName[tag.skillType])
483483
end
484+
elseif tag.type == "GemTag" then
485+
desc = "Gem tag: "..(tag.neg and "Not " or "")..self:FormatVarNameOrList(tag.gemTag, tag.gemTagList)
484486
elseif tag.type == "BaseFlag" then
485487
desc = "Base flag: "..(tag.neg and "Not " or "")..self:FormatModName(tostring(tag.baseFlag))
486488
elseif tag.type == "SlotNumber" then

src/Classes/ModStore.lua

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,25 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits)
830830
if not match then
831831
return
832832
end
833+
elseif tag.type == "GemTag" then
834+
local match = false
835+
local gemTags = cfg and cfg.skillGem and cfg.skillGem.tags
836+
if tag.gemTagList then
837+
for _, gemTag in pairs(tag.gemTagList) do
838+
if gemTags and gemTags[gemTag:lower()] then
839+
match = true
840+
break
841+
end
842+
end
843+
else
844+
match = gemTags and gemTags[tag.gemTag:lower()]
845+
end
846+
if tag.neg then
847+
match = not match
848+
end
849+
if not match then
850+
return
851+
end
833852
elseif tag.type == "BaseFlag" then
834853
local match = false
835854
if cfg and cfg.skillGem and cfg.skillGem.grantedEffect and cfg.skillGem.grantedEffect.statSets and cfg.skillGem.grantedEffect.statSets[1] then

src/Data/SkillStatMap.lua

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3017,23 +3017,23 @@ return {
30173017
--
30183018
--Fire
30193019
["supported_fire_skill_gem_level_+"] = {
3020-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.Fire }),
3020+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Fire" }),
30213021
},
30223022
--Cold
30233023
["supported_cold_skill_gem_level_+"] = {
3024-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.Cold }),
3024+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Cold" }),
30253025
},
30263026
--Lightning
30273027
["supported_lightning_skill_gem_level_+"] = {
3028-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.Lightning }),
3028+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Lightning" }),
30293029
},
30303030
--Chaos
30313031
["supported_chaos_skill_gem_level_+"] = {
3032-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.Chaos }),
3032+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Chaos" }),
30333033
},
30343034
--Physical
30353035
["supported_physical_skill_gem_level_+"] = {
3036-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.Physical }),
3036+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Physical" }),
30373037
},
30383038
--Active
30393039
["supported_active_skill_gem_level_+"] = {
@@ -3044,23 +3044,23 @@ return {
30443044
},
30453045
--Aura
30463046
["supported_aura_skill_gem_level_+"] = {
3047-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.Aura }),
3047+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Aura" }),
30483048
},
30493049
--Curse
30503050
["supported_curse_skill_gem_level_+"] = {
3051-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, KeywordFlag.Curse),
3051+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Curse" }),
30523052
},
30533053
--Strike
30543054
["supported_strike_skill_gem_level_+"] = {
3055-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.MeleeSingleTarget }),
3055+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Strike" }),
30563056
},
30573057
--Elemental
30583058
["supported_elemental_skill_gem_level_+"] = {
3059-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, OR64(KeywordFlag.Lightning, KeywordFlag.Cold, KeywordFlag.Fire)),
3059+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTagList = { "Lightning", "Cold", "Fire" } }),
30603060
},
30613061
--Minion
30623062
["supported_minion_skill_gem_level_+"] = {
3063-
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "SkillType", skillType = SkillType.Minion }),
3063+
mod("SupportedGemProperty", "LIST", { keyword = "grants_active_skill", key = "level", value = nil }, 0, 0, { type = "GemTag", gemTag = "Minion" }),
30643064
},
30653065
-- Remnant stats
30663066
["remnant_effect_+%"] = {

src/Modules/CalcActiveSkill.lua

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,35 @@ function calcs.createActiveSkill(activeEffect, supportList, env, actor, socketGr
230230
return activeSkill
231231
end
232232

233+
local function getSourceGemPropertyInfo(env, activeSkill)
234+
local activeEffect = activeSkill.activeEffect
235+
local sourceGem = activeEffect.srcInstance
236+
if not sourceGem or not activeEffect.gemData or activeEffect.gemData.tags.support then
237+
return { }
238+
end
239+
240+
env.sourceGemPropertyInfo = env.sourceGemPropertyInfo or { }
241+
if not env.sourceGemPropertyInfo[sourceGem] then
242+
local modList = new("ModList", activeSkill.actor.modDB)
243+
local supportCount = 0
244+
for _, supportEffect in ipairs(activeSkill.supportList) do
245+
if supportEffect.isSupporting and supportEffect.isSupporting[sourceGem] then
246+
calcs.mergeSkillInstanceMods(env, modList, supportEffect)
247+
if not supportEffect.grantedEffect.hidden then
248+
supportCount = supportCount + 1
249+
end
250+
end
251+
end
252+
modList:NewMod("Multiplier:SupportCount", "BASE", supportCount, "Support Count")
253+
env.sourceGemPropertyInfo[sourceGem] = modList:Tabulate("LIST", {
254+
skillName = activeEffect.gemData.name,
255+
skillGem = activeEffect.gemData,
256+
slotName = activeSkill.slotName,
257+
}, "SupportedGemProperty")
258+
end
259+
return env.sourceGemPropertyInfo[sourceGem]
260+
end
261+
233262
function calcs.getActiveSkillDisplayName(activeSkill)
234263
local skillName = activeSkill.activeEffect.grantedEffect.name
235264
local skillMinion = activeSkill.minion
@@ -741,11 +770,13 @@ function calcs.buildActiveSkillModList(env, activeSkill)
741770
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
742771
skillModList:NewMod("GemCorruptionLevel", "BASE", activeSkill.activeEffect.srcInstance.corruptLevel, "Corruption")
743772
end
744-
for _, supportProperty in ipairs(skillModList:Tabulate("LIST", activeSkill.skillCfg, "SupportedGemProperty")) do
773+
for _, supportProperty in ipairs(getSourceGemPropertyInfo(env, activeSkill)) do
745774
local value = supportProperty.value
746-
if value.keyword == "grants_active_skill" and activeSkill.activeEffect.gemData and not activeSkill.activeEffect.gemData.tags.support then
775+
if value.keyword == "grants_active_skill" then
747776
activeEffect[value.key] = activeEffect[value.key] + value.value
748-
skillModList:NewMod("GemSupport".. value.key:gsub("^%l", string.upper), "BASE", value.value, supportProperty.mod.source, #supportProperty.mod > 0 and supportProperty.mod[1] or nil)
777+
local gemTag = supportProperty.mod[1]
778+
gemTag = gemTag and gemTag.type == "GemTag" and gemTag or nil
779+
skillModList:NewMod("GemSupport".. value.key:gsub("^%l", string.upper), "BASE", value.value, supportProperty.mod.source, gemTag)
749780
end
750781
end
751782

src/Modules/CalcSetup.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ function wipeEnv(env, accelerate)
395395
if not accelerate.skills then
396396
-- Player Active Skills generation
397397
wipeTable(env.player.activeSkillList)
398+
env.sourceGemPropertyInfo = { }
398399

399400
-- Enhances Active Skills with skill ModFlags, KeywordFlags
400401
-- and modifiers that affect skill scaling (e.g., global buffs/effects)
@@ -1688,6 +1689,7 @@ function calcs.initEnv(build, mode, override, specEnv)
16881689
level = value.level,
16891690
quality = 0,
16901691
enabled = true,
1692+
isSupporting = { },
16911693
})
16921694
end
16931695
end

0 commit comments

Comments
 (0)