Skip to content

Fix defence conversion allocation with several targets - #2572

Open
Azaril wants to merge 1 commit into
PathOfBuildingCommunity:devfrom
Azaril:fix-defence-conversion-allocation
Open

Azaril wants to merge 1 commit into
PathOfBuildingCommunity:devfrom
Azaril:fix-defence-conversion-allocation

Conversation

@Azaril

@Azaril Azaril commented Oct 25, 2026

Copy link
Copy Markdown

Fixes #2570 .

Description of the problem being solved:

Two problems in the per-source conversion step of calcs.defence:

  • When a source's conversion rates total more than 100%, the loop meant to scale them down used ipairs over a table keyed by target name, so it never ran. Global and Life/Mana conversions then handed out more than 100% of the source.
  • The per-slot path reduced the source's slot base inside the target loop. Each target after the first took its share from an already reduced base, and the source was reduced once per target. This also happened below 100% total, and when a target came only from a gain-as rate.

This iterates the rates with pairs and reduces each slot base once, after every target has taken its share. The global and total bases already worked that way.

Steps taken to verify a working solution:

  • Added two specs to spec/System/TestDefence_spec.lua:

    • Life conversions totalling 125% scale by 100/125;
    • gaining Armour from Energy Shield doesn't change the Energy Shield kept or the Mana converted.

    Both fail on dev and pass with this change.

  • Ran every spec/System spec in ghcr.io/pathofbuildingcommunity/pathofbuilding-tests:latest, the same way CI does: 52 files, 905 tests, 0 failures.

  • Loaded both builds from Defence conversion: rates above 100% aren't scaled down, and a second target reduces the source base twice #2570:

    • Build A goes from Energy Shield 31 / Armour 93 to 25 / 84.
    • Build B goes from Energy Shield 46 / Mana 83 to 77 / 104.
  • No parser changes, so ModCache.lua is unaffected.

Link to a build that showcases this PR:

See the build codes in #2570.

Before screenshot:

  • Build A: Energy Shield 31, Armour 93.
  • Build B: Energy Shield 46, Armour 26, Mana 83.

After screenshot:

  • Build A: Energy Shield 25, Armour 84.
  • Build B: Energy Shield 77, Armour 26, Mana 104.

Two problems in the per-source conversion step of CalcDefence:

- When a source's ConvertTo* rates totalled more than 100%, the loop meant to
  scale them down used ipairs over a table keyed by target name, so it never
  ran. Global and Life/Mana conversions then converted more than 100% of the
  source.
- The per-slot path reduced the source's slot base inside the target loop.
  Every target after the first with a non-zero rate took its share from an
  already reduced base, and the source was reduced once per target. This also
  happened below 100% total, and when one target came only from a GainAs rate.

Iterate the rates with pairs, and reduce each slot base once after all targets
have taken their share.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Defence conversion: rates above 100% aren't scaled down, and a second target reduces the source base twice

1 participant