diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 0100226c0..54d9f45cc 100755 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -2775,7 +2775,7 @@ c["50% increased Skill Effect Duration"]={{[1]={flags=0,keywordFlags=0,name="Dur c["50% increased Spell damage for each 200 total Mana you have Spent Recently"]={{[1]={[1]={div=200,type="Multiplier",var="ManaSpentRecently"},flags=2,keywordFlags=0,name="Damage",type="INC",value=50}},nil} c["50% increased Spirit"]={{[1]={flags=0,keywordFlags=0,name="Spirit",type="INC",value=50}},nil} c["50% increased Strength Requirement"]={{[1]={flags=0,keywordFlags=0,name="StrRequirement",type="INC",value=50}},nil} -c["50% increased Surrounded Area of Effect"]={{[1]={flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=50}}," Surrounded "} +c["50% increased Surrounded Area of Effect"]={{[1]={flags=0,keywordFlags=0,name="SurroundedArea",type="INC",value=50}},nil} c["50% increased Thorns damage if you've consumed an Endurance Charge Recently"]={{[1]={[1]={limit=1,type="Multiplier",var="RemovableEnduranceCharge"},flags=0,keywordFlags=0,name="ThornsDamage",type="INC",value=50}},nil} c["50% increased Totem Placement range"]={{[1]={flags=0,keywordFlags=16384,name="WeaponRange",type="INC",value=50}}," Placement "} c["50% increased amount of Mana Leeched"]={{[1]={flags=0,keywordFlags=0,name="MaxManaLeechRate",type="INC",value=50}},nil} @@ -5300,6 +5300,7 @@ c["Physical Damage Reduction from Armour is based on your combined Armour and Ev c["Physical Damage is Pinning"]={nil,"Physical Damage is Pinning "} c["Physical Spell Critical Hits build Pin"]={nil,"Physical Spell Critical Hits build Pin "} c["Pin Enemies which are Primed for Pinning"]={nil,"Pin Enemies which are Primed for Pinning "} +c["Pin Enemies which are Primed for Pinning Require 5 fewer enemies to be Surrounded"]={nil,"Pin Enemies which are Primed for Pinning Require 5 fewer enemies to be Surrounded "} c["Pinned Enemies cannot deal Critical Hits"]={nil,"Pinned Enemies cannot deal Critical Hits "} c["Pinned enemies cannot perform actions"]={nil,"Pinned enemies cannot perform actions "} c["Possessed by Spirit Of The Bear for 20 seconds on use"]={nil,"Possessed by Spirit Of The Bear for 20 seconds on use "} @@ -5439,6 +5440,8 @@ c["Remnants have 10% increased effect"]={nil,"Remnants have 10% increased effect c["Remnants you create reappear once, 3 seconds after being collected"]={nil,"Remnants you create reappear once, 3 seconds after being collected "} c["Remove Ignite when you Warcry"]={nil,"Remove Ignite when you Warcry "} c["Remove a Curse when you use a Mana Flask"]={nil,"Remove a Curse when you use a Mana Flask "} +c["Require 4 fewer enemies to be Surrounded"]={{[1]={flags=0,keywordFlags=0,name="SurroundedMinimum",type="BASE",value=-4}},nil} +c["Require 5 fewer enemies to be Surrounded"]={{[1]={flags=0,keywordFlags=0,name="SurroundedMinimum",type="BASE",value=-5}},nil} c["Reserves 25% of Life"]={{[1]={flags=0,keywordFlags=0,name="ExtraLifeReserved",type="BASE",value=25}},nil} c["Reveal Weaknesses against Rare and Unique enemies"]={nil,"Reveal Weaknesses against Rare and Unique enemies "} c["Reveal Weaknesses against Rare and Unique enemies 50% more damage against enemies with an Open Weakness"]={nil,"Reveal Weaknesses against Rare and Unique enemies 50% more damage against enemies with an Open Weakness "} diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 523b97d3f..d78d0f7eb 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -97,32 +97,37 @@ local function addWeaponBaseStats(actor) end end end --- Calculate Presence radius + +-- Generic radius/area calculator for a given key prefix (e.g. "Presence", "Surrounded") ---@param actor table -local function calcPresenceRadius(actor) +---@param key string -- e.g. "Presence" or "Surrounded" +local function calcBuffRadius(actor, key) + local radiusKey, areaKey , modKey = key .. "Radius", key .. "Area", key .. "Mod" -- Calculate modifications to radius first - local baseRadius = actor.modDB:Sum("BASE", nil, "PresenceRadius") - local incRadius = actor.modDB:Sum("INC", nil, "PresenceRadius") - local moreRadius = actor.modDB:More(nil, "PresenceRadius") - local scaledRadius = actor.modDB:Override(nil, "PresenceRadius") or baseRadius * (1 + incRadius / 100) * moreRadius + local baseRadius = actor.modDB:Sum("BASE", nil, radiusKey) + local incRadius = actor.modDB:Sum("INC", nil, radiusKey) + local moreRadius = actor.modDB:More(nil, radiusKey) + local scaledRadius = actor.modDB:Override(nil, radiusKey) or (baseRadius * (1 + incRadius / 100) * moreRadius) -- Calculate modifications to area second local baseArea = math.pi * (scaledRadius * scaledRadius) - local incArea = actor.modDB:Sum("INC", nil, "PresenceArea") - local moreArea = actor.modDB:More(nil, "PresenceArea") - local scaledArea = actor.modDB:Override(nil, "PresenceArea") or baseArea * (1 + incArea / 100) * moreArea + local incArea = actor.modDB:Sum("INC", nil, areaKey) + local moreArea = actor.modDB:More(nil, areaKey) + local scaledArea = actor.modDB:Override(nil, areaKey) or (baseArea * (1 + incArea / 100) * moreArea) -- Convert back to final radius local finalRadius = math.floor(math.sqrt(scaledArea / math.pi)) - actor.output["PresenceRadius"] = finalRadius - actor.output["PresenceRadiusMetres"] = finalRadius / 10 - if scaledRadius / baseRadius ~= 1 then actor.output["PresenceMod"] = scaledRadius / baseRadius end + actor.output[radiusKey] = finalRadius + actor.output[radiusKey .. "Metres"] = finalRadius / 10 + if scaledRadius / baseRadius ~= 1 then + actor.output[modKey] = scaledRadius / baseRadius + end if actor.breakdown then - actor.breakdown.PresenceRadius = actor.breakdown.area(scaledRadius, (1 + incArea / 100) * moreArea, finalRadius) + actor.breakdown[radiusKey] = actor.breakdown.area(scaledRadius, (1 + incArea / 100) * moreArea, finalRadius) if baseRadius ~= scaledRadius then - actor.breakdown.PresenceMod = {} - t_insert(actor.breakdown.PresenceMod, s_format( "%.1fm ^8(base radius)", baseRadius / 10)) - t_insert(actor.breakdown.PresenceMod, s_format( " x %.2f ^8(inc)", 1 + incRadius / 100)) - t_insert(actor.breakdown.PresenceMod, s_format( " x %.2f ^8(more)", moreRadius)) - t_insert(actor.breakdown.PresenceMod, s_format( "= %.1fm", scaledRadius / 10)) + actor.breakdown[modKey] = {} + t_insert(actor.breakdown[modKey], s_format("%.1fm ^8(base radius)", baseRadius / 10)) + t_insert(actor.breakdown[modKey], s_format(" x %.2f ^8(inc)", 1 + incRadius / 100)) + t_insert(actor.breakdown[modKey], s_format(" x %.2f ^8(more)", moreRadius)) + t_insert(actor.breakdown[modKey], s_format(" = %.1fm", scaledRadius / 10)) end end end @@ -384,10 +389,13 @@ local function doActorAttribsConditions(env, actor) end end end - -- Calculate Presence value and set condition - calcPresenceRadius(actor) + -- Calculate Presence / Surrounded value and set condition + calcBuffRadius(actor, "Presence") + calcBuffRadius(actor, "Surrounded") local enemyDistance = m_max(modDB:Sum("BASE", nil, "Multiplier:enemyDistance"), 0) + local surroundedMinimum= m_max(modDB:Sum("BASE", nil, "SurroundedMinimum"), 0) condList["EnemyInPresence"] = output.PresenceRadius >= enemyDistance + condList["Surrounded"] = surroundedMinimum == 0 or surroundedMinimum == 1 and output.SurroundedRadius >= enemyDistance end -- Helper function to determine curse priority when processing curses beyond the curse limit diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index f6fa5ae17..145569774 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -1405,6 +1405,8 @@ return { }, }, { label = "Presence Mod", haveOutput = "PresenceMod", { format = "{2:output:PresenceMod}", { breakdown = "PresenceMod" }, { modName = "PresenceRadius", cfg = "skill" }} , }, { label = "Presence Radius", haveOutput = "PresenceRadius", { format = "{1:output:PresenceRadiusMetres}m", { breakdown = "PresenceRadius" }, { modName = "PresenceArea", cfg = "skill"} }, }, + { label = "Surrounded Mod", haveOutput = "SurroundedMod", { format = "{2:output:SurroundedMod}", { breakdown = "SurroundedMod" }, { modName = "SurroundedRadius", cfg = "skill" }} , }, + { label = "Surrounded Radius", haveOutput = "SurroundedRadius", { format = "{1:output:SurroundedRadiusMetres}m", { breakdown = "SurroundedRadius" }, { modName = "SurroundedArea", cfg = "skill"} }, }, { label = "Chance to Blind", { format = "{0:mod:1}%", { modName = "BlindChance", modType = "BASE", cfg = "skill" }, }, }, { label = "Chance to Daze", { format = "{0:mod:1}%", { modName = "DazeChance", modType = "BASE", cfg = "skill" }, }, }, { label = "Chance to Rearm", haveOutput = "HazardRearmChance", { format = "{2:mod:1}%", { modName = "HazardRearmChance", modType = "BASE", cfg = "skill"}, }, }, diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 471400dfb..cfa14519c 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -91,6 +91,8 @@ function calcs.initModDB(env, modDB) modDB:NewMod("PhysicalDamageReduction", "BASE", -15, "Base", { type = "Condition", var = "Crushed" }) modDB:NewMod("CritChanceCap", "BASE", 100, "Base") modDB:NewMod("PresenceRadius", "BASE", data.characterConstants["base_presence_radius"], "Base") + modDB:NewMod("SurroundedRadius", "BASE", data.misc.SurroundedRadiusBase, "Base") + modDB:NewMod("SurroundedMinimum", "BASE", data.gameConstants["BaseRequiredEnemiesToBeConsideredSurrounded"], "Base") modDB.conditions["Buffed"] = env.mode_buffs modDB.conditions["Combat"] = env.mode_combat modDB.conditions["Effective"] = env.mode_effective diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index b25419bf0..bebcf0a80 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -208,6 +208,7 @@ data.misc = { -- magic numbers TrapTriggerRadiusBase = 10, MineDetonationRadiusBase = 60, MineAuraRadiusBase = 35, + SurroundedRadiusBase = 30, MinionRevivalTimeBase = data.characterConstants["global_resummon_time_ms"] / 1000, BrandAttachmentRangeBase = 30, ProjectileDistanceCap = 150, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index c67e68674..d5644cd42 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -617,6 +617,7 @@ local modNameList = { ["firestorm explosion area of effect"] = { "AreaOfEffectSecondary", tag = { type = "SkillName", skillName = "Firestorm", includeTransfigured = true } }, ["presence area of effect"] = "PresenceArea", ["presence radius"] = "PresenceRadius", + ["surrounded area of effect"] = "SurroundedArea", ["duration"] = "Duration", ["skill effect duration"] = "Duration", ["fuse duration"] = "Duration", @@ -4178,6 +4179,7 @@ local specialModList = { ["elemental ailments are inflicted on you instead of linked targets"] = { mod("ExtraLinkEffect", "LIST", { mod = flag("ElementalAilmentImmune") }) }, ["non%-unique utility flasks you use apply to linked targets"] = { mod("ExtraLinkEffect", "LIST", { mod = mod("ParentNonUniqueFlasksAppliedToYou", "FLAG", true, { type = "GlobalEffect", effectType = "Global", unscalable = true } ), }) }, ["gain unholy might on block for (%d) seconds"] = { flag("Condition:UnholyMight", { type = "Condition", var = "BlockedRecently"}) }, + ["require (%d+) fewer enemies to be surrounded"] = function(num) return { mod("SurroundedMinimum", "BASE", -num) } end, -- Traps, Mines ["traps and mines deal (%d+)%-(%d+) additional physical damage"] = function(_, min, max) return { mod("PhysicalMin", "BASE", tonumber(min), nil, 0, bor(KeywordFlag.Trap, KeywordFlag.Mine)), mod("PhysicalMax", "BASE", tonumber(max), nil, 0, bor(KeywordFlag.Trap, KeywordFlag.Mine)) } end, ["traps and mines deal (%d+) to (%d+) additional physical damage"] = function(_, min, max) return { mod("PhysicalMin", "BASE", tonumber(min), nil, 0, bor(KeywordFlag.Trap, KeywordFlag.Mine)), mod("PhysicalMax", "BASE", tonumber(max), nil, 0, bor(KeywordFlag.Trap, KeywordFlag.Mine)) } end,