Skip to content

Commit 463f95d

Browse files
LocalIdentityLocalIdentity
andauthored
Add support for Gemling's additional quality Stats (#2333)
* Add support for Gemling's additional quality Stats Adds support for the new gemling quality stats There are still a bunch that need supporting but that should be easy Only shows the quality stats and adds their effect when you have the node allocated Also fixes an issue where some stat descriptions for quality mods weren't working as they were using the wrong stat set stat description scope * Add support for new quality mods * Fix default distance not applying for distance ramp The placeholder value wasn't being used for distance ramp, you had to manually set it * Fix gem tooltip max width * Rain of Blade quality --------- Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent 83beb38 commit 463f95d

26 files changed

Lines changed: 2799 additions & 483 deletions

spec/System/TestSkillsTab_spec.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ describe("TestSkillsTab", function()
321321
label = "Test Group",
322322
enabled = true,
323323
gemList = {
324-
{ nameSpec = "TestGem", level = 20, quality = 0, qualityId = "Default", enabled = true, count = 1 }
324+
{ nameSpec = "TestGem", level = 20, quality = 0, enabled = true, count = 1 }
325325
}
326326
}
327327

spec/System/TestSkills_spec.lua

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,45 @@ describe("TestSkills", function()
6363
assertGemSupportLevel("Apocalypse", 3, 4)
6464
end)
6565

66+
it("applies Advanced Thaumaturgy quality stats only when enabled", function()
67+
local advancedThaumaturgy = build.spec.nodes[14429]
68+
assert.is_not_nil(advancedThaumaturgy)
69+
assert.True(advancedThaumaturgy.modList:Flag(nil, "GemlingQuality"))
70+
71+
local grantedEffect = data.skills["AlchemistsBoonPlayer"]
72+
local statSet = grantedEffect.statSets[1]
73+
local skillInstance = {
74+
level = 20,
75+
quality = 20,
76+
}
77+
78+
local stats = calcLib.buildSkillInstanceStats(skillInstance, grantedEffect, statSet)
79+
assert.is_not_nil(stats["skill_alchemists_boon_generate_x_charges_for_any_flask_per_minute"])
80+
assert.is_nil(stats["alchemists_boon_attack_speed_granted_+%_during_life_flask"])
81+
assert.is_nil(stats["alchemists_boon_cast_speed_granted_+%_during_mana_flask"])
82+
83+
stats = calcLib.buildSkillInstanceStats(skillInstance, grantedEffect, statSet, true)
84+
assert.are.equals(20, stats["alchemists_boon_attack_speed_granted_+%_during_life_flask"])
85+
assert.are.equals(20, stats["alchemists_boon_cast_speed_granted_+%_during_mana_flask"])
86+
end)
87+
88+
it("describes quality stats from secondary skill stat sets", function()
89+
local grantedEffect = data.skills["ExplosiveSpearPlayer"]
90+
local qualityStat = grantedEffect.qualityStats[1]
91+
local stats = {
92+
active_skill_base_area_of_effect_radius = 4,
93+
}
94+
95+
assert.same({ 1, 2 }, qualityStat[3])
96+
local firstDescriptions = build.data.describeStats(stats, grantedEffect.statSets[1].statDescriptionScope, true)
97+
local qualityStatSet = grantedEffect.statSets[qualityStat[3][1] + 1]
98+
local qualityDescriptions = build.data.describeStats(stats, qualityStatSet.statDescriptionScope, true)
99+
100+
assert.are.equals(0, #firstDescriptions)
101+
assert.is_true(#qualityDescriptions > 0)
102+
assert.matches("Explosion radius", qualityDescriptions[1])
103+
end)
104+
66105

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

src/Classes/CompareTab.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2973,7 +2973,6 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories
29732973
nameSpec = cGem.nameSpec,
29742974
level = cGem.level,
29752975
quality = cGem.quality,
2976-
qualityId = cGem.qualityId,
29772976
enabled = cGem.enabled,
29782977
grantedEffect = cGem.grantedEffect,
29792978
gemData = cGem.gemData,

src/Classes/GemSelectControl.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ function GemSelectClass:Draw(viewPort, noTooltip)
471471
-- Rebuilding this tooltip runs a full build calculation, so only rebuild when the hovered gem or the underlying build changes
472472
if self.tooltip:CheckForUpdate(gemData, self.skillsTab.build.outputRevision, self.skillsTab.displayGroup, self.skillsTab.sortGemsByDPSField,
473473
self.skillsTab.defaultGemLevel, self.skillsTab.defaultGemQuality, self.skillsTab.defaultCorruptionLevel, self.skillsTab.defaultCorruptionState) then
474+
self.tooltip.maxWidth = 500
474475
-- No fastCalcOptions here: the tooltip's stat compare shows defensive stats too, so it needs the full (unaccelerated) calc
475476
local output = self:CalcOutputWithThisGem(calcFunc, gemData, self.skillsTab.sortGemsByDPSField == "FullDPS")
476477
local gemInstance = {

src/Classes/GemTooltip.lua

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
-- Shared renderer for gem-style tooltips.
55

66
local m_max = math.max
7+
local m_min = math.min
78

89
local GemTooltip = { }
910

1011
local function getFontSizes()
1112
return main.showFlavourText and 18 or 16, main.showFlavourText and 24 or 20
1213
end
1314

14-
local function addDescriptionLine(tooltip, build, statSet, line, stat, index)
15+
local function addDescriptionLine(tooltip, build, statSet, line, stat, index, colorCode)
1516
local fontSizeBig = getFontSizes()
1617
local source = statSet.statMap[stat] or build.data.skillStatMap[stat]
1718
local bg = (index % 2 == 0) and "GemHoverModBg" or nil
@@ -26,7 +27,7 @@ local function addDescriptionLine(tooltip, build, statSet, line, stat, index)
2627
end
2728
line = line .. " ^2" .. devText
2829
end
29-
tooltip:AddLine(fontSizeBig, colorCodes.MAGIC .. line, "FONTIN SC", bg)
30+
tooltip:AddLine(fontSizeBig, (colorCode or colorCodes.MAGIC) .. line, "FONTIN SC", bg)
3031
else
3132
if launch.devModeAlt then
3233
line = line .. " ^1" .. stat
@@ -206,6 +207,7 @@ end
206207
local function addStatSetInfo(tooltip, build, gemInstance, grantedEffect, statSet, noLabel, index, levelRange)
207208
local fontSizeBig, fontSizeTitle = getFontSizes()
208209
local displayInstance = getDisplayInstance(gemInstance)
210+
local includeAltQualityStats = build.calcsTab.mainEnv.modDB:Flag(nil, "GemlingQuality")
209211
local statSetLevel = statSet.levels[levelRange and gemInstance.level or displayInstance.level] or statSet.levels[1] or { }
210212
if not (index == 1 and statSet.label == grantedEffect.name) and statSet.label ~= "" and not noLabel then
211213
tooltip:AddSeparator(10)
@@ -226,18 +228,25 @@ local function addStatSetInfo(tooltip, build, gemInstance, grantedEffect, statSe
226228
local copiedInstance = copyTable(gemInstance, true)
227229
copiedInstance.quality = 0
228230
copiedInstance.level = 20
229-
local statsLevel20 = calcLib.buildSkillInstanceStats(copiedInstance, grantedEffect, statSet)
231+
local statsLevel20 = calcLib.buildSkillInstanceStats(copiedInstance, grantedEffect, statSet, includeAltQualityStats)
230232
copiedInstance.level = 1
231-
stats = calcLib.buildSkillInstanceStats(copiedInstance, grantedEffect, statSet)
233+
stats = calcLib.buildSkillInstanceStats(copiedInstance, grantedEffect, statSet, includeAltQualityStats)
232234
for statName, min in pairs(stats) do
233235
stats[statName] = { min = min, max = statsLevel20[statName] or min }
234236
end
235237
else
236-
stats = calcLib.buildSkillInstanceStats(displayInstance, grantedEffect, statSet)
238+
stats = calcLib.buildSkillInstanceStats(displayInstance, grantedEffect, statSet, includeAltQualityStats)
237239
end
238240
local descriptions, lineMap = build.data.describeStats(stats, statSet.statDescriptionScope)
241+
local altQualityStatColor = { }
242+
if includeAltQualityStats then
243+
for _, stat in ipairs(grantedEffect.altQualityStats or { }) do
244+
altQualityStatColor[stat[1]] = colorCodes.ENCHANTED
245+
end
246+
end
239247
for i, line in ipairs(descriptions) do
240-
addDescriptionLine(tooltip, build, statSet, line, lineMap[line], i)
248+
local stat = lineMap[line]
249+
addDescriptionLine(tooltip, build, statSet, line, stat, i, stat and altQualityStatColor[stat])
241250
end
242251
end
243252
end
@@ -248,19 +257,29 @@ local function addEffectStats(tooltip, build, gemInstance, grantedEffect, noLabe
248257
end
249258
end
250259

251-
local function addQualityRangeInfo(tooltip, build, grantedEffect, addedHeader)
260+
local function addQualityRangeInfo(tooltip, build, grantedEffect, addedHeader, includeAltQualityStats)
252261
-- Quality ranges are tree-only. SkillsTab shows the 20 quality value separately, but tree nodes need the 0-20 range inline.
253-
if not grantedEffect.qualityStats or #grantedEffect.qualityStats == 0 then
262+
local qualityStats = { }
263+
for _, stat in ipairs(grantedEffect.qualityStats or { }) do
264+
qualityStats[#qualityStats + 1] = { stat = stat[1], value = stat[2], statSetIndexes = stat[3], color = colorCodes.MAGIC }
265+
end
266+
if includeAltQualityStats then
267+
for _, stat in ipairs(grantedEffect.altQualityStats or { }) do
268+
qualityStats[#qualityStats + 1] = { stat = stat[1], value = stat[2], statSetIndexes = stat[3], color = colorCodes.ENCHANTED }
269+
end
270+
end
271+
if #qualityStats == 0 then
254272
return addedHeader
255273
end
256274
local fontSizeBig = getFontSizes()
257275
local lineIndex = 1
258-
for _, stat in ipairs(grantedEffect.qualityStats) do
259-
if stat[1] and stat[2] then
260-
local stats = { [stat[1]] = 20 * stat[2] }
261-
local descriptions, lineMap = build.data.describeStats(stats, grantedEffect.statSets[1].statDescriptionScope, true)
276+
for _, stat in ipairs(qualityStats) do
277+
if stat.stat and stat.value then
278+
local stats = { [stat.stat] = 20 * stat.value }
279+
local statSet = grantedEffect.statSets[(stat.statSetIndexes[1] or 0) + 1] or grantedEffect.statSets[1]
280+
local descriptions, lineMap = build.data.describeStats(stats, statSet.statDescriptionScope, true)
262281
for _, line in ipairs(descriptions) do
263-
local statName = lineMap[line] or stat[1]
282+
local statName = lineMap[line] or stat.stat
264283
if not addedHeader then
265284
tooltip:AddLine(fontSizeBig, "\n^7Additional Effects From Quality:", "FONTIN SC")
266285
addedHeader = true
@@ -273,7 +292,7 @@ local function addQualityRangeInfo(tooltip, build, grantedEffect, addedHeader)
273292
end
274293
return "(0-" .. value .. ")"
275294
end, 1)
276-
addDescriptionLine(tooltip, build, grantedEffect.statSets[1], line, statName, lineIndex)
295+
addDescriptionLine(tooltip, build, statSet, line, statName, lineIndex, stat.color)
277296
lineIndex = lineIndex + 1
278297
end
279298
end
@@ -288,6 +307,7 @@ function GemTooltip.AddGemTooltip(tooltip, build, gemInstance, options)
288307
tooltip.center = false
289308
tooltip.color = colorCodes.GEM
290309
tooltip.minWidth = 600
310+
tooltip.maxWidth = m_min(tooltip.maxWidth or 600, 600)
291311
tooltip.tooltipHeader = "GEM"
292312
tooltip.gemIcon = gemInstance.gemData.grantedEffect.icon
293313
tooltip.gemBackground = gemInstance.gemData.grantedEffect.id
@@ -343,9 +363,10 @@ function GemTooltip.AddGemTooltip(tooltip, build, gemInstance, options)
343363

344364
if options.includeQualityRange then
345365
local addedHeader
346-
addedHeader = addQualityRangeInfo(tooltip, build, grantedEffect, addedHeader)
366+
local includeAltQualityStats = build.calcsTab.mainEnv.modDB:Flag(nil, "GemlingQuality")
367+
addedHeader = addQualityRangeInfo(tooltip, build, grantedEffect, addedHeader, includeAltQualityStats)
347368
for _, effect in ipairs(additionalEffects or { }) do
348-
addedHeader = addQualityRangeInfo(tooltip, build, effect, addedHeader)
369+
addedHeader = addQualityRangeInfo(tooltip, build, effect, addedHeader, includeAltQualityStats)
349370
end
350371
end
351372

src/Classes/SkillsTab.lua

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,25 @@ function SkillsTabClass:CreateGemSlot(index)
890890
if not gemData then
891891
return
892892
end
893+
local includeAltQualityStats = self.build.calcsTab.mainEnv.modDB:Flag(nil, "GemlingQuality")
894+
local hasQualityStats = function(grantedEffect)
895+
return grantedEffect and (
896+
(grantedEffect.qualityStats and #grantedEffect.qualityStats > 0) or
897+
(includeAltQualityStats and grantedEffect.altQualityStats and #grantedEffect.altQualityStats > 0)
898+
)
899+
end
900+
local getQualityStats = function(grantedEffect)
901+
local qualityStats = { }
902+
for _, stat in ipairs(grantedEffect.qualityStats or { }) do
903+
qualityStats[#qualityStats + 1] = { stat = stat[1], value = stat[2], statSetIndexes = stat[3], color = colorCodes.MAGIC }
904+
end
905+
if includeAltQualityStats then
906+
for _, stat in ipairs(grantedEffect.altQualityStats or { }) do
907+
qualityStats[#qualityStats + 1] = { stat = stat[1], value = stat[2], statSetIndexes = stat[3], color = colorCodes.ENCHANTED }
908+
end
909+
end
910+
return qualityStats
911+
end
893912
-- Function for both granted effect and secondary such as vaal
894913
local addQualityLines = function(qualityList, grantedEffect)
895914
if #qualityList > 0 then
@@ -900,17 +919,19 @@ function SkillsTabClass:CreateGemSlot(index)
900919
end
901920
-- Hardcoded to use 20% quality instead of grabbing from gem, this is for consistency and so we always show something
902921
tooltip:AddLine(16, colorCodes.NORMAL.."At +20% Quality:")
903-
for k, qual in pairs(qualityList) do
922+
for _, qual in ipairs(qualityList) do
904923
-- Do the stats one at a time because we're not guaranteed to get the descriptions in the same order we look at them here
905924
local stats = { }
906-
stats[qual[1]] = qual[2] * 20
907-
local descriptions = self.build.data.describeStats(stats, grantedEffect.statSets[1].statDescriptionScope, true)
925+
stats[qual.stat] = qual.value * 20
926+
local statSet = grantedEffect.statSets[(qual.statSetIndexes[1] or 0) + 1] or grantedEffect.statSets[1]
927+
local descriptions, lineMap = self.build.data.describeStats(stats, statSet.statDescriptionScope, true)
908928
-- line may be nil if the value results in no line due to not being enough quality
909929
for _, line in ipairs(descriptions) do
910930
if line then
931+
local statName = lineMap[line] or qual.stat
911932
-- Check if we have a handler for the mod in the gem's statMap or in the shared stat map for skills
912-
if grantedEffect.statSets[1].statMap[qual[1]] or self.build.data.skillStatMap[qual[1]] then
913-
tooltip:AddLine(16, colorCodes.MAGIC..line)
933+
if statSet.statMap[statName] or self.build.data.skillStatMap[statName] then
934+
tooltip:AddLine(16, qual.color..line)
914935
else
915936
local line = colorCodes.UNSUPPORTED..line
916937
line = main.notSupportedModTooltips and (line .. main.notSupportedTooltipText) or line
@@ -921,24 +942,22 @@ function SkillsTabClass:CreateGemSlot(index)
921942
end
922943
end
923944
end
924-
-- Check if there is a quality of this type for the effect
925-
-- Currently only checks the first 2 additionalGrantedEffects. Will need to fix if gems ever add more
926-
if gemData and gemData.grantedEffect.qualityStats and #gemData.grantedEffect.qualityStats > 0 then
927-
local qualityTable = gemData.grantedEffect.qualityStats
928-
addQualityLines(qualityTable, gemData.grantedEffect)
945+
local qualityStatsShown = false
946+
if hasQualityStats(gemData.grantedEffect) then
947+
addQualityLines(getQualityStats(gemData.grantedEffect), gemData.grantedEffect)
948+
qualityStatsShown = true
929949
end
930-
if gemData and gemData.additionalGrantedEffects[1] and gemData.additionalGrantedEffects[1].qualityStats and #gemData.additionalGrantedEffects[1].qualityStats > 0 then
931-
local qualityTable = gemData.additionalGrantedEffects[1].qualityStats
932-
tooltip:AddSeparator(10)
933-
addQualityLines(qualityTable, gemData.additionalGrantedEffects[1])
934-
end
935-
if gemData and gemData.additionalGrantedEffects[2] and gemData.additionalGrantedEffects[2].qualityStats and #gemData.additionalGrantedEffects[2].qualityStats > 0 then
936-
local qualityTable = gemData.additionalGrantedEffects[2].qualityStats
937-
tooltip:AddSeparator(10)
938-
addQualityLines(qualityTable, gemData.additionalGrantedEffects[2])
950+
for _, effect in ipairs(gemData.additionalGrantedEffects or { }) do
951+
if hasQualityStats(effect) then
952+
if qualityStatsShown then
953+
tooltip:AddSeparator(10)
954+
end
955+
addQualityLines(getQualityStats(effect), effect)
956+
qualityStatsShown = true
957+
end
939958
end
940959
-- Add stat comparisons for hovered quality (based on set quality)
941-
if gemData and (gemData.grantedEffect.qualityStats or (gemData.additionalGrantedEffects[1] and gemData.additionalGrantedEffects[1].qualityStats or gemData.additionalGrantedEffects[2] and gemData.additionalGrantedEffects[2].qualityStats)) and self.displayGroup.gemList[index] then
960+
if qualityStatsShown and self.displayGroup.gemList[index] then
942961
local calcFunc, calcBase = self.build.calcsTab:GetMiscCalculator(self.build)
943962
if calcFunc then
944963
local storedQuality = self.displayGroup.gemList[index].quality

src/Data/ModCache.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5680,7 +5680,7 @@ c["Gain no inherent bonuses from Attributes"]={{[1]={flags=0,keywordFlags=0,name
56805680
c["Gain the benefits of Bonded modifiers on Runes and Idols"]={{[1]={flags=0,keywordFlags=0,name="Condition:CanUseBondedModifiers",type="FLAG",value=true}},nil}
56815681
c["Gains 0.18 Charges per Second"]={{[1]={flags=0,keywordFlags=0,name="FlaskChargesGenerated",type="BASE",value=0.18}},nil}
56825682
c["Gains 0.20 Charges per Second"]={{[1]={flags=0,keywordFlags=0,name="FlaskChargesGenerated",type="BASE",value=0.2}},nil}
5683-
c["Gem Quality grants Socketed Skills an additional effect"]={nil,"Gem Quality grants Socketed Skills an additional effect "}
5683+
c["Gem Quality grants Socketed Skills an additional effect"]={{[1]={flags=0,keywordFlags=0,name="GemlingQuality",type="FLAG",value=true}},nil}
56845684
c["Giant's Blood"]={{[1]={flags=0,keywordFlags=0,name="Keystone",type="LIST",value="Giant's Blood"}},nil}
56855685
c["Glancing Blows"]={{[1]={flags=0,keywordFlags=0,name="Keystone",type="LIST",value="Glancing Blows"}},nil}
56865686
c["Glorifying the defilement of 4050 souls in tribute to Ulaman"]={{[1]={flags=0,keywordFlags=0,name="JewelData",type="LIST",value={key="conqueredBy",value={conqueror={id=5,type="abyss"},id=4050}}}},nil}

0 commit comments

Comments
 (0)