Skip to content

Commit e3ee963

Browse files
authored
Merge branch 'PathOfBuildingCommunity:dev' into dev
2 parents 36ce5e3 + c1ffcf4 commit e3ee963

56 files changed

Lines changed: 17945 additions & 16740 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# Changelog
22

3+
## [v0.21.1](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/tree/v0.21.1) (2026/06/20)
4+
5+
[Full Changelog](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/compare/v0.21.0...v0.21.1)
6+
7+
8+
## What's Changed
9+
### Fixed Crashes
10+
- Fix crash when trying to use PoB trader after 0.5.3 [\#2238](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2238) ([vaisest](https://github.com/vaisest))
11+
### Fixed Calculations
12+
- Fix more Maximum Rage mod not working [\#2228](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2228) ([Blitz54](https://github.com/Blitz54))
13+
- Fix general Grenade mods not working [\#2196](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2196) ([LocalIdentity](https://github.com/LocalIdentity))
14+
- Fix Blazing Critical not applying as a global buff [\#2221](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2221) ([LocalIdentity](https://github.com/LocalIdentity))
15+
- Fix Sine Aequo Immobilisation buildup calculation [\#2222](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2222) ([LocalIdentity](https://github.com/LocalIdentity))
16+
- Fix Daze not applying 50% more Stun Buildup [\#2223](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2223) ([LocalIdentity](https://github.com/LocalIdentity))
17+
- Fix Overwhelming Presence quality mod multiplying Aura magnitude [\#2224](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2224) ([LocalIdentity](https://github.com/LocalIdentity))
18+
- Fix "+% to Critical Damage Bonus" mods on weapons applying to Spells [\#2247](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2247) ([luther-rotmg](https://github.com/luther-rotmg))
19+
### Fixed Behaviours
20+
- Fix Ice Bite and Innervate only supporting Attacks [\#2207](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2207) ([vaisest](https://github.com/vaisest))
21+
- Fix power report and trade search not working with Minions [\#2219](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2219) ([LocalIdentity](https://github.com/LocalIdentity))
22+
- Fix Bloodhounds Mark not counting the enemy as Marked [\#2220](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/2220) ([LocalIdentity](https://github.com/LocalIdentity))
23+
24+
325
## [v0.21.0](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/tree/v0.21.0) (2026/06/13)
426

527
[Full Changelog](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/compare/v0.20.0...v0.21.0)

changelog.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
VERSION[0.21.1][2026/06/20]
2+
3+
--- Fixed Crashes ---
4+
* Fix crash when trying to use PoB trader after 0.5.3 (vaisest)
5+
6+
--- Fixed Calculations ---
7+
* Fix more Maximum Rage mod not working (Blitz54)
8+
* Fix general Grenade mods not working (LocalIdentity)
9+
* Fix Blazing Critical not applying as a global buff (LocalIdentity)
10+
* Fix Sine Aequo Immobilisation buildup calculation (LocalIdentity)
11+
* Fix Daze not applying 50% more Stun Buildup (LocalIdentity)
12+
* Fix Overwhelming Presence quality mod multiplying Aura magnitude (LocalIdentity)
13+
* Fix "+% to Critical Damage Bonus" mods on weapons applying to Spells (luther-rotmg)
14+
15+
--- Fixed Behaviours ---
16+
* Fix Ice Bite and Innervate only supporting Attacks (vaisest)
17+
* Fix power report and trade search not working with Minions (LocalIdentity)
18+
* Fix Bloodhounds Mark not counting the enemy as Marked (LocalIdentity)
19+
120
VERSION[0.21.0][2026/06/13]
221

322
--- New to Path of Building ---

manifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version='1.0' encoding='UTF-8'?>
22
<PoBVersion>
3-
<Version number="0.21.0" />
3+
<Version number="0.21.1" />
44
<Source part="default" url="https://raw.githubusercontent.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/{branch}/" />
55
<Source part="runtime" platform="win32" url="https://raw.githubusercontent.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/{branch}/runtime/" />
66
<Source part="program" url="https://raw.githubusercontent.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/{branch}/src/" />

spec/System/TestAttacks_spec.lua

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,35 @@ describe("TestAttacks", function()
3030
assert.are.equals(2 + 0.25, build.calcsTab.mainOutput.CritMultiplier)
3131
end)
3232

33+
it("local Critical Damage Bonus on a weapon does not apply to spells (issue #2199)", function()
34+
-- baseline: a spell's crit multi with a plain quarterstaff (no local crit damage)
35+
build.itemsTab:CreateDisplayItemFromRaw([[
36+
New Item
37+
Razor Quarterstaff
38+
]])
39+
build.itemsTab:AddDisplayItem()
40+
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
41+
build.mainSocketGroup = 1
42+
runCallback("OnFrame")
43+
local baseSpellCritMulti = build.calcsTab.mainOutput.CritMultiplier
44+
45+
newBuild()
46+
47+
-- same spell + quarterstaff, now with a local "+X% to Critical Damage Bonus" affix
48+
build.itemsTab:CreateDisplayItemFromRaw([[
49+
New Item
50+
Razor Quarterstaff
51+
+50% to Critical Damage Bonus
52+
]])
53+
build.itemsTab:AddDisplayItem()
54+
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
55+
build.mainSocketGroup = 1
56+
runCallback("OnFrame")
57+
58+
-- the weapon-local crit damage must NOT reach the spell (it isn't using the weapon)
59+
assert.are.equals(baseSpellCritMulti, build.calcsTab.mainOutput.CritMultiplier)
60+
end)
61+
3362
it("correctly converts spell damage per stat to attack damage", function()
3463
assert.are.equals(0, build.calcsTab.mainEnv.player.modDB:Sum("INC", { flags = ModFlag.Attack }, "Damage"))
3564
build.itemsTab:CreateDisplayItemFromRaw([[

spec/System/TestTradeQueryCurrency_spec.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@ describe("TradeQuery Currency Conversion", function()
2323
end)
2424
end)
2525

26+
describe("ReduceOutput", function()
27+
it("uses selected minion stats for weighted result comparison", function()
28+
mock_tradeQuery.statSortSelectionList = { { stat = "AverageDamage" } }
29+
30+
local result = mock_tradeQuery:ReduceOutput({
31+
AverageDamage = 10,
32+
Life = 100,
33+
Minion = {
34+
AverageDamage = 250,
35+
Life = 200,
36+
},
37+
})
38+
39+
assert.are.equals(250, result.AverageDamage)
40+
assert.is_nil(result.Life)
41+
end)
42+
end)
43+
2644
describe("PriceBuilderProcessPoENinjaResponse", function()
2745
-- Pass: Processes without error, restoring map while adding a notice
2846
-- Fail: Corrupts map or crashes, indicating fragile API response handling, breaking future conversions

spec/System/TestTradeQueryGenerator_spec.lua

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,50 @@ describe("TradeQueryGenerator", function()
3434
local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)
3535
assert.are.equal(result, 100)
3636
end)
37+
38+
it("uses minion output for non-FullDPS stats when minion output is available", function()
39+
local baseOutput = { AverageDamage = 10, Minion = { AverageDamage = 100 } }
40+
local newOutput = { AverageDamage = 10, Minion = { AverageDamage = 250 } }
41+
local statWeights = { { stat = "AverageDamage", weightMult = 1 } }
42+
data.misc.maxStatIncrease = 1000
43+
44+
local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)
45+
46+
assert.are.equal(result, 2.5)
47+
end)
48+
49+
it("uses player output for FullDPS even when minion output is available", function()
50+
local baseOutput = { FullDPS = 100, Minion = { FullDPS = 100 } }
51+
local newOutput = { FullDPS = 250, Minion = { FullDPS = 1000 } }
52+
local statWeights = { { stat = "FullDPS", weightMult = 1 } }
53+
data.misc.maxStatIncrease = 1000
54+
55+
local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)
56+
57+
assert.are.equal(result, 2.5)
58+
end)
59+
60+
it("uses the fallback DPS ratio once when FullDPS is unavailable", function()
61+
local baseOutput = { Minion = { TotalDPS = 10, TotalDotDPS = 0, CombinedDPS = 10 } }
62+
local newOutput = { Minion = { TotalDPS = 25, TotalDotDPS = 0, CombinedDPS = 25 } }
63+
local statWeights = { { stat = "FullDPS", weightMult = 1 } }
64+
data.misc.maxStatIncrease = 1000
65+
66+
local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)
67+
68+
assert.are.equal(result, 2.5)
69+
end)
70+
71+
it("falls back to player output when the selected stat is not on minion output", function()
72+
local baseOutput = { Spirit = 100, Minion = { AverageDamage = 100 } }
73+
local newOutput = { Spirit = 120, Minion = { AverageDamage = 100 } }
74+
local statWeights = { { stat = "Spirit", weightMult = 1 } }
75+
data.misc.maxStatIncrease = 1000
76+
77+
local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)
78+
79+
assert.are.equal(result, 1.2)
80+
end)
3781
end)
3882

3983
describe("Filter prioritization", function()

spec/System/TestTreeTab_spec.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,22 @@ describe("TreeTab", function()
146146
assert.is_nil(build.treeTab.specList[1].allocNodes[2])
147147
end)
148148
end)
149+
150+
describe("Power stat calculation", function()
151+
it("uses minion output for non-FullDPS stats when minion output is available", function()
152+
local selection = { stat = "AverageDamage" }
153+
local outputWithNode = { AverageDamage = 10, Minion = { AverageDamage = 250 } }
154+
local baseOutput = { AverageDamage = 10, Minion = { AverageDamage = 100 } }
155+
156+
assert.are.equals(150, build.calcsTab:CalculatePowerStat(selection, outputWithNode, baseOutput))
157+
end)
158+
159+
it("uses player output for FullDPS even when minion output is available", function()
160+
local selection = { stat = "FullDPS" }
161+
local outputWithNode = { FullDPS = 250, Minion = { FullDPS = 1000 } }
162+
local baseOutput = { FullDPS = 100, Minion = { FullDPS = 1000 } }
163+
164+
assert.are.equals(150, build.calcsTab:CalculatePowerStat(selection, outputWithNode, baseOutput))
165+
end)
166+
end)
149167
end)

src/Classes/CalcsTab.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ function CalcsTabClass:PowerBuilder()
672672
end
673673

674674
function CalcsTabClass:CalculatePowerStat(selection, original, modified)
675-
if modified.Minion and not selection.stat == "FullDPS" then
675+
if modified.Minion and selection.stat ~= "FullDPS" then
676676
original = original.Minion
677677
modified = modified.Minion
678678
end

src/Classes/Item.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,9 +1866,9 @@ function ItemClass:BuildModListForSlotNum(baseList, slotNum)
18661866
weaponData[value.key] = value.value
18671867
end
18681868
for _, mod in ipairs(modList) do
1869-
-- Convert accuracy, L/MGoH and PAD Leech modifiers to local
1869+
-- Convert accuracy, crit damage bonus, L/MGoH and PAD Leech modifiers to local
18701870
if (
1871-
(mod.name == "Accuracy" and mod.flags == 0) or (mod.name == "ImpaleChance" and mod.flags ~= ModFlag.Spell) or
1871+
(mod.name == "Accuracy" and mod.flags == 0) or (mod.name == "CritMultiplier" and mod.flags == 0) or (mod.name == "ImpaleChance" and mod.flags ~= ModFlag.Spell) or
18721872
((mod.name == "LifeOnHit" or mod.name == "ManaOnHit") and mod.flags == ModFlag.Attack) or
18731873
((mod.name == "PhysicalDamageLifeLeech" or mod.name == "PhysicalDamageManaLeech") and mod.flags == ModFlag.Attack)
18741874
) and (mod.keywordFlags == 0 or mod.keywordFlags == KeywordFlag.Attack) and not mod[1] then

src/Classes/ItemsTab.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,12 +702,13 @@ holding Shift will put it in the second.]])
702702
end
703703

704704
-- Section: Affix Selection
705+
local maxModCount = 9
705706
self.controls.displayItemSectionAffix = new("Control", {"TOPLEFT",self.controls.displayItemSectionRune,"BOTTOMLEFT"}, {0, 0, 0, function()
706707
if not self.displayItem or not self.displayItem.crafted then
707708
return 0
708709
end
709710
local h = 6
710-
for i = 1, 6 do
711+
for i = 1, maxModCount do
711712
if self.controls["displayItemAffix"..i]:IsShown() then
712713
h = h + 24
713714
if self.controls["displayItemAffixRange"..i]:IsShown() then
@@ -717,7 +718,7 @@ holding Shift will put it in the second.]])
717718
end
718719
return h
719720
end})
720-
for i = 1, 6 do
721+
for i = 1, maxModCount do
721722
local prev = self.controls["displayItemAffix"..(i-1)] or self.controls.displayItemSectionAffix
722723
local drop, slider
723724
local function verifyRange(range, index, drop) -- flips range if it will form discontinuous values

0 commit comments

Comments
 (0)