diff --git a/src/Classes/Item.lua b/src/Classes/Item.lua index e9f7cbc75c..c9f8c0d6e2 100644 --- a/src/Classes/Item.lua +++ b/src/Classes/Item.lua @@ -277,6 +277,14 @@ function ItemClass:FindModifierSubstring(substring, itemSlotName) end end end + -- Also check GGPK-exported mod tags (e.g. "defences" tag catches mods that don't mention defence in text) + if v.modTags then + for _, tag in ipairs(v.modTags) do + if tag:lower():find(substring) then + return true + end + end + end end end return false diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 9a8162b911..0224d2f489 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -2670,13 +2670,30 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() elseif sourceId == "ESSENCE" then for _, essence in pairs(self.build.data.essences) do local modId = essence.mods[self.displayItem.type] - local mod = self.displayItem.affixes[modId] - t_insert(modList, { - label = essence.name .. " " .. "^8[" .. table.concat(mod, "/") .. "]" .. " (" .. mod.type .. ")", - mod = mod, - type = "custom", - essence = essence, - }) + if modId then + local mod = self.displayItem.affixes[modId] + t_insert(modList, { + label = essence.name .. " " .. "^8[" .. table.concat(mod, "/") .. "]" .. " (" .. mod.type .. ")", + mod = mod, + type = "custom", + essence = essence, + }) + end + -- Some essences (Desolation) have different mods per ring slot + if self.displayItem.type == "Ring" then + for _, slotKey in ipairs({"Ring 1", "Ring 2"}) do + local slotModId = essence.mods[slotKey] + if slotModId then + local mod = self.displayItem.affixes[slotModId] + t_insert(modList, { + label = essence.name .. " (" .. slotKey .. ") " .. "^8[" .. table.concat(mod, "/") .. "]" .. " (" .. mod.type .. ")", + mod = mod, + type = "custom", + essence = essence, + }) + end + end + end end table.sort(modList, function(a, b) if a.essence.type ~= b.essence.type then diff --git a/src/Data/Essence.lua b/src/Data/Essence.lua index 733cf5d6dc..5a64ade346 100644 --- a/src/Data/Essence.lua +++ b/src/Data/Essence.lua @@ -106,4 +106,5 @@ return { ["Metadata/Items/Currency/CurrencyEssenceInsanity1"] = { name = "Essence of Insanity", type = 21, tier = 8, mods = { ["Amulet"] = "ChanceToRecoverManaOnSkillUseEssence1", ["Belt"] = "MovementVelocityDuringFlaskEffectEssence1", ["Body Armour"] = "OnslaughtWhenHitNewEssence1", ["Boots"] = "ManaRegenerationWhileShockedEssence1", ["Bow"] = "SpiritMinionEssence1", ["Claw"] = "SpiritMinionEssence1", ["Dagger"] = "SpiritMinionEssence1", ["Gloves"] = "SocketedGemsHaveMoreAttackAndCastSpeedEssenceNew1", ["Helmet"] = "SocketedGemsAddPercentageOfPhysicalAsLightningEssence1", ["One Handed Axe"] = "SpiritMinionEssence1", ["One Handed Mace"] = "SpiritMinionEssence1", ["One Handed Sword"] = "SpiritMinionEssence1", ["Quiver"] = "AdditionalPierceEssence7", ["Ring"] = "ReflectDamageTakenEssence1", ["Sceptre"] = "SpiritMinionEssence1", ["Shield"] = "PowerChargeOnBlockEssence1", ["Staff"] = "SpiritMinionEssence1", ["Thrusting One Handed Sword"] = "SpiritMinionEssence1", ["Two Handed Axe"] = "SpiritMinionEssence1", ["Two Handed Mace"] = "SpiritMinionEssence1", ["Two Handed Sword"] = "SpiritMinionEssence1", ["Wand"] = "SpiritMinionEssence1", }, }, ["Metadata/Items/Currency/CurrencyEssenceHorror1"] = { name = "Essence of Horror", type = 22, tier = 8, mods = { ["Amulet"] = "CrushOnHitChanceEssence1", ["Belt"] = "AlchemistsGeniusOnFlaskEssence1_", ["Body Armour"] = "ReducedDamageFromCriticalStrikesPerEnduranceChargeEssence1", ["Boots"] = "ElementalDamageTakenWhileStationaryEssence1", ["Bow"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Claw"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Dagger"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Gloves"] = "SocketedSkillsCriticalChanceEssence1", ["Helmet"] = "SocketedGemsDealMoreElementalDamageEssence1", ["One Handed Axe"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["One Handed Mace"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["One Handed Sword"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Quiver"] = "AddedColdDamagePerFrenzyChargeEssenceQuiver1", ["Ring"] = "AddedColdDamagePerFrenzyChargeEssence1", ["Sceptre"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Shield"] = "NearbyEnemiesChilledOnBlockEssence1", ["Staff"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Thrusting One Handed Sword"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Two Handed Axe"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Two Handed Mace"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Two Handed Sword"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", ["Wand"] = "PowerFrenzyOrEnduranceChargeOnKillEssence1", }, }, ["Metadata/Items/Currency/CurrencyEssenceDelirium1"] = { name = "Essence of Delirium", type = 23, tier = 8, mods = { ["Amulet"] = "SpellBlockAmuletEssence1", ["Belt"] = "ChaosResistanceWhileUsingFlaskEssence1", ["Body Armour"] = "ChaosDamageOverTimeTakenEssence1", ["Boots"] = "CannotBePoisonedEssence1", ["Bow"] = "DecayOnHitEssence1", ["Claw"] = "DecayOnHitEssence1", ["Dagger"] = "DecayOnHitEssence1", ["Gloves"] = "SupportDamageOverTimeEssence1", ["Helmet"] = "SocketedAuraGemLevelsEssence1", ["One Handed Axe"] = "DecayOnHitEssence1", ["One Handed Mace"] = "DecayOnHitEssence1", ["One Handed Sword"] = "DecayOnHitEssence1", ["Quiver"] = "MarkEffectEssence1", ["Ring"] = "GlobalDamageOverTimeMultiplierRingEssence1", ["Sceptre"] = "DecayOnHitEssence1", ["Shield"] = "SpellBlockOnLowLifeEssence1", ["Staff"] = "DecayOnHitEssence1", ["Thrusting One Handed Sword"] = "DecayOnHitEssence1", ["Two Handed Axe"] = "DecayOnHitEssence1", ["Two Handed Mace"] = "DecayOnHitEssence1", ["Two Handed Sword"] = "DecayOnHitEssence1", ["Wand"] = "DecayOnHitEssence1", }, }, + ["Metadata/Items/Currency/CurrencyEssenceDesolation1"] = { name = "Essence of Desolation", type = 24, tier = 8, mods = { ["Amulet"] = "AilmentDurationEssenceDesolation1", ["Belt"] = "MagicFlaskEffectEssenceDesolation1", ["Body Armour"] = "GlobalDefencesEssenceDesolation1", ["Boots"] = "MovementSpeedPerEnemyEssenceDesolation1", ["Gloves"] = "AttackCastSpeedPerEnemyEssenceDesolation1", ["Helmet"] = "SocketedGemLevelEssenceDesolation1", ["Quiver"] = "ProjectileChainCloseRangeEssenceDesolation1", ["Ring 1"] = "UnleashSealsEssenceDesolation1", ["Ring 2"] = "ShockwaveCooldownEssenceDesolation1", ["Shield"] = "ArmourAppliesToEleDamageEssenceDesolation1", ["Claw"] = "DoubleDamagePerAilmentEssenceDesolation1", ["Dagger"] = "DoubleDamagePerAilmentEssenceDesolation1", ["One Handed Axe"] = "DoubleDamagePerAilmentEssenceDesolation1", ["One Handed Mace"] = "DoubleDamagePerAilmentEssenceDesolation1", ["One Handed Sword"] = "DoubleDamagePerAilmentEssenceDesolation1", ["Thrusting One Handed Sword"] = "DoubleDamagePerAilmentEssenceDesolation1", ["Wand"] = "DoubleDamagePerAilmentEssenceDesolation1", ["Sceptre"] = "DoubleDamagePerAilmentEssenceDesolation1", ["Bow"] = "DoubleDamagePerAilmentEssenceDesolationTwoHand1", ["Staff"] = "DoubleDamagePerAilmentEssenceDesolationTwoHand1", ["Two Handed Axe"] = "DoubleDamagePerAilmentEssenceDesolationTwoHand1", ["Two Handed Mace"] = "DoubleDamagePerAilmentEssenceDesolationTwoHand1", ["Two Handed Sword"] = "DoubleDamagePerAilmentEssenceDesolationTwoHand1", }, }, } \ No newline at end of file diff --git a/src/Data/ModItem.lua b/src/Data/ModItem.lua index ed03273684..bcb76415c4 100644 --- a/src/Data/ModItem.lua +++ b/src/Data/ModItem.lua @@ -1934,6 +1934,18 @@ return { ["MovementSpeedOnBurningChilledShockedGroundEssence1"] = { type = "Suffix", affix = "of the Essence", "12% increased Movement speed while on Burning, Chilled or Shocked ground", statOrder = { 9245 }, level = 63, group = "MovementSpeedOnBurningChilledShockedGround", weightKey = { "default", }, weightVal = { 0 }, modTags = { "speed" }, }, ["ManaRegenerationWhileShockedEssence1"] = { type = "Suffix", affix = "of the Essence", "70% increased Mana Regeneration Rate while Shocked", statOrder = { 2419 }, level = 63, group = "ManaRegenerationWhileShocked", weightKey = { "default", }, weightVal = { 0 }, modTags = { "resource", "mana" }, }, ["ManaGainedOnBlockEssence1"] = { type = "Suffix", affix = "of the Essence", "Recover 5% of your maximum Mana when you Block", statOrder = { 8028 }, level = 63, group = "ManaGainedOnBlock", weightKey = { "default", }, weightVal = { 0 }, modTags = { "block", "resource", "mana" }, }, + ["DoubleDamagePerAilmentEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "1% chance to deal Double Damage against Enemies for each type of Ailment you have inflicted on them", statOrder = { 9900 }, level = 63, group = "DoubleDamagePerAilmentEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "damage" }, }, + ["DoubleDamagePerAilmentEssenceDesolationTwoHand1"] = { type = "Suffix", affix = "of the Essence", "2% chance to deal Double Damage against Enemies for each type of Ailment you have inflicted on them", statOrder = { 9900 }, level = 63, group = "DoubleDamagePerAilmentEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "damage" }, }, + ["MovementSpeedPerEnemyEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "5% increased Movement Speed for each nearby Enemy, up to a maximum of 50%", statOrder = { 9901 }, level = 63, group = "MovementSpeedPerEnemyEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "speed" }, }, + ["GlobalDefencesEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "(70-90)% increased Global Defences if there are no Defence Modifiers on other Equipped Items", statOrder = { 9902 }, level = 63, group = "GlobalDefencesEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "defences" }, }, + ["SocketedGemLevelEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "+6 to Level of Socketed Gems while there is a single Gem Socketed in this Item", statOrder = { 9903 }, level = 63, group = "SocketedGemLevelEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "gem" }, }, + ["ArmourAppliesToEleDamageEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "(2-4)% of Armour applies to Fire, Cold and Lightning Damage taken from Hits if you have Blocked Recently", statOrder = { 9904 }, level = 63, group = "ArmourAppliesToEleDamageEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "armour", "defences", "elemental" }, }, + ["ProjectileChainCloseRangeEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "Projectiles can Chain from any number of additional targets in Close Range", statOrder = { 9905 }, level = 63, group = "ProjectileChainCloseRangeEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "attack" }, }, + ["AilmentDurationEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "(40-60)% increased Duration of Ailments of types you haven't inflicted Recently", statOrder = { 9906 }, level = 63, group = "AilmentDurationEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "ailment" }, }, + ["UnleashSealsEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "Left ring slot: Skills supported by Unleash have +1 to maximum number of Seals", statOrder = { 9907 }, level = 63, group = "UnleashSealsEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "caster" }, }, + ["ShockwaveCooldownEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "Right ring slot: Shockwave has +1 to Cooldown Uses", statOrder = { 9908 }, level = 63, group = "ShockwaveCooldownEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "attack" }, }, + ["AttackCastSpeedPerEnemyEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "5% increased Attack and Cast Speed for each nearby Enemy, up to a maximum of 30%", statOrder = { 9910 }, level = 63, group = "AttackCastSpeedPerEnemyEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "speed", "attack", "caster" }, }, + ["MagicFlaskEffectEssenceDesolation1"] = { type = "Suffix", affix = "of the Essence", "Equipped Magic Flasks have 30% increased effect on you if no Flasks are Adjacent to them", statOrder = { 9909 }, level = 63, group = "MagicFlaskEffectEssence", weightKey = { "default", }, weightVal = { 0 }, modTags = { "flask" }, }, ["BleedDuration1"] = { type = "Suffix", affix = "of Agony", "(8-12)% increased Bleeding Duration", statOrder = { 4893 }, level = 30, group = "BleedDuration", weightKey = { "bow", "sword", "axe", "mace", "default", }, weightVal = { 0, 0, 0, 0, 0 }, modTags = { "bleed", "physical", "attack", "ailment" }, }, ["BleedDuration2"] = { type = "Suffix", affix = "of Torment", "(13-18)% increased Bleeding Duration", statOrder = { 4893 }, level = 60, group = "BleedDuration", weightKey = { "bow", "sword", "axe", "mace", "default", }, weightVal = { 0, 0, 0, 0, 0 }, modTags = { "bleed", "physical", "attack", "ailment" }, }, ["ChanceToIgnite1"] = { type = "Suffix", affix = "of Ignition", "(18-24)% chance to Ignite", statOrder = { 1937 }, level = 15, group = "ChanceToIgnite", weightKey = { "sceptre", "wand", "default", }, weightVal = { 1000, 1000, 0 }, modTags = { "elemental", "fire", "ailment" }, }, diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 05b2d161b5..fdf47d2f62 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -1434,6 +1434,7 @@ function calcs.perform(env, skipEHP) local effectInc = modDB:Sum("INC", {actor = "player"}, "FlaskEffect") local effectIncMagic = modDB:Sum("INC", {actor = "player"}, "MagicUtilityFlaskEffect") + local effectIncMagicNoAdjacent = modDB:Sum("INC", {actor = "player"}, "MagicFlaskEffect") local effectIncNonPlayer = modDB:Sum("INC", nil, "FlaskEffect") local effectIncMagicNonPlayer = modDB:Sum("INC", nil, "MagicUtilityFlaskEffect") local flasksApplyToMinion = env.minion and modDB:Flag(env.player.mainSkill.skillCfg, "FlasksApplyToMinion") @@ -1523,6 +1524,16 @@ function calcs.perform(env, skipEHP) flaskEffectInc = flaskEffectInc + effectIncMagic flaskEffectIncNonPlayer = flaskEffectIncNonPlayer + effectIncMagicNonPlayer end + -- Essence of Desolation belt mod: bonus for magic flasks with no flask in an adjacent slot (1-5) + if item.rarity == "MAGIC" and effectIncMagicNoAdjacent ~= 0 then + local flaskSlotNum = env.flaskSlotMap and env.flaskSlotMap[item] + if flaskSlotNum then + local hasAdjacent = (env.flaskSlotOccupied[flaskSlotNum - 1] or env.flaskSlotOccupied[flaskSlotNum + 1]) + if not hasAdjacent then + flaskEffectInc = flaskEffectInc + effectIncMagicNoAdjacent + end + end + end local effectMod = 1 + (flaskEffectInc) / 100 local effectModNonPlayer = 1 + (flaskEffectIncNonPlayer) / 100 diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index e33109c645..422c111dfe 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -862,12 +862,20 @@ function calcs.initEnv(build, mode, override, specEnv) end end + -- Track which flask slot (1-5) each flask is in, for adjacency checks + env.flaskSlotMap = { } + env.flaskSlotOccupied = { } for _, slot in pairs(build.itemsTab.orderedSlots) do local slotName = slot.slotName local item = items[slotName] if item and item.type == "Flask" then if slot.active then env.flasks[item] = true + local flaskNum = tonumber(slotName:match("Flask (%d+)")) + if flaskNum then + env.flaskSlotMap[item] = flaskNum + env.flaskSlotOccupied[flaskNum] = true + end end if item.base.subType == "Life" then local highestLifeRecovery = env.itemModDB.multipliers["LifeFlaskRecovery"] or 0 @@ -1162,6 +1170,9 @@ function calcs.initEnv(build, mode, override, specEnv) end end env.itemModDB.multipliers["SocketedGemsIn"..slotName] = (env.itemModDB.multipliers["SocketedGemsIn"..slotName] or 0) + math.min(slotGemSocketsCount, socketedGems) + if socketedGems == 1 then + env.itemModDB.conditions["SingleGemSocketedIn"..slotName] = true -- for Essence of Desolation helmet mod + end 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 diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index feac95a2b0..f6123b6314 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -1237,6 +1237,12 @@ Huge sets the radius to 11. { var = "multiplierPoisonAppliedRecently", type = "count", label = "# of Poisons applied Recently:", ifMult = "PoisonAppliedRecently", apply = function(val, modList, enemyModList) modList:NewMod("Multiplier:PoisonAppliedRecently", "BASE", val, "Config", { type = "Condition", var = "Combat" }) end }, + { var = "conditionCausedBleedingRecently", type = "check", label = "Have you caused ^xE05030Bleeding ^7Recently?", ifCond = "CausedBleedingRecently", apply = function(val, modList, enemyModList) + modList:NewMod("Condition:CausedBleedingRecently", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) + end }, + { var = "conditionPoisonedEnemyRecently", type = "check", label = "Have you ^x60A060Poisoned ^7an enemy Recently?", ifCond = "PoisonedEnemyRecently", apply = function(val, modList, enemyModList) + modList:NewMod("Condition:PoisonedEnemyRecently", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) + end }, { var = "multiplierLifeSpentRecently", type = "count", label = "# of ^xE05030Life ^7spent Recently:", ifMult = "LifeSpentRecently", apply = function(val, modList, enemyModList) modList:NewMod("Multiplier:LifeSpentRecently", "BASE", val, "Config", { type = "Condition", var = "Combat" }) end }, diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index be484e0c32..49eaa97e4a 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -646,6 +646,21 @@ data.itemTagSpecial = { "Cannot Evade", }, }, + -- Text patterns for ItemCondition "no Defence Modifiers"; also backed by modTags in FindModifierSubstring + ["defence"] = (function() + local defencePatterns = { + "[Aa]rmour", + "[Ee]vasion", + "[Ee]nergy [Ss]hield", + "[Ww]ard", + } + local slots = { "weapon 1", "weapon 2", "helmet", "body armour", "gloves", "boots", "amulet", "ring 1", "ring 2", "belt", "shield" } + local t = {} + for _, slot in ipairs(slots) do + t[slot] = defencePatterns + end + return t + end)(), } data.itemTagSpecialExclusionPattern = { ["life"] = { diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index fd91130b3e..dc81d3d9bd 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -5344,6 +5344,43 @@ local specialModList = { ["(%d+)%% more frozen legion and general's cry cooldown recovery rate"] = function(num) return { mod("CooldownRecovery", "MORE", num, { type = "SkillName", skillNameList = { "Frozen Legion", "General's Cry" }, includeTransfigured = true }) } end, ["flamethrower, seismic and lightning spire trap have (%d+)%% increased cooldown recovery rate"] = function(num) return { mod("CooldownRecovery", "INC", num, { type = "SkillName", skillNameList = { "Flamethrower Trap", "Seismic Trap", "Lightning Spire Trap" }, includeTransfigured = true }) } end, ["flamethrower, seismic and lightning spire trap have %-(%d+) cooldown uses?"] = function(num) return { mod("AdditionalCooldownUses", "BASE", -num, { type = "SkillName", skillNameList = { "Flamethrower Trap", "Seismic Trap", "Lightning Spire Trap" }, includeTransfigured = true }) } end, + ["shockwave has %+(%d+) to cooldown uses?"] = function(num) return { mod("AdditionalCooldownUses", "BASE", num, { type = "SkillName", skillName = "Shockwave", includeTransfigured = true }) } end, + -- Stacks per ailment type on enemy; one entry per ailment so they each contribute independently + ["(%d+)%% chance to deal double damage against enemies for each type of ailment you have inflicted on them"] = function(num) return { + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Frozen" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Chilled" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Ignited" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Shocked" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Scorched" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Brittle" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Sapped" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Bleeding" }), + mod("DoubleDamageChance", "BASE", num, { type = "ActorCondition", actor = "enemy", var = "Poisoned" }), + } end, + ["(%d+)%% increased movement speed for each nearby enemy, up to a maximum of (%d+)%%"] = function(num, _, limit) return { mod("MovementSpeed", "INC", num, { type = "Multiplier", var = "NearbyEnemies", limit = tonumber(limit), limitTotal = true }) } end, + ["(%d+)%% increased attack and cast speed for each nearby enemy, up to a maximum of (%d+)%%"] = function(num, _, limit) return { mod("Speed", "INC", num, { type = "Multiplier", var = "NearbyEnemies", limit = tonumber(limit), limitTotal = true }) } end, + -- {SlotName} gets replaced with the actual slot (e.g. "Helmet") by Item.lua when the mod is applied + ["%+(%d+) to level of socketed gems while there is a single gem socketed in this item"] = function(num) return { + mod("GemProperty", "LIST", { keyword = "all", key = "level", value = num }, { type = "SocketedIn", slotName = "{SlotName}" }, { type = "Condition", var = "SingleGemSocketedIn{SlotName}" }), + } end, + ["(%d+)%% of armour applies to fire, cold and lightning damage taken from hits if you have blocked recently"] = function(num) return { + mod("ArmourAppliesToFireDamageTaken", "BASE", num, { type = "Condition", var = "BlockedRecently" }), + mod("ArmourAppliesToColdDamageTaken", "BASE", num, { type = "Condition", var = "BlockedRecently" }), + mod("ArmourAppliesToLightningDamageTaken", "BASE", num, { type = "Condition", var = "BlockedRecently" }), + } end, + -- "any number" modeled as +99; displays oddly in tooltip but calcs are correct + ["projectiles can chain from any number of additional targets in close range"] = { mod("ChainCountMax", "BASE", 99, nil, ModFlag.Projectile, { type = "Condition", var = "AtCloseRange" }) }, + -- Per-ailment duration; freeze/chill share a condition since they're both cold-based + ["(%d+)%% increased duration of ailments of types you haven't inflicted recently"] = function(num) return { + mod("EnemyFreezeDuration", "INC", num, { type = "Condition", var = "FrozenEnemyRecently", neg = true }), + mod("EnemyChillDuration", "INC", num, { type = "Condition", var = "FrozenEnemyRecently", neg = true }), + mod("EnemyIgniteDuration", "INC", num, { type = "Condition", var = "IgnitedEnemyRecently", neg = true }), + mod("EnemyShockDuration", "INC", num, { type = "Condition", var = "ShockedEnemyRecently", neg = true }), + mod("EnemyBleedDuration", "INC", num, { type = "Condition", var = "CausedBleedingRecently", neg = true }), + mod("EnemyPoisonDuration", "INC", num, { type = "Condition", var = "PoisonedEnemyRecently", neg = true }), + } end, + -- Adjacency checked in CalcPerform using flask slot positions (Flask 1-5) + ["equipped magic flasks have (%d+)%% increased effect on you if no flasks are adjacent to them"] = function(num) return { mod("MagicFlaskEffect", "INC", num, { type = "Condition", var = "NoAdjacentFlasks" }) } end, ["flameblast starts with (%d+) additional stages"] = function(num) return { mod("Multiplier:FlameblastMinimumStage", "BASE", num, 0, 0, { type = "GlobalEffect", effectType = "Buff", unscalable = true }) } end, ["incinerate starts with (%d+) additional stages"] = function(num) return { mod("Multiplier:IncinerateMinimumStage", "BASE", num, 0, 0, { type = "GlobalEffect", effectType = "Buff", unscalable = true }) } end, ["%+([%d%.]+) seconds to flameblast and incinerate cooldown"] = function(num) return {