From 9d1d155f16658dd3249c5740683c393015dbf541 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 12 May 2026 15:41:54 -0500 Subject: [PATCH 1/4] add support for temporary minions +limit mod add support for rage effect also granting you minion mods --- spec/System/TestSkills_spec.lua | 23 +++++++++++++++++++++++ src/Data/ModCache.lua | 7 +++---- src/Data/Skills/act_int.lua | 7 ++++++- src/Export/Skills/act_int.txt | 4 +++- src/Modules/CalcOffence.lua | 2 +- src/Modules/CalcSections.lua | 5 ++++- src/Modules/ModParser.lua | 2 ++ 7 files changed, 42 insertions(+), 8 deletions(-) diff --git a/spec/System/TestSkills_spec.lua b/spec/System/TestSkills_spec.lua index f0c02d4f3c..3784b0a804 100644 --- a/spec/System/TestSkills_spec.lua +++ b/spec/System/TestSkills_spec.lua @@ -84,4 +84,27 @@ describe("TestSkills", function() local finalCost = build.calcsTab.mainOutput.ManaCost assert.are.equals(16, round(finalCost)) end) + + it("Test 'every rage also grants you' for minion mods", function() + build.itemsTab:CreateDisplayItemFromRaw([[ + New Item + Fanatic Greathammer + Quality: 0 + ]]) + build.itemsTab:AddDisplayItem() + runCallback("OnFrame") + + build.skillsTab:PasteSocketGroup("Unearth 20/0 1") + build.skillsTab:PasteSocketGroup("Leap Slam 20/0 1\nRage I 1/0 1") + runCallback("OnFrame") + + local baseUnearthAttackSpeed = build.calcsTab.mainOutput.Minion.Speed + + build.configTab.input.customMods = "Every Rage also grants you 1% increased Minion Attack Speed" + build.configTab.input.multiplierRage = 30 + build.configTab:BuildModList() + runCallback("OnFrame") + + assert.True(baseUnearthAttackSpeed < build.calcsTab.mainOutput.Minion.Speed) + end) end) \ No newline at end of file diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index bab988d5c9..12b2298c6a 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -4877,9 +4877,8 @@ c["Every Rage also grants 1% increased Fire Damage"]={{[1]={[1]={type="Multiplie c["Every Rage also grants 1% increased Stun Threshold"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="StunThreshold",type="INC",value=1}},nil} c["Every Rage also grants 2% increased Spell Damage"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=2,keywordFlags=0,name="Damage",type="INC",value=2}},nil} c["Every Rage also grants 2% increased Stun Threshold"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="StunThreshold",type="INC",value=2}},nil} -c["Every Rage also grants you 1% increased Minion Attack Speed"]={nil,"you 1% increased Minion Attack Speed "} -c["Every Rage also grants you 1% increased Minion Attack Speed Every Rage also grants you 1% increased Minion Damage"]={nil,"you 1% increased Minion Attack Speed Every Rage also grants you 1% increased Minion Damage "} -c["Every Rage also grants you 1% increased Minion Damage"]={nil,"you 1% increased Minion Damage "} +c["Every Rage also grants you 1% increased Minion Attack Speed"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=1,keywordFlags=0,name="Speed",type="INC",value=1}}}},nil} +c["Every Rage also grants you 1% increased Minion Damage"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}}},nil} c["Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area"]={nil,"Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area "} c["Every second Slam Skill you use yourself is Ancestrally Boosted"]={nil,"Every second Slam Skill you use yourself is Ancestrally Boosted "} c["Every second, inflicts Critical Weakness on enemies in your Presence for 1 second"]={{[1]={flags=0,keywordFlags=0,name="ApplyCriticalWeakness",type="FLAG",value=true}},nil} @@ -6032,7 +6031,7 @@ c["Targets Cursed by you have at least 15% of Life Reserved"]={{[1]={flags=0,key c["Targets can be affected by +1 of your Poisons at the same time"]={{[1]={flags=0,keywordFlags=0,name="PoisonCanStack",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="PoisonStacks",type="BASE",value=1}},nil} c["Targets can be affected by two of your Chills at the same time"]={{[1]={flags=0,keywordFlags=0,name="ChillCanStack",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="ChillStacksMax",type="OVERRIDE",value=2}},nil} c["Targets can be affected by two of your Shocks at the same time"]={{[1]={flags=0,keywordFlags=0,name="ShockCanStack",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="ShockStacksMax",type="OVERRIDE",value=2}},nil} -c["Temporary Minion Skills have +2 to Limit of Minions summoned"]={nil,"Temporary Minion Skills have +2 to Limit of Minions summoned "} +c["Temporary Minion Skills have +2 to Limit of Minions summoned"]={{[1]={[1]={type="Condition",var="TemporaryMinion"},flags=0,keywordFlags=0,name="ActiveMinionLimit",type="BASE",value=2}},nil} c["The Effect of Chill on you is reversed"]={{[1]={flags=0,keywordFlags=0,name="SelfChillEffectIsReversed",type="FLAG",value=true}},nil} c["There is no Limit on the number of Banners you can place"]={nil,"There is no Limit on the number of Banners you can place "} c["This Weapon's Critical Hit Chance is 100%"]={{[1]={flags=0,keywordFlags=0,name="WeaponData",type="LIST",value={key="CritChance",value=100}}},nil} diff --git a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua index 7cf580ce22..910c4db2a0 100644 --- a/src/Data/Skills/act_int.lua +++ b/src/Data/Skills/act_int.lua @@ -16291,7 +16291,9 @@ skills["RaiseZombiePlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + }, + baseMods = { + flag("Condition:TemporaryMinion"), }, constantStats = { { "display_minion_monster_type", 1 }, @@ -21217,6 +21219,9 @@ skills["UnearthPlayer"] = { area = true, minion = true, }, + baseMods = { + flag("Condition:TemporaryMinion"), + }, constantStats = { { "unearth_base_cone_speed_multiplier", 50 }, { "active_skill_base_area_of_effect_radius", 60 }, diff --git a/src/Export/Skills/act_int.txt b/src/Export/Skills/act_int.txt index e2bc3a5aff..7bf3c0d9bd 100644 --- a/src/Export/Skills/act_int.txt +++ b/src/Export/Skills/act_int.txt @@ -1102,7 +1102,8 @@ statMap = { #minionList RaisedZombie #skill RaiseZombiePlayer #set RaiseZombiePlayer -#flags spell minion permanentMinion +#flags spell minion +#baseMod flag("Condition:TemporaryMinion") #mods #skillEnd @@ -1400,6 +1401,7 @@ statMap = { #skill UnearthPlayer #set UnearthPlayer #flags spell area minion +#baseMod flag("Condition:TemporaryMinion") #mods #skillEnd diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 3e87cc8ace..77ffffbdfb 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -1192,7 +1192,7 @@ function calcs.offence(env, actor, activeSkill) -- Calculate skill type stats if skillFlags.minion then if activeSkill.minion and activeSkill.minion.minionData.limit then - output.ActiveMinionLimit = m_floor(env.modDB:Override(nil, activeSkill.minion.minionData.limit) or calcLib.val(skillModList, activeSkill.minion.minionData.limit, skillCfg)) + output.ActiveMinionLimit = m_floor(env.modDB:Override(nil, activeSkill.minion.minionData.limit) or (calcLib.val(skillModList, activeSkill.minion.minionData.limit, skillCfg) + calcLib.val(skillModList, "ActiveMinionLimit", skillCfg))) end output.SummonedMinionsPerCast = m_floor(calcLib.val(skillModList, "MinionPerCastCount", skillCfg)) if output.SummonedMinionsPerCast == 0 then diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index ab1596c29d..9332d9f144 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -641,7 +641,10 @@ return { { label = "Rage per second", color = colorCodes.RAGE, haveOutput = "RagePerSecondHasCost", { format = "{2:output:RagePerSecondCost}", { breakdown = "RagePerSecondCost" }, { modName = { "RageCost", "Cost", "RageNoMult" }, cfg = "skill" }, }, }, { label = "Armour Break / hit", haveOutput = "ArmourBreakPerHit", { format = "{0:output:ArmourBreakPerHit}", { modName = "ArmourBreakPerHit", modType = "BASE"} }, }, { label = "Soul Cost", color = colorCodes.RAGE, haveOutput = "SoulHasCost", { format = "{0:output:SoulCost}", { breakdown = "SoulCost" }, { modName = { "SoulCost" }, cfg = "skill" }, }, }, - { label = "Active Minion Limit", haveOutput = "ActiveMinionLimit", { format = "{0:output:ActiveMinionLimit}" } }, + { label = "Active Minion Limit", haveOutput = "ActiveMinionLimit", { format = "{0:output:ActiveMinionLimit}", + { breakdown = "ActiveMinionLimit" }, + { modName = { "ActiveMinionLimit" }, cfg = "skill" }, + }, }, { label = "Minion Revival Time", haveOutput = "MinionRevivalSpeed", { format = "{2:output:MinionRevivalSpeed}s", { breakdown = "MinionRevivalSpeed" }, { modName = { "MinionRevivalSpeed" } } },}, { label = "Quantity Multiplier", haveOutput = "QuantityMultiplier", { format = "{0:output:QuantityMultiplier}", { breakdown = "QuantityMultiplier" }, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index a13144ac8b..0c1398efdf 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -1378,6 +1378,7 @@ local preFlagList = { ["allies in your presence [hgd][ae][via][enl] "] = { newAura = true, newAuraOnlyAllies = true }, ["^you and allies in your presence [hgd][ae][via][enl] "] = { newAura = true }, ["^every rage also grants "] = { tag = { type = "Multiplier", var = "RageEffect" } }, + ["^every rage also grants you "] = { tag = { type = "Multiplier", var = "RageEffect", actor = "parent" } }, ["^each rage also grants "] = { tag = { type = "Multiplier", var = "RageEffect" } }, ["^every (%d+) rage also grants "] = function(num) return { tag = { type = "Multiplier", var = "RageEffect", div = tonumber(num) } } end, ["^you and allies affected by auras from your skills [hgd][ae][via][enl] "] = { tag = { type = "Condition", var = "AffectedByAura" } }, @@ -4655,6 +4656,7 @@ local specialModList = { ["skeleton warriors are permanent minions and follow you"] = { flag("RaisedSkeletonPermanentDuration", { type = "SkillName", skillName = "Summon Skeletons" }) }, -- typo never existed except in some items generated by PoB ["summoned skeleton warriors are permanent and follow you"] = { flag("RaisedSkeletonPermanentDuration", { type = "SkillName", skillName = "Summon Skeletons" }) }, ["minions recoup (%d+)%% of damage taken as life"] = function(num) return { mod("MinionModifier", "LIST", { mod = mod("LifeRecoup", "BASE", num) }) } end, + ["temporary minion skills have %+(%d+) to limit of minions summoned"] = function(num) return { mod("ActiveMinionLimit", "BASE", num, { type = "Condition", var = "TemporaryMinion"}) } end, -- Projectiles ["skills chain %+(%d) times"] = function(num) return { mod("ChainCountMax", "BASE", num) } end, ["arrows chain %+(%d) times"] = function(num) return { mod("ChainCountMax", "BASE", num, nil, 0, KeywordFlag.Arrow) } end, From e292b1a4d85f9f355e2cfcc3d0012f2296a9603a Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 12 May 2026 17:03:45 -0500 Subject: [PATCH 2/4] convert permanentMinion to duration remove duration from ManifestWeapon add BaseFlag as a modType to avoid some hacky solution in CalcOffence and allow cleaner CalcSectionBreakdown --- src/Classes/CalcBreakdownControl.lua | 2 ++ src/Classes/ModStore.lua | 13 +++++++++++++ src/Data/ModCache.lua | 2 +- src/Data/Skills/act_dex.lua | 1 - src/Data/Skills/act_int.lua | 24 ++++++++---------------- src/Data/Skills/other.lua | 5 ++--- src/Export/Skills/act_dex.txt | 2 +- src/Export/Skills/act_int.txt | 22 ++++++++++------------ src/Export/Skills/other.txt | 6 +++--- src/Modules/CalcPerform.lua | 2 +- src/Modules/ModParser.lua | 2 +- 11 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/Classes/CalcBreakdownControl.lua b/src/Classes/CalcBreakdownControl.lua index bd4609930c..fb92742ff6 100644 --- a/src/Classes/CalcBreakdownControl.lua +++ b/src/Classes/CalcBreakdownControl.lua @@ -481,6 +481,8 @@ function CalcBreakdownClass:AddModSection(sectionData, modList) else desc = "Skill type: "..(tag.neg and "Not " or "")..self:FormatModName(SkillTypeName[tag.skillType]) end + elseif tag.type == "BaseFlag" then + desc = "Base flag: "..(tag.neg and "Not " or "")..self:FormatModName(tostring(tag.baseFlag)) elseif tag.type == "SlotNumber" then desc = "When in slot #"..tag.num elseif tag.type == "GlobalEffect" then diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index 6470f1b219..7b410fcc6c 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -782,6 +782,19 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) if not match then return end + elseif tag.type == "BaseFlag" then + local match = false + if cfg and cfg.skillGem and cfg.skillGem.grantedEffect and cfg.skillGem.grantedEffect.statSets and cfg.skillGem.grantedEffect.statSets[1] then + match = cfg.skillGem.grantedEffect.statSets[1].baseFlags[tag.baseFlag] + else + match = cfg and cfg.baseFlags and cfg.baseFlags[tag.baseFlag] + end + if tag.neg then + match = not match + end + if not match then + return + end elseif tag.type == "SlotName" then if not cfg then return diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 12b2298c6a..1bd2d48b70 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -6031,7 +6031,7 @@ c["Targets Cursed by you have at least 15% of Life Reserved"]={{[1]={flags=0,key c["Targets can be affected by +1 of your Poisons at the same time"]={{[1]={flags=0,keywordFlags=0,name="PoisonCanStack",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="PoisonStacks",type="BASE",value=1}},nil} c["Targets can be affected by two of your Chills at the same time"]={{[1]={flags=0,keywordFlags=0,name="ChillCanStack",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="ChillStacksMax",type="OVERRIDE",value=2}},nil} c["Targets can be affected by two of your Shocks at the same time"]={{[1]={flags=0,keywordFlags=0,name="ShockCanStack",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="ShockStacksMax",type="OVERRIDE",value=2}},nil} -c["Temporary Minion Skills have +2 to Limit of Minions summoned"]={{[1]={[1]={type="Condition",var="TemporaryMinion"},flags=0,keywordFlags=0,name="ActiveMinionLimit",type="BASE",value=2}},nil} +c["Temporary Minion Skills have +2 to Limit of Minions summoned"]={{[1]={[1]={baseFlag="duration",neg=true,type="BaseFlag"},flags=0,keywordFlags=0,name="ActiveMinionLimit",type="BASE",value=2}},nil} c["The Effect of Chill on you is reversed"]={{[1]={flags=0,keywordFlags=0,name="SelfChillEffectIsReversed",type="FLAG",value=true}},nil} c["There is no Limit on the number of Banners you can place"]={nil,"There is no Limit on the number of Banners you can place "} c["This Weapon's Critical Hit Chance is 100%"]={{[1]={flags=0,keywordFlags=0,name="WeaponData",type="LIST",value={key="CritChance",value=100}}},nil} diff --git a/src/Data/Skills/act_dex.lua b/src/Data/Skills/act_dex.lua index 6ce0eb1764..d64c38146f 100644 --- a/src/Data/Skills/act_dex.lua +++ b/src/Data/Skills/act_dex.lua @@ -897,7 +897,6 @@ skills["SummonBeastPlayer"] = { minion = true, summonBeast = true, duration = true, - permanentMinion = true, }, baseMods = { mod("MinionModifier", "LIST", { mod = mod("Damage", "MORE", 25) }), --Server side damage mod added in 0.3, diff --git a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua index 910c4db2a0..8d6761abe6 100644 --- a/src/Data/Skills/act_int.lua +++ b/src/Data/Skills/act_int.lua @@ -16168,7 +16168,6 @@ skills["RagingSpiritsPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, }, constantStats = { { "base_number_of_raging_spirits_allowed", 10 }, @@ -16292,9 +16291,6 @@ skills["RaiseZombiePlayer"] = { spell = true, minion = true, }, - baseMods = { - flag("Condition:TemporaryMinion"), - }, constantStats = { { "display_minion_monster_type", 1 }, { "zombie_decay_rate_increase_+%_final", 25 }, @@ -17692,7 +17688,7 @@ skills["SummonSkeletalArsonistsPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -17812,7 +17808,7 @@ skills["SummonSkeletalBrutesPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -17932,7 +17928,7 @@ skills["SummonSkeletalClericsPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -18052,7 +18048,7 @@ skills["SummonSkeletalFrostMagesPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -18173,7 +18169,7 @@ skills["SummonSkeletalReaversPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -18294,7 +18290,7 @@ skills["SummonSkeletalSnipersPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -18414,7 +18410,7 @@ skills["SummonSkeletalStormMagesPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -18536,7 +18532,7 @@ skills["SummonSkeletalWarriorsPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 2 }, @@ -19715,7 +19711,6 @@ skills["SummonSpectrePlayer"] = { minion = true, spectre = true, duration = true, - permanentMinion = true, }, baseMods = { mod("MinionModifier", "LIST", { mod = mod("Damage", "MORE", 25) }), --Server side damage mod added in 0.3, @@ -21219,9 +21214,6 @@ skills["UnearthPlayer"] = { area = true, minion = true, }, - baseMods = { - flag("Condition:TemporaryMinion"), - }, constantStats = { { "unearth_base_cone_speed_multiplier", 50 }, { "active_skill_base_area_of_effect_radius", 60 }, diff --git a/src/Data/Skills/other.lua b/src/Data/Skills/other.lua index 138b5395e8..0dd967f165 100644 --- a/src/Data/Skills/other.lua +++ b/src/Data/Skills/other.lua @@ -5307,7 +5307,6 @@ skills["ManifestWeaponPlayer"] = { baseFlags = { spell = true, minion = true, - duration = true, }, constantStats = { { "minion_1%_damage_+%_per_X_player_strength", 1 }, @@ -8022,7 +8021,7 @@ skills["SummonInfernalHoundPlayer"] = { baseFlags = { spell = true, minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "display_minion_monster_type", 8 }, @@ -8151,7 +8150,7 @@ skills["SupportingFirePlayer"] = { }, baseFlags = { minion = true, - permanentMinion = true, + duration = true, }, constantStats = { { "minion_1%_damage_+%_per_X_player_strength", 1 }, diff --git a/src/Export/Skills/act_dex.txt b/src/Export/Skills/act_dex.txt index 11dbefdcdd..f8b064b685 100644 --- a/src/Export/Skills/act_dex.txt +++ b/src/Export/Skills/act_dex.txt @@ -90,7 +90,7 @@ statMap = { #minionList #skill SummonBeastPlayer #set SummonBeastPlayer -#flags spell minion summonBeast duration permanentMinion +#flags spell minion summonBeast duration #baseMod mod("MinionModifier", "LIST", { mod = mod("Damage", "MORE", 25) }), --Server side damage mod added in 0.3 #mods #skillEnd diff --git a/src/Export/Skills/act_int.txt b/src/Export/Skills/act_int.txt index 7bf3c0d9bd..5180ba802b 100644 --- a/src/Export/Skills/act_int.txt +++ b/src/Export/Skills/act_int.txt @@ -1095,7 +1095,7 @@ statMap = { #minionList SummonedRagingSpirit #skill RagingSpiritsPlayer #set RagingSpiritsPlayer -#flags spell minion permanentMinion +#flags spell minion #mods #skillEnd @@ -1103,7 +1103,6 @@ statMap = { #skill RaiseZombiePlayer #set RaiseZombiePlayer #flags spell minion -#baseMod flag("Condition:TemporaryMinion") #mods #skillEnd @@ -1189,49 +1188,49 @@ statMap = { #minionList RaisedSkeletonArsonist #skill SummonSkeletalArsonistsPlayer #set SummonSkeletalArsonistsPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd #minionList RaisedSkeletonBrute #skill SummonSkeletalBrutesPlayer #set SummonSkeletalBrutesPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd #minionList RaisedSkeletonCleric #skill SummonSkeletalClericsPlayer #set SummonSkeletalClericsPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd #minionList RaisedSkeletonFrostMage #skill SummonSkeletalFrostMagesPlayer #set SummonSkeletalFrostMagesPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd #minionList RaisedSkeletonReaver #skill SummonSkeletalReaversPlayer #set SummonSkeletalReaversPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd #minionList RaisedSkeletonSniper #skill SummonSkeletalSnipersPlayer #set SummonSkeletalSnipersPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd #minionList RaisedSkeletonStormMage #skill SummonSkeletalStormMagesPlayer #set SummonSkeletalStormMagesPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd @@ -1239,7 +1238,7 @@ statMap = { #minionList RaisedSkeletonWarriors #skill SummonSkeletalWarriorsPlayer #set SummonSkeletalWarriorsPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd @@ -1309,7 +1308,7 @@ statMap = { #minionList #skill SummonSpectrePlayer #set SummonSpectrePlayer -#flags spell minion spectre duration permanentMinion +#flags spell minion spectre duration #baseMod mod("MinionModifier", "LIST", { mod = mod("Damage", "MORE", 25) }), --Server side damage mod added in 0.3 #mods #skillEnd @@ -1401,7 +1400,6 @@ statMap = { #skill UnearthPlayer #set UnearthPlayer #flags spell area minion -#baseMod flag("Condition:TemporaryMinion") #mods #skillEnd diff --git a/src/Export/Skills/other.txt b/src/Export/Skills/other.txt index b03319e2bd..6f9720cb5a 100644 --- a/src/Export/Skills/other.txt +++ b/src/Export/Skills/other.txt @@ -368,7 +368,7 @@ minionUses = { ["Weapon 1"] = true, }, #set ManifestWeaponPlayer -#flags spell minion duration +#flags spell minion statMap = { ["minion_1%_damage_+%_per_X_player_strength"] = { mod("MinionModifier", "LIST", { mod = mod("Damage", "INC", nil, 0, 0, { type = "PerStat", stat = "Str", actor = "parent" }) }), @@ -556,7 +556,7 @@ statMap = { #minionList SummonedHellhound #skill SummonInfernalHoundPlayer #set SummonInfernalHoundPlayer -#flags spell minion permanentMinion +#flags spell minion duration #mods #skillEnd @@ -564,7 +564,7 @@ statMap = { #minionList TacticianMinion #skill SupportingFirePlayer #set SupportingFirePlayer -#flags minion permanentMinion +#flags minion duration statMap = { ["minion_1%_damage_+%_per_X_player_strength"] = { mod("MinionModifier", "LIST", { mod = mod("Damage", "INC", nil, 0, 0, { type = "PerStat", stat = "Str", actor = "parent" }) }), diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index cd5a2bc12d..2339e11be5 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -255,7 +255,7 @@ local function doActorAttribsConditions(env, actor) if actor.mainSkill.skillTypes[SkillType.Movement] then condList["UsedMovementSkillRecently"] = true end - if skillFlags.minion and not skillFlags.permanentMinion then + if skillFlags.minion and not skillFlags.duration then condList["UsedMinionSkillRecently"] = true end if actor.mainSkill.skillTypes[SkillType.Vaal] then diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 0c1398efdf..d6bab22939 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -4656,7 +4656,7 @@ local specialModList = { ["skeleton warriors are permanent minions and follow you"] = { flag("RaisedSkeletonPermanentDuration", { type = "SkillName", skillName = "Summon Skeletons" }) }, -- typo never existed except in some items generated by PoB ["summoned skeleton warriors are permanent and follow you"] = { flag("RaisedSkeletonPermanentDuration", { type = "SkillName", skillName = "Summon Skeletons" }) }, ["minions recoup (%d+)%% of damage taken as life"] = function(num) return { mod("MinionModifier", "LIST", { mod = mod("LifeRecoup", "BASE", num) }) } end, - ["temporary minion skills have %+(%d+) to limit of minions summoned"] = function(num) return { mod("ActiveMinionLimit", "BASE", num, { type = "Condition", var = "TemporaryMinion"}) } end, + ["temporary minion skills have %+(%d+) to limit of minions summoned"] = function(num) return { mod("ActiveMinionLimit", "BASE", num, { type = "BaseFlag", baseFlag = "duration", neg = true }) } end, -- Projectiles ["skills chain %+(%d) times"] = function(num) return { mod("ChainCountMax", "BASE", num) } end, ["arrows chain %+(%d) times"] = function(num) return { mod("ChainCountMax", "BASE", num, nil, 0, KeywordFlag.Arrow) } end, From 19d2548fb9630e1386fb9da3f21fca605d9b085b Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Wed, 13 May 2026 12:47:17 -0500 Subject: [PATCH 3/4] update to work for Minions and Minion Dmg/Speed applies to you frm chober chaber and trenchtimbre add test to maintain both scenarios --- spec/System/TestSkills_spec.lua | 39 ++++++++++++++++++++++++++++++++- src/Data/ModCache.lua | 4 ++-- src/Modules/ModParser.lua | 9 +++++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/spec/System/TestSkills_spec.lua b/spec/System/TestSkills_spec.lua index 3784b0a804..7b3f2592ad 100644 --- a/spec/System/TestSkills_spec.lua +++ b/spec/System/TestSkills_spec.lua @@ -85,7 +85,7 @@ describe("TestSkills", function() assert.are.equals(16, round(finalCost)) end) - it("Test 'every rage also grants you' for minion mods", function() + it("Test 'every rage also grants you' for minion mods and minion apply to you mods #run", function() build.itemsTab:CreateDisplayItemFromRaw([[ New Item Fanatic Greathammer @@ -106,5 +106,42 @@ describe("TestSkills", function() runCallback("OnFrame") assert.True(baseUnearthAttackSpeed < build.calcsTab.mainOutput.Minion.Speed) + + newBuild() + build.itemsTab:CreateDisplayItemFromRaw([[ + Rarity: UNIQUE + Chober Chaber + Leaden Greathammer + Variant: Pre 0.1.1 + Variant: Current + Selected Variant: 2 + Quality: 20 + LevelReq: 33 + Implicits: 0 + +100 Intelligence Requirement + {variant:1}{range:0.5}(80-120)% increased Physical Damage + {variant:2}{range:0.5}Adds (58-65) to (102-110) Physical Damage + {range:0.5}+(80-100) to maximum Mana + {variant:2}+50 to Spirit + {variant:1}+5% to Critical Hit Chance + Increases and Reductions to Minion Damage also affect you + ]]) + build.itemsTab:AddDisplayItem() + runCallback("OnFrame") + + build.skillsTab:PasteSocketGroup("Leap Slam 20/0 1\nRage I 1/0 1") + runCallback("OnFrame") + + build.configTab.input.multiplierRage = 30 + build.configTab:BuildModList() + runCallback("OnFrame") + + local baseLeapSlamHit = build.calcsTab.mainOutput.AverageDamage + + build.configTab.input.customMods = "Every Rage also grants you 1% increased Minion Damage" + build.configTab:BuildModList() + runCallback("OnFrame") + + assert.True(baseLeapSlamHit < build.calcsTab.mainOutput.AverageDamage) end) end) \ No newline at end of file diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 1bd2d48b70..b9dca9c0f2 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -4877,8 +4877,8 @@ c["Every Rage also grants 1% increased Fire Damage"]={{[1]={[1]={type="Multiplie c["Every Rage also grants 1% increased Stun Threshold"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="StunThreshold",type="INC",value=1}},nil} c["Every Rage also grants 2% increased Spell Damage"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=2,keywordFlags=0,name="Damage",type="INC",value=2}},nil} c["Every Rage also grants 2% increased Stun Threshold"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="StunThreshold",type="INC",value=2}},nil} -c["Every Rage also grants you 1% increased Minion Attack Speed"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=1,keywordFlags=0,name="Speed",type="INC",value=1}}}},nil} -c["Every Rage also grants you 1% increased Minion Damage"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}}},nil} +c["Every Rage also grants you 1% increased Minion Attack Speed"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Speed",type="INC",value=1}}},[2]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Speed",type="INC",value=1}}}},nil} +c["Every Rage also grants you 1% increased Minion Damage"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}},[2]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}}},nil} c["Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area"]={nil,"Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area "} c["Every second Slam Skill you use yourself is Ancestrally Boosted"]={nil,"Every second Slam Skill you use yourself is Ancestrally Boosted "} c["Every second, inflicts Critical Weakness on enemies in your Presence for 1 second"]={{[1]={flags=0,keywordFlags=0,name="ApplyCriticalWeakness",type="FLAG",value=true}},nil} diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index d6bab22939..3d86029b8a 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -1378,7 +1378,6 @@ local preFlagList = { ["allies in your presence [hgd][ae][via][enl] "] = { newAura = true, newAuraOnlyAllies = true }, ["^you and allies in your presence [hgd][ae][via][enl] "] = { newAura = true }, ["^every rage also grants "] = { tag = { type = "Multiplier", var = "RageEffect" } }, - ["^every rage also grants you "] = { tag = { type = "Multiplier", var = "RageEffect", actor = "parent" } }, ["^each rage also grants "] = { tag = { type = "Multiplier", var = "RageEffect" } }, ["^every (%d+) rage also grants "] = function(num) return { tag = { type = "Multiplier", var = "RageEffect", div = tonumber(num) } } end, ["^you and allies affected by auras from your skills [hgd][ae][via][enl] "] = { tag = { type = "Condition", var = "AffectedByAura" } }, @@ -4657,6 +4656,14 @@ local specialModList = { ["summoned skeleton warriors are permanent and follow you"] = { flag("RaisedSkeletonPermanentDuration", { type = "SkillName", skillName = "Summon Skeletons" }) }, ["minions recoup (%d+)%% of damage taken as life"] = function(num) return { mod("MinionModifier", "LIST", { mod = mod("LifeRecoup", "BASE", num) }) } end, ["temporary minion skills have %+(%d+) to limit of minions summoned"] = function(num) return { mod("ActiveMinionLimit", "BASE", num, { type = "BaseFlag", baseFlag = "duration", neg = true }) } end, + ["every rage also grants you (%d+)%% increased minion attack speed"] = function(num) return { + mod("MinionModifier", "LIST", { mod = mod("Speed", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "player" }) }), + mod("MinionModifier", "LIST", { mod = mod("Speed", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "parent" }) }), + } end, + ["every rage also grants you (%d+)%% increased minion damage"] = function(num) return { + mod("MinionModifier", "LIST", { mod = mod("Damage", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "player" }) }), + mod("MinionModifier", "LIST", { mod = mod("Damage", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "parent" }) }), + } end, -- Projectiles ["skills chain %+(%d) times"] = function(num) return { mod("ChainCountMax", "BASE", num) } end, ["arrows chain %+(%d) times"] = function(num) return { mod("ChainCountMax", "BASE", num, nil, 0, KeywordFlag.Arrow) } end, From 19b44264df30cdaddb3325f9f444704ec43ab3e1 Mon Sep 17 00:00:00 2001 From: LocalIdentity Date: Thu, 14 May 2026 06:51:52 +1000 Subject: [PATCH 4/4] Fix handling of player actor --- src/Classes/ModStore.lua | 43 ++++++++++++++++++++++++++------------- src/Data/ModCache.lua | 4 ++-- src/Modules/ModParser.lua | 10 ++++----- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index 7b410fcc6c..7feeb9a1c2 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -34,6 +34,14 @@ local ModStoreClass = newClass("ModStore", function(self, parent) self.conditions = { } end) +local function getActor(self, actorType) + if actorType == "player" then + return self.actor.player or (self.actor.parent and self.actor.parent.player) or (self.actor.enemy and self.actor.enemy.player) + else + return self.actor[actorType] + end +end + function ModStoreClass:ScaleAddMod(mod, scale) local unscalable = false for _, effects in ipairs(mod) do @@ -315,15 +323,17 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) -- This explicit target is necessary because even though the GetMultiplier method does call self.parent.GetMultiplier, it does so with noMod = true, -- disabling the summation (3rd part): (not noMod and self:Sum("BASE", cfg, multiplierName[var]) or 0) if tag.limitActor then - if self.actor[tag.limitActor] then - limitTarget = self.actor[tag.limitActor].modDB + local limitActor = getActor(self, tag.limitActor) + if limitActor then + limitTarget = limitActor.modDB else return end end if tag.actor then - if self.actor[tag.actor] then - target = self.actor[tag.actor].modDB + local actor = getActor(self, tag.actor) + if actor then + target = actor.modDB else return end @@ -387,15 +397,17 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) local target = self local thresholdTarget = self if tag.thresholdActor then - if self.actor[tag.thresholdActor] then - thresholdTarget = self.actor[tag.thresholdActor].modDB + local thresholdActor = getActor(self, tag.thresholdActor) + if thresholdActor then + thresholdTarget = thresholdActor.modDB else return end end if tag.actor then - if self.actor[tag.actor] then - target = self.actor[tag.actor].modDB + local actor = getActor(self, tag.actor) + if actor then + target = actor.modDB else return end @@ -417,8 +429,9 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) local target = self -- This functions similar to the above tagTypes in regard to which actor to use, but for PerStat -- if the actor is 'parent', we don't want to return if we're already using 'parent', just keep using 'self' - if tag.actor and self.actor[tag.actor] then - target = self.actor[tag.actor].modDB + local actor = getActor(self, tag.actor) + if actor then + target = actor.modDB end if tag.statList then base = 0 @@ -465,8 +478,9 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) local target = self -- This functions similar to the above tagTypes in regard to which actor to use, but for PercentStat -- if the actor is 'parent', we don't want to return if we're already using 'parent', just keep using 'self' - if tag.actor and self.actor[tag.actor] then - target = self.actor[tag.actor].modDB + local actor = getActor(self, tag.actor) + if actor then + target = actor.modDB end if tag.statList then base = 0 @@ -581,7 +595,8 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) local match = false local target = self if tag.actor then - target = self.actor[tag.actor] and self.actor[tag.actor].modDB + local actor = getActor(self, tag.actor) + target = actor and actor.modDB end if target and (tag.var or tag.varList) then if tag.varList then @@ -876,4 +891,4 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) end end return value -end \ No newline at end of file +end diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index b9dca9c0f2..49c083c001 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -4877,8 +4877,8 @@ c["Every Rage also grants 1% increased Fire Damage"]={{[1]={[1]={type="Multiplie c["Every Rage also grants 1% increased Stun Threshold"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="StunThreshold",type="INC",value=1}},nil} c["Every Rage also grants 2% increased Spell Damage"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=2,keywordFlags=0,name="Damage",type="INC",value=2}},nil} c["Every Rage also grants 2% increased Stun Threshold"]={{[1]={[1]={type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="StunThreshold",type="INC",value=2}},nil} -c["Every Rage also grants you 1% increased Minion Attack Speed"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Speed",type="INC",value=1}}},[2]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Speed",type="INC",value=1}}}},nil} -c["Every Rage also grants you 1% increased Minion Damage"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}},[2]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="parent",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}}},nil} +c["Every Rage also grants you 1% increased Minion Attack Speed"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=1,keywordFlags=0,name="Speed",type="INC",value=1}}}},nil} +c["Every Rage also grants you 1% increased Minion Damage"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}}},nil} c["Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area"]={nil,"Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area "} c["Every second Slam Skill you use yourself is Ancestrally Boosted"]={nil,"Every second Slam Skill you use yourself is Ancestrally Boosted "} c["Every second, inflicts Critical Weakness on enemies in your Presence for 1 second"]={{[1]={flags=0,keywordFlags=0,name="ApplyCriticalWeakness",type="FLAG",value=true}},nil} diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 3d86029b8a..a333b43fba 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -4656,13 +4656,11 @@ local specialModList = { ["summoned skeleton warriors are permanent and follow you"] = { flag("RaisedSkeletonPermanentDuration", { type = "SkillName", skillName = "Summon Skeletons" }) }, ["minions recoup (%d+)%% of damage taken as life"] = function(num) return { mod("MinionModifier", "LIST", { mod = mod("LifeRecoup", "BASE", num) }) } end, ["temporary minion skills have %+(%d+) to limit of minions summoned"] = function(num) return { mod("ActiveMinionLimit", "BASE", num, { type = "BaseFlag", baseFlag = "duration", neg = true }) } end, - ["every rage also grants you (%d+)%% increased minion attack speed"] = function(num) return { - mod("MinionModifier", "LIST", { mod = mod("Speed", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "player" }) }), - mod("MinionModifier", "LIST", { mod = mod("Speed", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "parent" }) }), - } end, ["every rage also grants you (%d+)%% increased minion damage"] = function(num) return { - mod("MinionModifier", "LIST", { mod = mod("Damage", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "player" }) }), - mod("MinionModifier", "LIST", { mod = mod("Damage", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "parent" }) }), + mod("MinionModifier", "LIST", { mod = mod("Damage", "INC", num, { type = "Multiplier", var = "RageEffect", actor = "player" }) }), + } end, + ["every rage also grants you (%d+)%% increased minion attack speed"] = function(num) return { + mod("MinionModifier", "LIST", { mod = mod("Speed", "INC", num, nil, ModFlag.Attack, { type = "Multiplier", var = "RageEffect", actor = "player" }) }), } end, -- Projectiles ["skills chain %+(%d) times"] = function(num) return { mod("ChainCountMax", "BASE", num) } end,