Skip to content

Gaslight v2.1.0 — Initiative Tracking, HUD System, Sync Commands#2276

Open
KenanMillet wants to merge 38 commits into
Roll20:masterfrom
KenanMillet:Gaslight-v2.1.0
Open

Gaslight v2.1.0 — Initiative Tracking, HUD System, Sync Commands#2276
KenanMillet wants to merge 38 commits into
Roll20:masterfrom
KenanMillet:Gaslight-v2.1.0

Conversation

@KenanMillet

@KenanMillet KenanMillet commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Major feature release adding initiative tracking across gaslit pages, an on-canvas HUD system, and per-token sync control commands.

New Features

Initiative Tracking

  • Linked tokens auto-added/removed from turn order
  • Initiative value changes propagate to all linked copies
  • Direction-aware auto-skip: non-master children skipped on forward/backward
  • Sort-aware: master tokens always grouped on top after sort
  • Manual drag reorder: master-anchored grouping
  • Round calculation formula support for custom turns

HUD System (!gaslight hud)

  • View indicator: Shows current relay state (ALL / OFF / player name) on the foreground layer
  • Initiative HUD: On-canvas turn order display with:
    • Pathv2 frame (resizable, customizable stroke/fill)
    • Mirrored token entries (syncs name, status, tint via Mirror)
    • Custom turn pins (square, transparent, titled)
    • Current turn diamond indicator (movable to set Y position)
    • Overflow hidden (baseOpacity/showname for tokens, off-screen for pins)
    • Drag-to-reorder: vertical drag between entries changes initiative order
    • Swipe-to-change-turn: horizontal drag past frame edge makes it that token's turn
    • Current turn swipe: advances/retreats past linked children
    • Dynamic token sizing from frame width
    • Adjustable: frame size/position, token padding, text offset/font/color/stroke, highlight styling
    • Direction-based custom pin shift with circular wrap
    • Round calculation formulas applied on turn entry
    • Delete token/pin = remove from initiative; delete frame = HUD off
  • Both elements: on by default for new installs, persist through merge/split, customizable via GM interaction
  • Commands: !gaslight hud [on|off|reset] [init|view], aliases (init/turn/turns, relay)

Sync/Desync Commands

  • !gaslight sync [props|all|reset] — manage per-token sync whitelist
  • !gaslight desync [props|all] — exclude props from sync
  • Token-level gaslight_sync in gmnotes (same pattern as gaslight_link)
  • Auto-populated from character attribute on token placement/split

View Modes

  • !gaslight view off — disable relay (GM-only changes)
  • !gaslight view master — relay to all (default on split)
  • !gaslight view <player> — relay to specific player
  • State migration from v2.0.0 (null → 'master')

Bug Fixes

  • Fix: multiple custom turns allowed (don't add '-1' to placed set)
  • Fix: deduplicate linkedIds before adding to turn order
  • Fix: initiative drag reorder uses master-anchored grouping
  • Fix: always run reorderInitiative as final step (fixes reverse-sort)
  • Fix: parent added to knownFlags (prevents leaking as scene param)

Dependencies

No new dependencies. Uses existing Anchor, Mirror, PathV2, Pin APIs.

Testing

  • Initiative forward/backward/sort/drag all tested
  • HUD view/initiative elements tested (toggle, reset, styling, positioning)
  • Merge/split lifecycle tested (HUD destroyed on merge, recreated on split)
  • Multiple custom turns, duplicate linkedIds edge cases tested

- Auto-add linked copies when a token is added to turn order
- Auto-remove linked copies when a token is removed
- Initiative value sync: changes propagate to all linked tokens
- Direction-aware auto-skip: non-master children are skipped on forward/backward
- Sort detection: reorders groups with master on top after sort
- _pageid included on pushed entries for cross-page visibility
- gaslight_sync now reads from token gmnotes (same pattern as gaslight_link)
- Auto-populate from character attribute on token placement/split
- !gaslight sync [show|set|add|remove|clear] — manage sync props per token
- !gaslight desync [add|remove] — manage exclusions per token
- getGaslightSync accepts token object or charId (backward compat)
- !gaslight sync (no args) — show current config
- !gaslight sync <props> — add to whitelist
- !gaslight sync all — explicitly sync everything
- !gaslight sync reset — remove token-level override
- !gaslight desync <props> — exclude props from sync
- !gaslight desync all — disable all syncing (preserves link)
…pies from character

- getGaslightSync reads only from token gmnotes (no runtime fallback)
- Character attribute is purely a template (auto-populated on token place/split)
- !gaslight sync reset now re-copies character attribute value into token gmnotes
- Consistent with gaslight_link pattern
- s.view = null → relay disabled (GM-only changes)
- s.view = 'master' → relay to all players (default on split)
- s.view = <playerId> → relay to specific player
- !gaslight view off/none → disable relay
- !gaslight view master/gm/all → enable relay to all
- Split sets view to 'master' automatically
- SCRIPT_VERSION -> 2.1.0
- Migration: v2.0.0 state with view=null (meant relay-all) -> view='master'
- New installs default view to 'master'
@KenanMillet KenanMillet marked this pull request as draft July 1, 2026 20:21
…lp text

- Created 2.1.0 versioned copy
- script.json: version 2.1.0, added 2.0.0 to previousversions, new commands in description
- README: added sync/desync commands, view modes, initiative tracking sections
- HELP_TEXT: full command reference with view modes + initiative note
@KenanMillet KenanMillet marked this pull request as ready for review July 1, 2026 23:44
- reorderInitiative skips children, only anchors at master position
- Auto-skip only fires on forward/backward turn advance
- Manual drag with child on top triggers reorder instead of skip
- Standalone reorder detection runs when master on top + order changed
…ouping

- Remove complex sort/drag detection heuristics
- Always run reorderInitiative as final step before writing
- Idempotent: no-op if groups already correct
- Fixes reverse-sort leaving children above master
- HUD infrastructure: state.hud tracks preferences + element IDs
- !gaslight hud [element] [on|off|reset] — toggle/reset HUD elements
- View HUD: foreground text showing relay state (OFF/ALL/player)
- Position/size persists when GM moves element (change:text listener)
- Delete = off (destroy:text listener, whispers to GM)
- Merge destroys elements, split recreates if preference is on
- Startup recovery: recreate missing elements, clean orphans
- Reset: clears saved position, turns on, moves to center-top default
- Frame path on foreground layer with token entries
- Mirror-linked to master tokens (syncs name, status, tint)
- Current turn at top, overflow hidden via baseOpacity + showname
- Updates on turnorder change
- Delete any piece = toggle off
- !gaslight hud initiative [on|off|reset]
…tching

- Increased padding to 30 for nameplate space
- Custom turns rendered as pins (square, transparent, title for name)
- Pins moved off-screen (-5000) when overflowing frame
- Hybrid diff: tokens kept (lerp), pins count-diffed
- Reflow updates initiative text values + pin titles
- Custom entry matching by pr value (prevents text swaps)
- Direction-aware reflow passed from turn order handler
- Destroy handlers for pin/graphic/path/text
- Forward/backward: shift all custom pin/text by one slot (no matching needed)
- Full reflow (sort/add/remove): pr-value matching fallback
- Much simpler, eliminates text swap glitch on turn advance
- Switch frame from path to pathv2 (rec shape, two-point format)
- Fix frame dimension reading (x/y + points)
- Pin Y offset helper (hudPinY) for bottom-middle anchor
- hudSlotY helper for consistent position calculation
- INIT_HUD_EDGE_PADDING (15px) for top/bottom frame inset
- INIT_HUD_H_PADDING (10px) for frame width
- Default frame fits 5 tokens (5*50 + 4*30 + 2*15 = 400px)
- Pin shape: circle, scale: 2.0
- Fix double-offset bug in direction shift
…tion

- Rotation-based direction detection (anchor on first non-custom token)
- Detect direction BEFORE skip/reorder modifies newOrder
- Custom text wraps circularly: min wraps to max position (forward), max wraps to min (backward)
- Text position is source of truth for pin visibility
- Fixes custom pin/text disappearing and not coming back
- Token size derived from frame width (frameWidth - 2*hPadding)
- Frame resize narrower: reduce hPadding first (min 5), then shrink tokens
- Frame resize wider: increase hPadding
- Token resize: frame width adjusts to fit (hPadding preserved)
- Frame move/resize persists to state
- Tokens resize during reflow (width/height set)
- Rename: INIT_HUD_PADDING -> INIT_HUD_TOKEN_PADDING, INIT_HUD_EDGE_PADDING -> INIT_HUD_V_PADDING
- Replace INIT_HUD_* constants with defaultInitHud object
- Reset uses Object.assign({}, defaultInitHud) for clean slate
- All sizing/padding reads from data.* with defaultInitHud fallback
- Text font_size and font_family adjustable (GM changes one, all follow)
- Text X offset stored relative to frame right edge
- Frame width read from actual path points (not computed)
- hudSlotY/hudPinY accept tokenPadding param
- Remove debug logs
…oke_width

- Text: color, stroke (glow), font_size, font_family all adjustable + persist
- Frame: stroke, fill, stroke_width adjustable + persist
- isdrawing=true on HUD tokens (no token menu/grid snap)
- tooltipVisibleTo='' on pins (no tooltip popup)
- All styling propagates to sibling elements on change
- Stroke/color set to transparent when text is hidden (overflow)
- defaultViewHud object: leftNorm, top, fontSize, fontFamily, color, stroke
- leftNorm: normalized 0-1 X position (stays centered on page resize)
- All styling persists in state.hud.viewData
- Reset clears viewData, restores all defaults
- Matches initiative HUD pattern (change detection, propagation)
- Toggle word before/after element: 'hud reset init' = 'hud init reset'
- No-args toggles all elements, single toggle word applies to all
- Reset turns all elements on + restores defaults
- Aliases: init/turn/turns -> initiative, relay -> view
- Drag HUD token vertically to reorder initiative (moves linked group)
- Drag only detected if token wasn't resized (corner resize safety)
- change:pin handler detects vertical drag on HUD pins
- Reorders custom turn entry in full turn order
- Uses text position as source of truth for current slot index
- Pin Y offset accounted for in target slot calculation
…= HUD off)

- Delete HUD token: removes entry + linked children from turn order, reflows
- Delete HUD pin: removes custom turn from turn order, reflows
- Delete HUD text: same behavior (removes associated token/pin + turn order entry)
- Delete frame: still turns initiative HUD off entirely
- Associated text/token cleaned up on either deletion
- Drag token/pin past frame edge horizontally = rotate turn order to that entry
- Vertical drift guard: horizontal swipe only if vertical movement < half token size
- Horizontal escape guard: vertical reorder only if token stays within frame
- Works for both graphic tokens and custom pins
- Current turn positioned at frame center (not top)
- Past turns above center, future turns below
- Offset-based positioning (hudSlotY uses offset from center)
- Yellow highlight rectangle on current turn slot
- Fix: deduplicate linkedIds before adding to turn order
- Fix: don't add '-1' to placed set in reorderInitiative (allows multiple custom turns)
- Fix: alreadyHasLinked guard prevents cascade additions
…ixes

- Apply custom turn formula when reaching top via API rotation
- Inverse formula on backward direction
- Only apply if our code modified the order (no double-apply with Roll20)
- Update custom text pr values in direction shift path
- Horizontal swipe: right=forward, left=backward with formula application
- Known issue: current-turn swipe and pin backward rotation need fixing
- Current turn swipe: advance/retreat past linked children (not no-op)
- Formula applies when custom ENTERS top (not when leaving)
- Pin horizontal swipe: removed isCurrentTurn gate, added targetFullIdx=0 handling
- Pin vertical vs horizontal: use horizontalEscapePin flag instead of early return
- Fix duplicate var declarations in pin handler
- Fix missing 's' variable in doSplit
- Fix stray brace in pin handler
- Tighten formula check in onTurnOrderChanged (compare custom+pr to old top)
…ity, tweaks

- Highlight: 45deg rotation, stroke width 5, tokenSize+15, customizable styling
- Moving highlight vertically sets current turn Y position (normalized 0-1)
- Slot-based visibility: count actual slots that fit above/below indicator
- Token padding default: 20px (token+padding = 70px = 1 grid cell)
- Frame default: 5.5 tokens tall for easier indicator movement
- Pin scale: 1.75
- Text offset: 25px
- Highlight delete = just clear ID (recreated on next update, doesn't turn off HUD)
- slotsAbove/slotsBelow computed from actual positions, not Math.floor
@KenanMillet KenanMillet changed the title Gaslight v2.1.0 Gaslight v2.1.0 — Initiative Tracking, HUD System, Sync Commands Jul 3, 2026
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.

1 participant