diff --git a/spec/System/TestItemMods_spec.lua b/spec/System/TestItemMods_spec.lua index 1546d60804..d057aa8db3 100644 --- a/spec/System/TestItemMods_spec.lua +++ b/spec/System/TestItemMods_spec.lua @@ -67,6 +67,18 @@ describe("TetsItemMods", function() assert.are_not.equals(lightningResBefore, build.calcsTab.mainOutput.LightningResist) end) + it("caps socketed gem multipliers in gem order", function() + build.itemsTab:CreateDisplayItemFromRaw("Test Gloves\nIron Gauntlets\nSockets: R-R-R-R") + build.itemsTab:AddDisplayItem() + build.skillsTab:PasteSocketGroup("Slot: Gloves\nHeavy Strike 20/0 1\nHeavy Strike 20/0 1\nHeavy Strike 20/0 1\nHeavy Strike 20/0 1\nArc 20/0 1\n") + runCallback("OnFrame") + + local multipliers = build.calcsTab.mainEnv.itemModDB.multipliers + assert.are.equals(4, multipliers.SocketedGemsInGloves) + assert.are.equals(4, multipliers.SocketedRedGemsInGloves) + assert.are.equals(0, multipliers.SocketedBlueGemsInGloves) + end) + it("Doomsower vaal pact and extra phys as fire", function() build.itemsTab:CreateDisplayItemFromRaw([[Doomsower Lion Sword diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 6cc41f93c4..b537903158 100755 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -10068,12 +10068,12 @@ c["Minions cannot be Blinded Minions have 15% chance to Blind Enemies on hit"]={ c["Minions cannot be Killed, but die 6 seconds after being reduced to 1 Life"]={nil,"cannot be Killed, but die 6 seconds after being reduced to 1 Life "} c["Minions convert 25% of Physical Damage to Chaos Damage per Empty Socket"]={{[1]={[1]={type="Multiplier",var="EmptySocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToChaos",type="BASE",value=25}}}},nil} c["Minions convert 25% of Physical Damage to Chaos Damage per White Socket"]={{[1]={[1]={type="Multiplier",var="WhiteSocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToChaos",type="BASE",value=25}}}},nil} -c["Minions convert 25% of Physical Damage to Cold Damage per Socketed Green Gem"]={nil,"convert 25% of Physical Damage to Cold Damage per Socketed Green Gem "} -c["Minions convert 25% of Physical Damage to Cold Damage per Socketed Green Gem Minions convert 25% of Physical Damage to Cold Damage per Green Socket"]={{[1]={[1]={type="Multiplier",var="GreenSocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="Physical damage to cold damage per socketed green gem minions convert 25% of physicalDamageConvertToCold",type="BASE",value=25}}}},nil} -c["Minions convert 25% of Physical Damage to Fire Damage per Socketed Red Gem"]={nil,"convert 25% of Physical Damage to Fire Damage per Socketed Red Gem "} -c["Minions convert 25% of Physical Damage to Fire Damage per Socketed Red Gem Minions convert 25% of Physical Damage to Fire Damage per Red Socket"]={{[1]={[1]={type="Multiplier",var="RedSocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="Physical damage to fire damage per socketed red gem minions convert 25% of physicalDamageConvertToFire",type="BASE",value=25}}}},nil} -c["Minions convert 25% of Physical Damage to Lightning Damage per Socketed Blue Gem"]={nil,"convert 25% of Physical Damage to Lightning Damage per Socketed Blue Gem "} -c["Minions convert 25% of Physical Damage to Lightning Damage per Socketed Blue Gem Minions convert 25% of Physical Damage to Lightning Damage per Blue Socket"]={{[1]={[1]={type="Multiplier",var="BlueSocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="Physical damage to lightning damage per socketed blue gem minions convert 25% of physicalDamageConvertToLightning",type="BASE",value=25}}}},nil} +c["Minions convert 25% of Physical Damage to Cold Damage per Green Socket"]={{[1]={[1]={type="Multiplier",var="GreenSocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToCold",type="BASE",value=25}}}},nil} +c["Minions convert 25% of Physical Damage to Cold Damage per Socketed Green Gem"]={{[1]={[1]={type="Multiplier",var="SocketedGreenGemsIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToCold",type="BASE",value=25}}}},nil} +c["Minions convert 25% of Physical Damage to Fire Damage per Red Socket"]={{[1]={[1]={type="Multiplier",var="RedSocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToFire",type="BASE",value=25}}}},nil} +c["Minions convert 25% of Physical Damage to Fire Damage per Socketed Red Gem"]={{[1]={[1]={type="Multiplier",var="SocketedRedGemsIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToFire",type="BASE",value=25}}}},nil} +c["Minions convert 25% of Physical Damage to Lightning Damage per Blue Socket"]={{[1]={[1]={type="Multiplier",var="BlueSocketIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToLightning",type="BASE",value=25}}}},nil} +c["Minions convert 25% of Physical Damage to Lightning Damage per Socketed Blue Gem"]={{[1]={[1]={type="Multiplier",var="SocketedBlueGemsIn{SlotName}"},flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToLightning",type="BASE",value=25}}}},nil} c["Minions convert 50% of Physical Damage to Cold Damage"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="PhysicalDamageConvertToCold",type="BASE",value=50}}}},nil} c["Minions count as having the same number of"]={nil,"count as having the same number of "} c["Minions count as having the same number of Endurance, Frenzy and Power Charges as you"]={nil,"count as having the same number of Endurance, Frenzy and Power Charges as you "} diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 5abada18e8..5cadb660de 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -1189,13 +1189,13 @@ function calcs.initEnv(build, mode, override, specEnv) -- Calculate socket counts local slotEmptySocketsCount = { R = 0, G = 0, B = 0, W = 0} local slotGemSocketsCount = 0 - local socketedGems = 0 + local socketedGems = { } -- Loop through socket groups to calculate number of socketed gems - for _, socketGroup in pairs(env.build.skillsTab.socketGroupList) do + for _, socketGroup in ipairs(env.build.skillsTab.socketGroupList) do if (not socketGroup.source and socketGroup.enabled and socketGroup.slot and socketGroup.slot == slotName and socketGroup.gemList) then - for _, gem in pairs(socketGroup.gemList) do + for _, gem in ipairs(socketGroup.gemList) do if (gem.gemData and gem.enabled) then - socketedGems = socketedGems + 1 + t_insert(socketedGems, gem) end end end @@ -1205,18 +1205,36 @@ function calcs.initEnv(build, mode, override, specEnv) if socket.color == 'R' or socket.color == 'B' or socket.color == 'G' or socket.color == 'W' then slotGemSocketsCount = slotGemSocketsCount + 1 -- loop through sockets indexes that are greater than number of socketed gems - if i > socketedGems then + if i > #socketedGems then slotEmptySocketsCount[socket.color] = slotEmptySocketsCount[socket.color] + 1 end end end - env.itemModDB.multipliers["SocketedGemsIn"..slotName] = (env.itemModDB.multipliers["SocketedGemsIn"..slotName] or 0) + math.min(slotGemSocketsCount, socketedGems) + local socketedColours = { R = 0, G = 0, B = 0 } + -- Only gems that fit in the item's sockets contribute to multipliers + for i = 1, math.min(slotGemSocketsCount, #socketedGems) do + local tags = socketedGems[i].gemData.tags + if tags and tags.strength then + socketedColours.R = socketedColours.R + 1 + end + if tags and tags.dexterity then + socketedColours.G = socketedColours.G + 1 + end + if tags and tags.intelligence then + socketedColours.B = socketedColours.B + 1 + end + end + env.itemModDB.multipliers["SocketedGemsIn" .. slotName] = math.min(slotGemSocketsCount, #socketedGems) + env.itemModDB.multipliers["SocketedRedGemsIn" .. slotName] = socketedColours.R + env.itemModDB.multipliers["SocketedGreenGemsIn" .. slotName] = socketedColours.G + env.itemModDB.multipliers["SocketedBlueGemsIn" .. slotName] = socketedColours.B + env.itemModDB.multipliers["EmptySocketIn" .. slotName] = math.min(slotGemSocketsCount, slotEmptySocketsCount.R + slotEmptySocketsCount.G + slotEmptySocketsCount.B + slotEmptySocketsCount.W) env.itemModDB.multipliers.EmptyRedSocketsInAnySlot = (env.itemModDB.multipliers.EmptyRedSocketsInAnySlot or 0) + slotEmptySocketsCount.R env.itemModDB.multipliers.EmptyGreenSocketsInAnySlot = (env.itemModDB.multipliers.EmptyGreenSocketsInAnySlot or 0) + slotEmptySocketsCount.G env.itemModDB.multipliers.EmptyBlueSocketsInAnySlot = (env.itemModDB.multipliers.EmptyBlueSocketsInAnySlot or 0) + slotEmptySocketsCount.B env.itemModDB.multipliers.EmptyWhiteSocketsInAnySlot = (env.itemModDB.multipliers.EmptyWhiteSocketsInAnySlot or 0) + slotEmptySocketsCount.W -- Warn if socketed gems over socket limit - if socketedGems > slotGemSocketsCount then + if #socketedGems > slotGemSocketsCount then env.itemWarnings.socketLimitWarning = env.itemWarnings.socketLimitWarning or { } t_insert(env.itemWarnings.socketLimitWarning, slotName) end diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index dc522c003d..1daba4fcbd 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -1433,6 +1433,9 @@ local modTagList = { ["for each empty blue socket on any equipped item"] = { tag = { type = "Multiplier", var = "EmptyBlueSocketsInAnySlot" } }, ["for each empty white socket on any equipped item"] = { tag = { type = "Multiplier", var = "EmptyWhiteSocketsInAnySlot" } }, ["per socketed gem"] = { tag = { type = "Multiplier", var = "SocketedGemsIn{SlotName}"}}, + ["per socketed red gem"] = { tag = { type = "Multiplier", var = "SocketedRedGemsIn{SlotName}" } }, + ["per socketed green gem"] = { tag = { type = "Multiplier", var = "SocketedGreenGemsIn{SlotName}" } }, + ["per socketed blue gem"] = { tag = { type = "Multiplier", var = "SocketedBlueGemsIn{SlotName}" } }, ["for each impale on enemy"] = { tag = { type = "Multiplier", var = "ImpaleStacks", actor = "enemy" } }, ["per impale on enemy"] = { tag = { type = "Multiplier", var = "ImpaleStacks", actor = "enemy" } }, ["per grasping vine"] = { tag = { type = "Multiplier", var = "GraspingVinesCount" } }, @@ -4376,6 +4379,14 @@ local specialModList = { ["minions convert (%d+)%% of (.+) damage to (.+) damage per (.+) socket"] = function(num, _, source, target, socketColor) return { mod("MinionModifier", "LIST", { mod = mod(source:gsub("^%l", string.upper) .. "DamageConvertTo" .. target:gsub("^%l", string.upper), "BASE", num) }, { type = "Multiplier", var = socketColor:gsub("^%l", string.upper) .. "SocketIn{SlotName}" }) } end, + ["minions convert (%d+)%% of (.+) damage to (.+) damage per socketed (%a+) gem"] = function(num, _, source, target, colour) + if colour == "red" or colour == "green" or colour == "blue" then + local var = string.format("Socketed%sGemsIn{SlotName}", colour:gsub("^%l", string.upper)) + return { + mod("MinionModifier", "LIST", { mod = mod(source:gsub("^%l", string.upper) .. "DamageConvertTo" .. target:gsub("^%l", string.upper), "BASE", num) }, { type = "Multiplier", var = var }) + } + end + end, ["minions have a (%d+)%% chance to impale on hit with attacks"] = function(num) return { mod("MinionModifier", "LIST", { mod = mod("ImpaleChance", "BASE", num ) }) } end, ["minions from herald skills deal (%d+)%% more damage"] = function(num) return { mod("MinionModifier", "LIST", { mod = mod("Damage", "MORE", num) }, { type = "SkillType", skillType = SkillType.Herald }) } end, ["minions have (%d+)%% increased movement speed for each herald affecting you"] = function(num) return { mod("MinionModifier", "LIST", { mod = mod("MovementSpeed", "INC", num, { type = "Multiplier", var = "Herald", actor = "parent" }) }) } end,