diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index 024417aa64..5d10c274b2 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -758,7 +758,7 @@ function ImportTabClass:ImportItemsAndSkills(charData) end local rarityMap = { [0] = "NORMAL", "MAGIC", "RARE", "UNIQUE", [9] = "RELIC", [10] = "RELIC" } -local slotMap = { ["Weapon"] = "Weapon 1", ["Offhand"] = "Weapon 2", ["Weapon2"] = "Weapon 1 Swap", ["Offhand2"] = "Weapon 2 Swap", ["Helm"] = "Helmet", ["BodyArmour"] = "Body Armour", ["Gloves"] = "Gloves", ["Boots"] = "Boots", ["Amulet"] = "Amulet", ["Ring"] = "Ring 1", ["Ring2"] = "Ring 2", ["Belt"] = "Belt" } +local slotMap = { ["Weapon"] = "Weapon 1", ["Offhand"] = "Weapon 2", ["Weapon2"] = "Weapon 1 Swap", ["Offhand2"] = "Weapon 2 Swap", ["Helm"] = "Helmet", ["BodyArmour"] = "Body Armour", ["Gloves"] = "Gloves", ["Boots"] = "Boots", ["Amulet"] = "Amulet", ["Ring"] = "Ring 1", ["Ring2"] = "Ring 2", ["Ring3"] = "Ring 3", ["Belt"] = "Belt" } function ImportTabClass:ImportItem(itemData, slotName) if not slotName then diff --git a/src/Classes/Item.lua b/src/Classes/Item.lua index 0bdc088852..f76e9c0801 100644 --- a/src/Classes/Item.lua +++ b/src/Classes/Item.lua @@ -1628,6 +1628,9 @@ function ItemClass:BuildModList() for i = 1, 2 do self.slotModList[i] = self:BuildModListForSlotNum(baseList, i) end + if self.type == "Ring" then + self.slotModList[3] = self:BuildModListForSlotNum(baseList, 3) + end else self.modList = self:BuildModListForSlotNum(baseList) end diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 5be775a69a..e534f880b3 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -27,7 +27,7 @@ local socketDropList = { { label = colorCodes.SCION.."S", color = "W" } } -local baseSlots = { "Weapon 1", "Weapon 2", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring 1", "Ring 2", "Belt", "Charm 1", "Charm 2", "Charm 3", "Flask 1", "Flask 2" } +local baseSlots = { "Weapon 1", "Weapon 2", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring 1", "Ring 2", "Ring 3","Belt", "Charm 1", "Charm 2", "Charm 3", "Flask 1", "Flask 2" } local catalystQualityFormat = { "^x7F7F7FQuality (Life Modifiers): "..colorCodes.MAGIC.."+%d%% (augmented)", @@ -120,6 +120,10 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro swapSlot.shown = function() return self.activeItemSet.useSecondWeaponSet end + elseif slotName == "Ring 3" then + slot.shown = function() + return self.build.calcsTab.mainEnv.modDB:Flag(nil, "AdditionalRingSlot") + end end end @@ -3054,7 +3058,7 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode) -- Build sorted list of slots to compare with local compareSlots = { } for slotName, slot in pairs(self.slots) do - if self:IsItemValidForSlot(item, slotName) and not slot.inactive and (not slot.weaponSet or slot.weaponSet == (self.activeItemSet.useSecondWeaponSet and 2 or 1)) then + if self:IsItemValidForSlot(item, slotName) and not slot.inactive and (not slot.weaponSet or slot.weaponSet == (self.activeItemSet.useSecondWeaponSet and 2 or 1)) and slot.shown() then t_insert(compareSlots, slot) end end diff --git a/src/Classes/SkillListControl.lua b/src/Classes/SkillListControl.lua index 02a95c3ffe..891f4374b4 100644 --- a/src/Classes/SkillListControl.lua +++ b/src/Classes/SkillListControl.lua @@ -22,6 +22,7 @@ local slot_map = { ["Amulet"] = { icon = NewImageHandle(), path = "Assets/icon_amulet.png" }, ["Ring 1"] = { icon = NewImageHandle(), path = "Assets/icon_ring_left.png" }, ["Ring 2"] = { icon = NewImageHandle(), path = "Assets/icon_ring_right.png" }, + ["Ring 3"] = { icon = NewImageHandle(), path = "Assets/icon_ring_right.png" }, ["Belt"] = { icon = NewImageHandle(), path = "Assets/icon_belt.png" }, } diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 5ddbd0a2e9..c82494836a 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -23,6 +23,7 @@ local groupSlotDropList = { { label = "Amulet", slotName = "Amulet" }, { label = "Ring 1", slotName = "Ring 1" }, { label = "Ring 2", slotName = "Ring 2" }, + { label = "Ring 3", slotName = "Ring 3" }, { label = "Belt", slotName = "Belt" }, } diff --git a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua index 81db94815a..39325f3331 100644 --- a/src/Classes/TradeQuery.lua +++ b/src/Classes/TradeQuery.lua @@ -16,7 +16,7 @@ local m_min = math.min local m_ceil = math.ceil local s_format = string.format -local baseSlots = { "Weapon 1", "Weapon 2", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring 1", "Ring 2", "Belt", "Charm 1", "Charm 2", "Charm 3", "Flask 1", "Flask 2" } +local baseSlots = { "Weapon 1", "Weapon 2", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring 1", "Ring 2", "Ring 3", "Belt", "Charm 1", "Charm 2", "Charm 3", "Flask 1", "Flask 2" } local TradeQueryClass = newClass("TradeQuery", function(self, itemsTab) self.itemsTab = itemsTab diff --git a/src/Classes/TradeQueryGenerator.lua b/src/Classes/TradeQueryGenerator.lua index a9f63e1e55..71a5cefeaf 100644 --- a/src/Classes/TradeQueryGenerator.lua +++ b/src/Classes/TradeQueryGenerator.lua @@ -646,7 +646,7 @@ function TradeQueryGeneratorClass:StartQuery(slot, options) elseif slot.slotName == "Amulet" then itemCategoryQueryStr = "accessory.amulet" itemCategory = "Amulet" - elseif slot.slotName == "Ring 1" or slot.slotName == "Ring 2" then + elseif slot.slotName == "Ring 1" or slot.slotName == "Ring 2" or slot.slotName == "Ring 3" then itemCategoryQueryStr = "accessory.ring" itemCategory = "Ring" elseif slot.slotName == "Belt" then diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 4fabb6a8f4..e9d8a67b82 100755 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -85,6 +85,7 @@ c["+0% to Lightning Resistance"]={{[1]={flags=0,keywordFlags=0,name="LightningRe c["+0.15% to Thorns Critical Hit Chance"]={{[1]={flags=0,keywordFlags=0,name="CritChance",type="BASE",value=0.15}}," Thorns "} c["+0.15% to Thorns Critical Hit Chance +25% to Thorns Critical Hit Chance"]={{[1]={flags=0,keywordFlags=0,name="CritChance",type="BASE",value=0.15}}," Thorns +25% to Thorns Critical Hit Chance "} c["+1 Charm Slot"]={{[1]={flags=0,keywordFlags=0,name="CharmLimit",type="BASE",value=1}},nil} +c["+1 Ring Slot"]={{[1]={flags=0,keywordFlags=0,name="AdditionalRingSlot",type="FLAG",value=true}},nil} c["+1 metre to Dodge Roll distance"]={{}," metre to Dodge Roll distance "} c["+1 metre to Dodge Roll distance 50% increased Evasion Rating if you've Dodge Rolled Recently"]={{[1]={[1]={type="Condition",var="DodgeRolledRecently"},flags=0,keywordFlags=0,name="Evasion",type="BASE",value=1}}," metre to Dodge Roll distance 50% increased "} c["+1 to Evasion Rating per 1 Armour on Equipped Gloves"]={{[1]={[1]={div=1,stat="ArmourOnGloves",type="PerStat"},flags=0,keywordFlags=0,name="Evasion",type="BASE",value=1}},nil} diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index e6d96fdee4..7fd8bd7ac5 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -348,7 +348,7 @@ local function determineCursePriority(curseName, activeSkill) elseif source ~= "" then sourcePriority = data.cursePriority["CurseFromEquipment"] end - if source ~= "" and slotPriority == data.cursePriority["Ring 2"] then + if source ~= "" and (slotPriority == data.cursePriority["Ring 2"] or slotPriority == data.cursePriority["Ring 3"]) then -- Implicit and explicit curses from rings have equal priority; only curses from socketed skill gems care about which ring slot they're equipped in slotPriority = data.cursePriority["Ring 1"] end @@ -1069,7 +1069,7 @@ function calcs.perform(env, skipEHP) end local modCopy = copyTable(mod) - modCopy.source = "Many Sources:".. colorCodes.UNIQUE .. "Ingenuity " .. colorCodes.SOURCE .. tostring(ringsEffectMod * 100) .. "% Ring 1 Bonus Effect" + modCopy.source = "Many Sources:".. colorCodes.SOURCE .. tostring(ringsEffectMod * 100) .. "% Ring 1 Bonus Effect" modDB:ScaleAddMod(modCopy, ringsEffectMod) ::skip_mod:: @@ -1091,9 +1091,51 @@ function calcs.perform(env, skipEHP) end local modCopy = copyTable(mod) - modCopy.source = "Many Sources:".. colorCodes.UNIQUE .. "Ingenuity " .. colorCodes.SOURCE .. tostring(ringsEffectMod * 100) .. "% Ring 2 Bonus Effect" + modCopy.source = "Many Sources:".. colorCodes.SOURCE .. tostring(ringsEffectMod * 100) .. "% Ring 2 Bonus Effect" modDB:ScaleAddMod(modCopy, ringsEffectMod) + ::skip_mod:: + end + end + if env.player.itemList["Ring 3"] then + local slotName = "Ring 3" + + if env.player.itemList["Ring 3"].name:match("Kalandra's Touch") and env.player.itemList["Ring 2"] and not env.player.itemList["Ring 2"].name:match("Kalandra's Touch") then + slotName = "Ring 2" + end + + for _, mod in ipairs(env.player.itemList[slotName].modList or env.player.itemList[slotName].slotModList[1]) do + -- Filter out SocketedIn type mods + for _, tag in ipairs(mod) do + if tag.type == "SocketedIn" then + goto skip_mod + end + end + + local modCopy = copyTable(mod) + modCopy.source = "Many Sources:".. colorCodes.SOURCE .. tostring(ringsEffectMod * 100) .. "% Ring 3 Bonus Effect" + modDB:ScaleAddMod(modCopy, ringsEffectMod) + + ::skip_mod:: + end + end + end + + local amuletsEffectMod = modDB:Sum("INC", nil, "EffectOfBonusesFromAmulets") / 100 + if amuletsEffectMod > 0 then + if env.player.itemList["Amulet"] then + for _, mod in ipairs(env.player.itemList["Amulet"].modList or env.player.itemList["Amulet"].slotModList[1]) do + -- Filter out SocketedIn type mods + for _, tag in ipairs(mod) do + if tag.type == "SocketedIn" then + goto skip_mod + end + end + + local modCopy = copyTable(mod) + modCopy.source = "Many Sources:".. colorCodes.SOURCE .. tostring(amuletsEffectMod * 100) .. "% Amulet Bonus Effect" + modDB:ScaleAddMod(modCopy, amuletsEffectMod) + ::skip_mod:: end end diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 103ac6ee65..79ad9d925c 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -1073,7 +1073,7 @@ function calcs.initEnv(build, mode, override, specEnv) else env.itemModDB.multipliers["NonCorruptedItem"] = (env.itemModDB.multipliers["NonCorruptedItem"] or 0) + 1 end - local otherRing = items[(slotName == "Ring 1" and "Ring 2") or (slotName == "Ring 2" and "Ring 1")] + local otherRing = items[(slotName == "Ring 1" and "Ring 2") or (slotName == "Ring 2" and "Ring 1") or (slotName == "Ring 3" and "Ring 2")] if otherRing and not otherRing.name:match("Kalandra's Touch") then for _, mod in ipairs(otherRing.modList or otherRing.slotModList[slot.slotNum] or {}) do -- Filter out SocketedIn type mods diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index 6687c67651..d0e5a88f52 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -264,7 +264,8 @@ data.cursePriority = { ["Boots"] = 7000, ["Ring 1"] = 8000, ["Ring 2"] = 9000, - ["CurseFromEquipment"] = 10000, + ["Ring 3"] = 10000, + ["CurseFromEquipment"] = 11000, ["CurseFromAura"] = 20000, } diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 9e7fc9ea25..7a74b48b67 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -2777,6 +2777,7 @@ local specialModList = { ["non%-channelling spells cost an additional (%d+)%% of maximum energy shield"] = function(num) return { mod("ESCostBase", "BASE", 1, nil, 0, KeywordFlag.Spell, { type = "PercentStat", percent = num, stat = "EnergyShield" }, { type = "SkillType", skillType = SkillType.Channel, neg = true } )} end, ["non%-channelling spells consume power charges to deal (%d+)%% more damage"] = function(num) return { mod("Damage", "MORE", num, nil, 0,KeywordFlag.Spell, { type = "SkillType", skillType = SkillType.Channel, neg = true }, { type = "MultiplierThreshold", var = "RemovablePowerCharge", threshold = 1 })} end, ["no inherent mana regeneration"] = { flag("Condition:NoInherentManaRegen") }, + ["%+1 ring slot"] = { flag("AdditionalRingSlot") }, ["regenerate (%D+) equal to (%d+)%% of maximum (%D+) per second"] = function(_, resource1, num, resource2) return { mod( combineToUpper(resource1) .. "Regen", "BASE", 1, { type = "PercentStat", stat = combineToUpper(resource2), percent = num } )} end, -- Mercenary -- +2 Weapon Set Passive Skill Points @@ -4228,6 +4229,10 @@ local specialModList = { ["projectiles deal (%d+)%% increased damage with hits and ailments for each enemy pierced"] = function(num) return { mod("Damage", "INC", num, nil, 0, bor(KeywordFlag.Hit, KeywordFlag.Ailment), { type = "PerStat", stat = "PiercedCount" }, { type = "SkillType", skillType = SkillType.Projectile }) } end, ["(%d+)%% increased bonuses gained from equipped quiver"] = function(num) return {mod("EffectOfBonusesFromQuiver", "INC", num)} end, ["(%d+)%% increased bonuses gained from equipped rings"] = function(num) return {mod("EffectOfBonusesFromRings", "INC", num)} end, + ["(%d+)%% increased bonuses gained from equipped rings and amulets"] = function(num) return { + mod("EffectOfBonusesFromRings", "INC", num), + mod("EffectOfBonusesFromAmulets", "INC", num), + } end, ["(%d+)%% chance for spell skills to fire 2 additional projectiles"] = function(num) return { mod("TwoAdditionalProjectilesChance", "BASE", num, nil , ModFlag.Spell) } end, -- Strike Skills ["non%-vaal strike skills target (%d+) additional nearby enem[yi]e?s?"] = function(num) return { mod("AdditionalStrikeTarget", "BASE", num, { type = "SkillType", skillType = SkillType.MeleeSingleTarget}, { type = "SkillType", skillType = SkillType.Vaal, neg = true}) } end,