Skip to content

Commit b2b3749

Browse files
PaliakWires77
andauthored
Fix globalLimit being sensitive to tag order (#8652)
* FEAT(items): Add showcased uniques to New.lua * FEAT(mods): add handling for new mods on Scornflux * FEAT(mods): add handling for "Take X Fire Damage when you use a Skill" * FEAT(mods): add handling for Damage penetrates "Fire Resistance equal to your overcapped Fire Resistance" * FEAT(mods): add handling for "Warcries have an additional Life Cost equal to 15% of your Maximum Life" * FEAT(mods): add handling for "Warcry Skills have X increased Area of Effect" * FEAT(mods): add handling for `Gain no armour from equipped body armour` * FEAT(mods): port generalized "doubled" mod handling from POB2 PathOfBuildingCommunity/PathOfBuilding-PoE2#1095 * Update spelling and ModCache * FIX(mods): globalLimit style mods did not work sometimes When a mod gots pice wise parsed the tags can be added to the mod table in unpredictable order. The inital implementation was simply checking the first tag which caused the global limit functionality to not work sometimes. This commit moves the logic into EvalMod. * FEAT(mods): add support for "you have no Str/Dex" mods * FIX(spelling): un-rake-able --------- Co-authored-by: Wires77 <Wires77@users.noreply.github.com>
1 parent 9e1acfd commit b2b3749

4 files changed

Lines changed: 115 additions & 26 deletions

File tree

spec/System/TestDefence_spec.lua

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,102 @@ describe("TestDefence", function()
844844
assert.are.equals(0, floor(poolsRemaining.Life))
845845
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
846846
end)
847+
848+
it("Unbreakable + Iron Reflexes", function()
849+
build.configTab.input.customMods = [[
850+
you have no dexterity
851+
]]
852+
build.configTab:BuildModList()
853+
runCallback("OnFrame")
854+
855+
-- Get the base to make this test more adaptable to changes
856+
local baseArmour = build.calcsTab.mainOutput.Armour
857+
local baseEvasion = build.calcsTab.mainOutput.Evasion
858+
859+
build.configTab.input.customMods = [[
860+
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
861+
you have no dexterity
862+
]]
863+
build.itemsTab:CreateDisplayItemFromRaw([[
864+
New Item
865+
Shabby Jerkin
866+
Quality: 20
867+
]])
868+
build.itemsTab:AddDisplayItem()
869+
build.configTab:BuildModList()
870+
runCallback("OnFrame")
847871

872+
-- Get the base + Shabby Jerkin to make this test more adaptable to changes
873+
local ironReflexesArmour = build.calcsTab.mainOutput.Armour - baseArmour - baseEvasion
874+
875+
print("build.calcsTab.mainOutput.Armour:" .. build.calcsTab.mainOutput.Armour)
876+
877+
build.configTab.input.customMods = [[
878+
Armour from Equipped Body Armour is doubled
879+
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
880+
you have no dexterity
881+
]]
882+
build.configTab:BuildModList()
883+
runCallback("OnFrame")
884+
885+
-- Evasion from Body Armour is converted to Armour before being doubled
886+
assert.are.equals(2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
887+
888+
build.configTab.input.customMods = [[
889+
Armour from Equipped Body Armour is doubled
890+
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
891+
Gain no armour from equipped body armour
892+
you have no dexterity
893+
]]
894+
build.configTab:BuildModList()
895+
runCallback("OnFrame")
896+
897+
-- Only the base armour from the chest is affected.
898+
-- Armour converted with Iron Reflexes still applies
899+
assert.are.equals(2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
900+
build.configTab.input.customMods = [[
901+
Armour from Equipped Body Armour is doubled
902+
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
903+
Gain no armour from equipped body armour
904+
defences from equipped body armour are doubled if it has no socketed gems
905+
you have no dexterity
906+
]]
907+
build.configTab:BuildModList()
908+
runCallback("OnFrame")
909+
910+
-- Oath Of Maji double defences stack with Unbreakable
911+
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
912+
913+
build.configTab.input.customMods = [[
914+
Armour from Equipped Body Armour is doubled
915+
Armour from Equipped Body Armour is doubled
916+
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
917+
Gain no armour from equipped body armour
918+
defences from equipped body armour are doubled if it has no socketed gems
919+
you have no dexterity
920+
]]
921+
build.configTab:BuildModList()
922+
runCallback("OnFrame")
923+
924+
-- Mod form unbreakable should apply only once
925+
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
926+
927+
build.configTab.input.customMods = [[
928+
Armour from Equipped Body Armour is doubled
929+
Armour from Equipped Body Armour is doubled
930+
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
931+
Gain no armour from equipped body armour
932+
defences from equipped body armour are doubled if it has no socketed gems
933+
defences from equipped body armour are doubled if it has no socketed gems
934+
you have no dexterity
935+
]]
936+
build.configTab:BuildModList()
937+
runCallback("OnFrame")
938+
939+
-- Oath Of Maji should apply only once
940+
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
941+
end)
942+
848943
it("MoM + EB", function()
849944
build.configTab.input.enemyIsBoss = "None"
850945
-- enough mana and es, 0% and 100% bypass

src/Classes/ModDB.lua

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,7 @@ function ModDBClass:SumInternal(context, modType, cfg, flags, keywordFlags, sour
9898
local mod = modList[i]
9999
if mod.type == modType and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or ( mod.source and mod.source:match("[^:]+") == source )) then
100100
if mod[1] then
101-
local value = context:EvalMod(mod, cfg) or 0
102-
if mod[1].globalLimit and mod[1].globalLimitKey then
103-
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] or 0
104-
if globalLimits[mod[1].globalLimitKey] + value > mod[1].globalLimit then
105-
value = mod[1].globalLimit - globalLimits[mod[1].globalLimitKey]
106-
end
107-
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] + value
108-
end
101+
local value = context:EvalMod(mod, cfg, globalLimits) or 0
109102
result = result + value
110103
else
111104
result = result + mod.value
@@ -133,14 +126,7 @@ function ModDBClass:MoreInternal(context, cfg, flags, keywordFlags, source, ...)
133126
if mod.type == "MORE" and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or mod.source:match("[^:]+") == source) then
134127
local value
135128
if mod[1] then
136-
value = context:EvalMod(mod, cfg) or 0
137-
if mod[1].globalLimit and mod[1].globalLimitKey then
138-
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] or 0
139-
if globalLimits[mod[1].globalLimitKey] + value > mod[1].globalLimit then
140-
value = mod[1].globalLimit - globalLimits[mod[1].globalLimitKey]
141-
end
142-
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] + value
143-
end
129+
value = context:EvalMod(mod, cfg, globalLimits) or 0
144130
else
145131
value = mod.value or 0
146132
end
@@ -249,15 +235,7 @@ function ModDBClass:TabulateInternal(context, result, modType, cfg, flags, keywo
249235
if (mod.type == modType or not modType) and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or mod.source:match("[^:]+") == source) then
250236
local value
251237
if mod[1] then
252-
value = context:EvalMod(mod, cfg)
253-
if mod[1].globalLimit and mod[1].globalLimitKey then
254-
value = value or 0
255-
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] or 0
256-
if globalLimits[mod[1].globalLimitKey] + value > mod[1].globalLimit then
257-
value = mod[1].globalLimit - globalLimits[mod[1].globalLimitKey]
258-
end
259-
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] + value
260-
end
238+
value = context:EvalMod(mod, cfg, globalLimits)
261239
else
262240
value = mod.value
263241
end

src/Classes/ModStore.lua

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,22 @@ function ModStoreClass:GetStat(stat, cfg)
260260
end
261261
end
262262

263-
function ModStoreClass:EvalMod(mod, cfg)
263+
function ModStoreClass:EvalMod(mod, cfg, globalLimits)
264264
local value = mod.value
265265
for _, tag in ipairs(mod) do
266266
if tag.type == "Multiplier" then
267267
local target = self
268268
local limitTarget = self
269+
270+
if globalLimits and tag.globalLimit and tag.globalLimitKey then
271+
value = value or 0
272+
globalLimits[tag.globalLimitKey] = globalLimits[tag.globalLimitKey] or 0
273+
if globalLimits[tag.globalLimitKey] + value > tag.globalLimit then
274+
value = tag.globalLimit - globalLimits[tag.globalLimitKey]
275+
end
276+
globalLimits[tag.globalLimitKey] = globalLimits[tag.globalLimitKey] + value
277+
end
278+
269279
-- Allow limiting a self multiplier on a parent multiplier (eg. Agony Crawler on player virulence)
270280
-- This explicit target is necessary because even though the GetMultiplier method does call self.parent.GetMultiplier, it does so with noMod = true,
271281
-- disabling the summation (3rd part): (not noMod and self:Sum("BASE", cfg, multiplierName[var]) or 0)

src/Modules/ModParser.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4254,6 +4254,12 @@ local specialModList = {
42544254
["you have no intelligence"] = {
42554255
mod("Int", "MORE", -100),
42564256
},
4257+
["you have no dexterity"] = {
4258+
mod("Dex", "MORE", -100),
4259+
},
4260+
["you have no strength"] = {
4261+
mod("Str", "MORE", -100),
4262+
},
42574263
["elemental resistances are zero"] = {
42584264
mod("FireResist", "OVERRIDE", 0),
42594265
mod("ColdResist", "OVERRIDE", 0),

0 commit comments

Comments
 (0)