Skip to content

fix: lit-light transfer, torch sprite dialogs and Momentum first term (#134, #137, #138) - #139

Merged
DimitroffVodka merged 5 commits into
mainfrom
fix/issues-134-137-138
Sep 15, 2026
Merged

DimitroffVodka merged 5 commits into
mainfrom
fix/issues-134-137-138

Conversation

@DimitroffVodka

Copy link
Copy Markdown
Owner

What

Four fixes, one commit each:

Commit Fix
57d8cdbc Momentum first term (#134). Momentum finds the damage formula's first dice term with the system's own pattern, so terms like 1d(6+2) no longer get exploded twice.
1e75bbce Sprite config windows (#137). The Equipped Sprite and Torch Sprite windows scroll inside a resizable window that fits the screen, and Save/Cancel always stay visible.
d251a8c8 Torch Sprite flame. Moving or rescaling the torch prop in the dialog now carries the flame with it.
b95908cd Lit light transfer (#138). Transfer to Player moves a lit light's token light and torch sprite to the receiver.

How

  • Momentum not applying to bonus dice #134: SDX's DICE_TERM also matched terms the system's pattern skips (1dF, 1d(6+2)), so the two could disagree about which term comes first. SYSTEM_DICE_TERM copies the SD 4.0.6 pattern, and the dice terms on both sides of the system's first term get exploded. docs/wiki/Combat-and-Damage.md no longer says the Momentum toggle doesn't fix the system bug.
  • Sprite and Weapon Animation config menu too big. #137: Foundry caps .application height and hides overflow, so the tail of a tall form was cut off with no scrollbar. The fix is a flex scroll area with the footer outside it. The Weapon config window also calls setPosition() again when it grows, because Foundry only keeps a window on screen when its position is set, not when its content grows.
  • Torch flame: a change to the dialog only. It remembers where the flame sits on the prop and rebuilds the flame position and size after each prop edit. The saved torchSprite values keep their meaning, so there's no migration and the code that draws the sprite in play is unchanged.
  • Light Sources Transfer to Player #138: nativeTransferItems copied the lit item and deleted the original but never moved the light. It now hands the light over the way the system's sheet drop does:
    • it puts out the receiver's own light, creates the copy, then calls turnLightOff on the giver and turnLightOn on the receiver
    • the existing createItem/updateToken hooks move the sprite
    • a lit item never merges into an existing stack, and a split of a lit stack arrives unlit

Test plan

  • New tests: weapon-momentum.test.mjs (first-term boundary), torch-sprite-flame-follow.test.mjs, and transfer-lit-light.test.mjs. On the code before the fix, three of the transfer file's four cases fail.
  • npm test: 1644 pass, 0 fail
  • npm run verify: verify: OK
  • Each fix was checked live on V14 with SD 4.0.6:

Known gaps, not fixed here

  • Light Sources Transfer to Player #138:
    • The party sheet's Transfer to member, and the trade window when Item Piles is active, still move a lit item without its light.
    • When the GM relays the transfer, the GM's current scene decides which token gets the light. The system's own torch pickup has the same limit.
  • Torch flame: saved configs whose prop was moved before this fix keep their out-of-place flame until the flame sliders are touched once or Reset is used.
  • Momentum not applying to bonus dice #134: SYSTEM_DICE_TERM is a hand copy of the system's regex. A future system change to that pattern could make them disagree again.

Fixes #138. Refs #134, #137.

🤖 Generated with Claude Code

With world Momentum on, SDX pre-explodes every damage die except the one
stock Shadowdark 4.0.6 will explode itself. That term was located with
SDX's DICE_TERM, which also matches non-numeric faces (1dF, 1d(6+2)); the
system's pattern skips them. When a formula led with such a term the two
disagreed about which die was first, so '1d(6+2) + 1d6' came out as
'1d(6+2) + 1d6xx' — a doubled explode and inflated damage.

The boundary now uses the system's regex, and terms on both sides of it
are exploded, so a leading paren-faced die explodes too. Live-verified
against stock 4.0.6 through rollFromConfig.

Also rewrites the Combat-and-Damage Momentum section, which still said
SDX does not fix the system's first-die-only behaviour (it has since
v6.14.0), and notes that the fix-up rides the Weapon Bonuses feature.

Refs #134
Foundry caps every window at the viewport and clips .window-content, so a tall Equipped Sprite or Torch Sprite form hid its Save button. The fields now scroll with the buttons pinned, both windows are resizable, and the Equipped Sprite window re-clamps its top when the image browser, a category or the enable checkbox makes it taller.
Prop and flame are stored as separate token-relative offsets, so moving or rescaling the prop left the flame behind. Prop edits now move the flame to the same spot on the prop art and scale it with the prop; flame edits re-anchor it. Dialog-only: the saved torchSprite flag format is unchanged.
nativeTransferItems copied a lit item to the receiver and deleted the
original, but never moved the token light. The giver kept a light with no
item left to put it out, and the receiver's lit item cast none. It now hands
the light over the way the system's sheet drop does: put out the receiver's
own light, create the copy, then turnLightOff on the giver and turnLightOn
on the receiver. The torch sprite follows through the existing createItem
and updateToken hooks. A lit item no longer merges into an existing stack,
and a split of a lit stack arrives unlit.
…bound

Carrying the flame with the prop could push a flame value past its
range-picker bounds (default torch, prop X 1 carries the flame to 1.15),
and the picker clamped it off its spot on the prop. fitProp finds how far
the edited prop field can go before any carried flame value leaves its
slider, stops the prop there, and snaps inward to the prop slider's step
because the picker rounds to the nearest step.
@DimitroffVodka

Copy link
Copy Markdown
Owner Author

[P2] Preserve the flame anchor when carried values exceed bounds (scripts/animation/TorchSpriteConfig.mjs:149-151)

Fixed in 7729c38.

The flame sliders can't be widened to fit a carried value, because <range-picker> reads its min/max once, in its constructor. So a prop edit now stops where the flame reaches its limit:

  • fitProp finds how far the edited prop field (X, Y or scale) can go before any carried flame value (X, Y or size) leaves its slider range, and stops the prop there.
  • It rounds that stop toward the allowed side. The picker rounds to its nearest step, so it could otherwise land just past the limit.

With the default torch, prop X now stops at 0.85, and the flame lands at exactly 1 on the same spot of the prop.

Tests: 3 new cases in torch-sprite-flame-follow.test.mjs: the upper limit, the lower limit, and a limit that falls between steps (1.714, rounded down to 1.7). npm test 1647/1647, verify: OK, CI green.

Live check in the real dialog, on an unlit Torch:

  • Dragging prop X to 1 stopped at -0.1, with the flame at exactly 1 and still on the same spot of the prop.
  • Dragging scale to 3 stayed at 1.5, because the flame was already at its right-hand limit.
  • Cancel left the saved settings unchanged.

Behaviour change: when the flame is near an edge, a prop slider now stops before its end. Moving the flame first frees it.

@DimitroffVodka
DimitroffVodka merged commit 7619028 into main Sep 15, 2026
1 check passed
@DimitroffVodka
DimitroffVodka deleted the fix/issues-134-137-138 branch September 15, 2026 15:09
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.

Light Sources Transfer to Player

1 participant