Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
9a2c480
Port PoB1 #9861 type hint PR (#2414)
vaisest Aug 26, 2026
5b89749
Add breakdowns to the build side bar on mouseover (#2435)
vaisest Aug 26, 2026
93e7794
Add Path of Exile 2 BuildPlanner (.build) export (#2432)
vaisest Aug 27, 2026
aca2a73
Port add comparisons to config tab tooltips (#10050) (#2438)
vaisest Aug 27, 2026
2494062
Port refactor custom modifiers block into toggleable blocks (#10050, …
vaisest Aug 27, 2026
7330bcc
Port add comparisons to config tab tooltips (#10050) (#2440)
vaisest Aug 27, 2026
1d8bfec
Improve Build Export qol (#2436)
LocalIdentity Aug 27, 2026
cabfc9a
Editor config
Aug 27, 2026
dc9f761
Port "Improve buy similar matching" (#10284) (#2441)
vaisest Aug 27, 2026
3ec148d
Port "Use Currency Exchange API instead of poe.ninja in trader" #1007…
vaisest Aug 27, 2026
d7c0fda
Fix trader row hiding logic (#2444)
vaisest Aug 28, 2026
4678d16
Add support for select pseudo stats in trader weights (#2445)
vaisest Aug 28, 2026
eb5bfde
Improve stat search with pseudo stats and word order ignore (#2446)
vaisest Aug 28, 2026
9d037a8
Add NOT filters to trader (#2447)
vaisest Aug 28, 2026
9394553
Improve calc performance (#2448)
vaisest Aug 28, 2026
db28dde
Fix Abyssal wasting Stat description
Aug 29, 2026
188f932
Add support for increased mod magnitude mods and Unborn Lich (#2453)
vaisest Aug 29, 2026
4c35bfd
ModCache
Aug 29, 2026
da416ad
Fix more side bar breakdowns (#2450)
vaisest Aug 29, 2026
6df5844
Add a bunch of type hints (#2454)
vaisest Aug 29, 2026
ea0b2cf
Add support for Grip of Kulemak's Abyssal Wasting (#2455)
vaisest Aug 29, 2026
e7ec912
Add more type hints for mods and calculations (#2456)
LocalIdentity Aug 29, 2026
73ffd51
Fix Mageblood + Against the Darkness
Aug 29, 2026
773ed75
[pob1-port] Add sorting for modifier dropdowns in crafting UI (#2470)
github-actions[bot] Aug 29, 2026
574b7e7
[pob1-port] Allow recursive build list search with class filtering (#…
github-actions[bot] Aug 29, 2026
388d275
[pob1-port] Show augmented Armour/Evasion/Ward/Energy Shield in blue …
github-actions[bot] Aug 29, 2026
defd734
[pob1-port] Fix Shield block chance calcs (#2466)
github-actions[bot] Aug 29, 2026
0043cde
[pob1-port] Fix Drillneck damage applying to Spells (#2465)
github-actions[bot] Aug 29, 2026
a5950a4
[pob1-port] Fix being unable to set Enemy Resistance to 0 in config t…
github-actions[bot] Aug 29, 2026
59393d4
[pob1-port] Fix some mods not checking payable cost (#2457)
github-actions[bot] Aug 29, 2026
e7249b4
Apply changes from https://github.com/PathOfBuildingCommunity/PathOfB…
github-actions[bot] Aug 29, 2026
495b3aa
[pob1-port] Fix Mana cost efficiency rounding (#2458)
github-actions[bot] Aug 29, 2026
71f92c4
[pob1-port] Allow toggling individual item mods just by clicking on t…
github-actions[bot] Aug 29, 2026
2d3eb00
[pob1-port] Add items filter by loadout (#2463)
github-actions[bot] Aug 29, 2026
15eeb9e
Port versioned unique variant groups from PoB 1 (#2472)
LocalIdentity Aug 30, 2026
d0886e6
Fix PoB1 port action
Aug 30, 2026
dcaf526
[pob1-port] Fix mirrored items missing "Mirrored" text when using API…
github-actions[bot] Aug 30, 2026
3724086
[pob1-port] Fix skill Area of Effect rounding and minion skill AoE va…
github-actions[bot] Aug 30, 2026
ae1e2d1
[pob1-port] Fix allocated nodes appearing in unallocated power report…
github-actions[bot] Aug 30, 2026
8a69ebb
[pob1-port] Fix Block chance rounding with Mana-Infused Staff (#2480)
github-actions[bot] Aug 30, 2026
c24c4f1
[pob1-port] Fix Vulconus Avatar of Fire mod not applying when the Key…
github-actions[bot] Aug 30, 2026
0786e48
Apply changes from https://github.com/PathOfBuildingCommunity/PathOfB…
github-actions[bot] Aug 30, 2026
f5f9cec
[pob1-port] Clarify stat-difference shortcut context (#2484)
github-actions[bot] Aug 30, 2026
033c3d2
[pob1-port] Fix Herald Skills not scaling area with some tree nodes (…
github-actions[bot] Aug 30, 2026
dcf8d9e
Apply changes from https://github.com/PathOfBuildingCommunity/PathOfB…
github-actions[bot] Aug 30, 2026
7e89f96
Apply changes from https://github.com/PathOfBuildingCommunity/PathOfB…
github-actions[bot] Aug 30, 2026
8293385
Apply changes from https://github.com/PathOfBuildingCommunity/PathOfB…
github-actions[bot] Aug 30, 2026
357e189
[pob1-port] Fix harvest Weapon Range enchant not appearing properly (…
github-actions[bot] Aug 30, 2026
c470f8e
[pob1-port] Fix "x to Total Mana Cost" mods not working correctly wit…
github-actions[bot] Aug 30, 2026
0a7d941
[pob1-port] Fix rounding of scaled damage conversion percentages (#2477)
github-actions[bot] Aug 30, 2026
d1a5bf0
Fix test
Aug 30, 2026
372eec8
[pob1-port] Increase wait time for OAuth login and copy URL to clipbo…
github-actions[bot] Aug 30, 2026
bfcc04b
[pob1-port] Fix reimport of skills showing old gem data (#2491)
github-actions[bot] Aug 30, 2026
4cac6a2
[pob1-port] Update gem control to lazily sort by DPS (#2473)
github-actions[bot] Aug 30, 2026
c2175fd
[pob1-port] Allow calc panes to become overlay windows (#2487)
github-actions[bot] Aug 30, 2026
a92b33d
[pob1-port] Fix various issues with advanced copy/paste (#2474)
github-actions[bot] Aug 30, 2026
99c9fbf
Implement scoring % breakdown to Trader result dropdown (#2374)
Lawlzer Aug 30, 2026
061f1b1
Cache tooltip assets (#2493)
meehl Aug 30, 2026
ea03acd
Add Minion Rage configuration support (#2425)
kylande01 Aug 30, 2026
3530368
Fix an interaction between Rakiatas Flow and sources of "ignore non-n…
emptywalls Aug 30, 2026
ec72557
refactor, simplify calcAncestralBoost (#2370)
Peechey Aug 30, 2026
5cf521f
Fix crash when adding +1 Suffix Rune (#2372)
sengokudaikon Aug 30, 2026
5c7ce7f
Fix 2H weapons not removing off-hand items in comparisons (#2368)
vaisest Aug 30, 2026
47b9789
Add support for Runic ward (#2146)
Blitz54 Aug 31, 2026
3145221
Fix Bringer of Rain not importing off hand Shield (#2496)
LocalIdentity Aug 31, 2026
0ac860d
Fix tooltip issue
Aug 31, 2026
802f17f
Add support for Idolatry and change how Bonded lines are parsed (#2366)
LocalIdentity Aug 31, 2026
1bcdb48
Add Martial Artist Rune slots (#1991)
vaisest Aug 31, 2026
97cb973
Improve JITability of Calc-related code: (#2494)
vaisest Sep 1, 2026
0194cf7
Added support for Decree of Loyalty mods (#2497)
ntcarlson Sep 4, 2026
3887ae6
Fix double clicking and dragging items causing issues - #10149 (#2500)
vaisest Sep 4, 2026
8d187d7
Merge remote-tracking branch 'upstream/dev' into sync-upstream-2026-0…
Sep 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
trim_trailing_whitespace = false
indent_style = tab
max_line_length = 360
align_array_table = false
align_continuous_rect_table_field = false
32 changes: 30 additions & 2 deletions .github/workflows/backport_receive.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,42 @@ jobs:
with:
ref: 'dev'
- name: Apply patch
env:
PORT_SOURCE_TOKEN: ${{ secrets.WIRES77_PAT }}
PR_NUMBER: ${{ github.event.client_payload.id }}
run: |
# Download patch first to avoid broken pipes if apply exits early
set -euo pipefail

if [ -z "$PORT_SOURCE_TOKEN" ]; then
echo "::error::WIRES77_PAT is not configured"
exit 1
fi

PATCH_FILE=$(mktemp)
curl -L ${{ github.event.client_payload.patch_url }} -o "$PATCH_FILE"
curl --fail-with-body --location \
--retry 5 \
--retry-all-errors \
--retry-max-time 300 \
--header "Accept: application/vnd.github.patch" \
--header "Authorization: Bearer $PORT_SOURCE_TOKEN" \
--header "X-GitHub-Api-Version: 2026-03-10" \
"https://api.github.com/repos/PathOfBuildingCommunity/PathOfBuilding/pulls/$PR_NUMBER" \
--output "$PATCH_FILE"

if ! grep -Eq '^(From [0-9a-f]{40} Mon Sep 17 00:00:00 2001|diff --git )' "$PATCH_FILE"; then
echo "::error::GitHub returned something other than a patch"
exit 1
fi

if ! git apply -v --3way --ignore-whitespace --index "$PATCH_FILE"; then
echo "3-way apply failed, retrying with --reject"
git apply -v --reject --ignore-whitespace --index "$PATCH_FILE" || true
fi

if [ -z "$(git status --porcelain)" ]; then
echo "::error::Patch produced no changes or rejection files"
exit 1
fi
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
Expand Down
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ luajit/
spec/test_results.log
spec/test_generation.log
src/luacov.stats.out
runtime/lua/debugger.lua

# Release
manifest-updated.xml
Expand All @@ -33,7 +34,7 @@ src/Export/ggpk/*.dll
src/TreeData/**/*.scm
src/TreeData/**/*.txt
src/TreeData/**/*.bat

# PoB Trader
*_currency_values.json

Expand All @@ -42,6 +43,10 @@ src/Data/TimelessJewelData/*.bin

# Simplegraphic Debugging
runtime/imgui.ini

runtime/SimpleGraphic/SimpleGraphic.log

src/poe_api_response.json
runtime/SimpleGraphic/Screenshots

.emmyrc.json
.luarc.json
99 changes: 97 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ It is recommended to use it over the built-in Lua plugins.
Please note that EmmyLua is not available for other editors based on Visual Studio Code,
such as [VSCodium](https://vscodium.com) or [Eclipse Theia](https://theia-ide.org) but can be built from source if needed.

Another alternative on VSCode is to use [sumneko's Lua language server](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) along with [actboy168's debugger](https://marketplace.visualstudio.com/items?itemName=actboy168.lua-debug). These can potentially offer more features than EmmyLua, such as conditional breakpoints.

## Runtime environment

It is recommended that you configure your IDE to include `src/_SimpleGraphic.def.lua` somehow. Path of Building runs inside a special Lua environment via SimpleGraphic which implements a small API. These are not defined inside the project, which means that the aforementioned meta/hint file is required for the IDE to know which functions exist. As the file is not included in code, it must be explicitly mentioned as a library in whichever language server you are using, or otherwise it will not be read.

This file is normally not executed, but does contain basic implementations for parts of the API, which allows many parts of PoB to work without running inside SimpleGraphic. If you wish to test individual changes, it might be possible to do so through a script using Luajit directly. To do so, see HeadlessWrapper.lua for an example. It should be noted that some parts of the API (such as subscripts) are not implemented, which means some parts of PoB are unusable.

### Visual Studio Code

1. Create a new <kbd>Debug Configuration</kbd> of type <kbd>EmmyLua New Debug</kbd>
Expand Down Expand Up @@ -171,20 +179,60 @@ such as [VSCodium](https://vscodium.com) or [Eclipse Theia](https://theia-ide.or
1. In VSCode click <kbd>Start Debugging</kbd> (the green icon) or press <kbd>F5</kbd>
1. The debugger should connect

You might also want to use actboy168 debugger. This is possible by using for example the following launch.json configuration:

```json
{
"version": "0.2.0",
"configurations": [
{
"name": "🍄attach",
"type": "lua",
"request": "attach",
"stopOnEntry": false,
"address": "127.0.0.1:12306",
"luaVersion": "luajit",
},

]
}
```

Then, similarly to the EmmyLua example:

1. Find the sub-folder that looks like `actboy168.lua-debug-x.y.z-win32-x64` in `%USERPROFILE%/.vscode/extensions`. Navigate to it and find the `debugger.lua` script under the script folder. Copy this to `runtime/lua`.
2. Copy-paste the following code snippet into `launch:OnInit()`:
```lua
local debugger = require("debugger"):start("127.0.0.1:12306")
-- debugger:event("wait") -- Uncomment this line if you want PoB to wait until the debugger is attached.
```

Note that Linux developers using Wine might need to use the Windows debugger instead of using the VSCode debugger. This can be done by:

1. Downloading the .vsix from the VSCode extension page
2. Copying `extension/{script,runtime}` to the `runtime` folder of the PoB directory (i.e., `runtime/runtime`).
3. Copying `debugger.lua` from `runtime/scripts/debugger.lua` to `runtime/lua/debugger.lua`.
4. Using `local debugger = loadfile(GetRuntimePath().."/lua/debugger.lua")():start("127.0.0.1:12306")` instead of the above code to avoid issues with Wine backwards slashes

#### Excluding directories from EmmyLua

Depending on the amount of system ram you have available and the amount that gets assigned to the jvm running the emmylua language server you might run into issues when trying to debug Path of building.
Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua language server to use a significant amount of memory. Sometimes causing the language server to crash. To avoid this and speed up initialization consider adding an `.emmyrc.json` file to the `.vscode` folder in the root of the Path of building folder with the following content:
Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua language server to use a significant amount of memory. Sometimes causing the language server to crash. To avoid this and speed up initialization consider adding an `.emmyrc.json` to the root of the Path of building folder with the following content:

```json
{
"$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
"runtime": {
"version": "LuaJIT"
"version": "LuaJIT",
// this is not technically correct as LoadModule behaviour can
// differ from require, but it is useful for now
"requireLikeFunction": ["LoadModule"],
},
"workspace": {
"ignoreGlobs": [
"**/*_spec.lua",
"spec/**/*.lua",
"runtime/lua/sha1/lua53_ops.lua",
"**/src/Data/**/*.lua",
"**/src/TreeData/**/*.lua",
"**/src/Modules/ModParser.lua"
Expand All @@ -193,6 +241,46 @@ Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua
}
```

This file can be customised according to what you want. It is a good idea to ignore test files as these tend to add things to the global namespace, which will look confusing, and they are designed to be run by Busted. `lua53_ops.lua` produces errors and doesn't actually get imported when using LuaJIT. It can be useful to keep the data and mod parser files, but generally this will increase the time the LSP takes to index the project on startup.

### Excluding directories from Sumneko's language server

If you prefer to not use EmmyLua, the following configuration works well for Sumneko's VS Code extension:

```json
{
"Lua.workspace.ignoreDir": [
".vscode",
// these files add things to global that aren't there in normal
// operation
"spec/*",
"src/Export/*",
"src/HeadlessWrapper.lua",

// this has lua 5.3 code which produces errors, but doesn't actually run
"src/runtime/lua/sha1/*",

// avoid overriding the below library setting
"src/_SimpleGraphic.def.lua",
],
"Lua.diagnostics.disable": ["inject-field"],
// disables diagnostics even when you open one of the above
"Lua.diagnostics.ignoredFiles": "Disable",
"Lua.runtime.version": "LuaJIT",
"Lua.workspace.preloadFileSize": 1000,
// this is not technically correct as LoadModule behaviour can
// differ from require, but it is useful for now
"Lua.runtime.special": {
"LoadModule": "require"
},
"Lua.workspace.library": [
"src/_SimpleGraphic.def.lua"
],
}
```

The extension will automatically skip large files from being preloaded (controlled by `Lua.workspace.preloadFileSize`), so they don't have to be excluded. The configuration file can be found by pressing Ctrl-Shift-P and selecting `Preferences: Open Workspace Settings (JSON)`. If you wish to check test files, you can remove the "ignoredFiles" option and install the busted, LuaFileSystem, and luassert LuaLS addons through `Lua: Open Addon Manager`.

### PyCharm Community / IntelliJ Idea Community

1. Create a new "Debug Configuration" of type "Emmy Debugger(NEW)".
Expand Down Expand Up @@ -226,6 +314,13 @@ More tests can be added to this folder to test specific functionality, or new te

Please try to include tests for your new features in your pull request. Additionally, if your pr breaks a test that should be passing please update it accordingly.

It is a good idea to prefer Docker due to it having a very reliable Lua setup. But if you have performance problems with it, installing `busted` locally might help as it tends to be faster to execute:

1. Install Luajit (due to PoB accessing the jit library, it non-Luajit versions might not work)
2. Install [Luarocks](https://luarocks.org/) (for example, through Scoop or your Linux package manager)
3. Run `luarocks install busted`
4. Run `busted --lua=luajit` to run the tests. You can also use e.g. `-p TestUtils_spec.lua` to run a specific file.

### Debugging tests
When running tests with a docker container it is possible to use EmmyLua for debugging. Paste in the following right under `function launch:OnInit()` in `./src/Launch.lua`:
```lua
Expand Down
2 changes: 1 addition & 1 deletion manifest.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ exclude-directories =

[program]
path = src
exclude-files = HeadlessWrapper.lua,LaunchInstall.lua,Settings.xml
exclude-files = HeadlessWrapper.lua,LaunchInstall.lua,Settings.xml,_SimpleGraphic.def.lua
exclude-directories = src/Export,src/TreeData,src/Builds,src/luacov.stats.out,src/Data/TimelessJewelData/BrutalRestraint.bin,src/Data/TimelessJewelData/ElegantHubris.bin,src/Data/TimelessJewelData/GloriousVanity.bin,src/Data/TimelessJewelData/LethalPride.bin,src/Data/TimelessJewelData/MilitantFaith.bin,src/poe_api_response.json

[tree]
Expand Down
138 changes: 138 additions & 0 deletions spec/System/TestBuildDisplayStats_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
describe("Build display stats", function()
local originalCompactValues

before_each(function()
originalCompactValues = main.useCompactValues
newBuild()
end)

after_each(function()
main.useCompactValues = originalCompactValues
end)

local function getSidebarLine(label)
local suffix = label .. ":"
for _, stat in ipairs(build.controls.statBox.list) do
if stat[1] and stat[1]:sub(-#suffix) == suffix then
return stat
end
end
end

it("only underlines sidebar stats with a visible breakdown", function()
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
runCallback("OnFrame")

for _, line in ipairs(build.controls.statBox.list) do
if line.underline and line.underline[2] then
build:SetDisplayStat({ line = line, x = 0, y = 0, width = 300 }, false)
assert.is_true(build.controls.breakdown.shown, line[1])
build:ClearDisplayStat()
end
end
end)

it("links resource sidebar stats to their breakdowns", function()
local expectedBreakdowns = {
LifeUnreserved = "LifeReserved",
LifeUnreservedPercent = "LifeReserved",
ManaUnreserved = "ManaReserved",
ManaUnreservedPercent = "ManaReserved",
SpiritUnreserved = "SpiritReserved",
SpiritUnreservedPercent = "SpiritReserved",
LifeLeechGainRate = "LifeLeech",
ManaLeechGainRate = "ManaLeech",
EnergyShieldLeechGainRate = "EnergyShieldLeech",
}
for _, statData in ipairs(build.displayStats) do
if expectedBreakdowns[statData.stat] then
assert.are.equal(expectedBreakdowns[statData.stat], statData.breakdown, statData.stat)
expectedBreakdowns[statData.stat] = nil
end
end
assert.is_nil(next(expectedBreakdowns))
end)

it("shows a breakdown for life reserved by a modifier", function()
build.itemsTab:CreateDisplayItemFromRaw("New Item\nGold Ring\nReserves 25% of Life")
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")

local lifeLine = getSidebarLine("Unreserved Life")
assert.are.equal("LifeReserved", lifeLine.breakdown)
build:SetDisplayStat({ line = lifeLine, x = 0, y = 0, width = 300 }, false)
assert.is_true(build.controls.breakdown.shown)
end)

it("uses aggregate breakdowns for dual-wield attacks", function()
build.skillsTab:PasteSocketGroup("skillId:MeleeMaceMacePlayer Mace Strike 20/0 1")
build.itemsTab:CreateDisplayItemFromRaw("New Item\nMarauding Mace\nQuality: 0\n20% increased Attack Speed")
build.itemsTab:AddDisplayItem()
build.itemsTab:CreateDisplayItemFromRaw("New Item\nMarauding Mace\nQuality: 0")
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")

local actor = build.calcsTab.mainEnv.player
assert.is_true(actor.mainSkill.activeEffect.statSet.skillFlags.bothWeaponAttack)
assert.matches("Simultaneous hits from each weapon", table.concat(actor.breakdown.Speed, "\n"), nil, true)
assert.matches("Both weapons", table.concat(actor.breakdown.PreEffectiveCritChance, "\n"), nil, true)
assert.matches("Both weapons", table.concat(actor.breakdown.CritChance, "\n"), nil, true)
assert.not_matches("Crit confirmation roll", table.concat(actor.breakdown.PreEffectiveCritChance, "\n"), nil, true)
assert.matches("Crit confirmation roll", table.concat(actor.breakdown.CritChance, "\n"), nil, true)
assert.not_matches("Effective Crit Chance:", table.concat(actor.breakdown.CritChance, "\n"), nil, true)
assert.matches("Both weapons", table.concat(actor.breakdown.HitChance, "\n"), nil, true)

local critLine = getSidebarLine("Crit Chance")
local effectiveCritLine = getSidebarLine("Effective Crit Chance")
assert.are.equal("PreEffectiveCritChance", critLine.breakdown)
assert.are.equal("CritChance", effectiveCritLine.breakdown)

local displayData = build:GetSidebarBreakdown(critLine.breakdown, critLine.modNames, critLine.ignoredSections, "player")
local breakdownCount = 0
local hasMainHandModifiers = false
for _, section in ipairs(displayData) do
breakdownCount = breakdownCount + (section.breakdown and 1 or 0)
hasMainHandModifiers = hasMainHandModifiers or section.cfg == "weapon1"
end
assert.are.equal(1, breakdownCount)
assert.is_true(hasMainHandModifiers)
end)

it("uses off-hand breakdowns for shield attacks", function()
build.itemsTab:CreateDisplayItemFromRaw("New Item\nShortsword\nQuality: 0")
build.itemsTab:AddDisplayItem()
build.itemsTab:CreateDisplayItemFromRaw("New Item\nSplintered Tower Shield\nQuality: 0")
build.itemsTab:AddDisplayItem()
build.skillsTab:PasteSocketGroup("Shield Wall 20/0 1")
build.configTab.input.enemyEvasion = 10000
build.configTab:BuildModList()
runCallback("OnFrame")

local actor = build.calcsTab.mainEnv.player
assert.is_falsy(actor.mainSkill.activeEffect.statSet.skillFlags.weapon1Attack)
assert.is_true(actor.mainSkill.activeEffect.statSet.skillFlags.weapon2Attack)
assert.are.equal(actor.breakdown.OffHand.Speed, actor.breakdown.Speed)
assert.are.equal(actor.breakdown.OffHand.AccuracyHitChance, actor.breakdown.HitChance)
assert.are.equal(actor.breakdown.OffHand.PreEffectiveCritChance, actor.breakdown.PreEffectiveCritChance)
assert.are.equal(actor.breakdown.OffHand.CritChance, actor.breakdown.CritChance)

local critLine = getSidebarLine("Crit Chance")
local effectiveCritLine = getSidebarLine("Effective Crit Chance")
assert.are.equal("PreEffectiveCritChance", critLine.breakdown)
assert.are.equal("OffHand.CritChance", actor.breakdown.PreEffectiveCritChance.breakdownSource)
assert.are.equal("CritChance", effectiveCritLine.breakdown)

local displayData = build:GetSidebarBreakdown(critLine.breakdown, critLine.modNames, critLine.ignoredSections, "player")
local hasModifierSection = false
for _, section in ipairs(displayData) do
hasModifierSection = hasModifierSection or section.modName ~= nil
end
assert.is_true(hasModifierSection)

build.configTab.input.enemyBlockChance = 25
build.configTab:BuildModList()
runCallback("OnFrame")
actor = build.calcsTab.mainEnv.player
assert.are.equal(actor.breakdown.OffHand.HitChance, actor.breakdown.HitChance)
end)
end)
Loading
Loading