2026-07-03 17:18:00 -04:00
|
|
|
# Initiative Ordering — Design
|
|
|
|
|
|
|
|
|
|
## Core Principle
|
|
|
|
|
|
|
|
|
|
**Slot, never sort.**
|
|
|
|
|
|
|
|
|
|
Initiative order = a single list. Participants occupy slots determined by
|
|
|
|
|
initiative value. The list is mutated by insert/move operations — never
|
|
|
|
|
re-sorted wholesale.
|
|
|
|
|
|
|
|
|
|
## Single Source of Truth
|
|
|
|
|
|
|
|
|
|
One list: `participants[]`.
|
|
|
|
|
|
|
|
|
|
- Display order = `participants[]` order (both Player view + DM view).
|
|
|
|
|
- Turn order = `participants[]` order.
|
|
|
|
|
- No derived/re-sorted copy. `turnOrderIds`, if present, is always an exact
|
|
|
|
|
mirror (`participants.map(p => p.id)`) — never an independent ordering.
|
|
|
|
|
|
|
|
|
|
## When Ordering Changes
|
|
|
|
|
|
|
|
|
|
| Action | Effect on order |
|
|
|
|
|
|--------|-----------------|
|
|
|
|
|
| **Add** (roll or manual) | Insert participant into slot by initiative |
|
|
|
|
|
| **Edit initiative** | Move participant to new slot |
|
|
|
|
|
| **Drag** | Reorder within a tie (same initiative) only |
|
|
|
|
|
| **Remove** | Splice out; others keep position |
|
|
|
|
|
| **Start encounter** | Freeze current list. No re-sort. |
|
|
|
|
|
| **Round wrap** | No rebuild. Continue rotation through existing list. |
|
|
|
|
|
| **Damage/heal/death/save** | No order change. |
|
2026-07-06 10:31:46 -04:00
|
|
|
| **Toggle active** | No position change. Does **not** advance current turn. Skip on next explicit turn advance only. |
|
2026-07-03 17:18:00 -04:00
|
|
|
|
|
|
|
|
## Slotting Rules
|
|
|
|
|
|
|
|
|
|
- Insert/move positions participants so the list stays initiative-descending.
|
|
|
|
|
- **Tie-break = original add order.** Later additions slot *after* existing
|
|
|
|
|
same-init participants. Stable insertion.
|
|
|
|
|
- Tie order is only changed by explicit DM drag. Never auto-changed.
|
|
|
|
|
|
|
|
|
|
## Drag (DM Tie-Break Override)
|
|
|
|
|
|
|
|
|
|
- Only participants with the **same initiative** are draggable onto each other.
|
|
|
|
|
- Cross-initiative drag is **not allowed**. (Use edit-initiative field instead.)
|
|
|
|
|
- Drag persists in `participants[]`. Survives all subsequent operations.
|
|
|
|
|
- **Re-slotting on add/edit must preserve drag-established tie order.**
|
|
|
|
|
|
2026-07-06 10:31:46 -04:00
|
|
|
## Toggle Active Semantics
|
|
|
|
|
|
|
|
|
|
Toggle active is a roster/status edit, not a turn action.
|
|
|
|
|
|
|
|
|
|
- Deactivating the current participant leaves `currentTurnParticipantId` unchanged.
|
|
|
|
|
- Deactivating the current participant does **not** increment `round`.
|
|
|
|
|
- DM must click Next Turn to pass turn after deactivating current.
|
|
|
|
|
- Next Turn skips inactive participants during rotation.
|
|
|
|
|
- Reactivating a participant restores them to rotation at their existing slot.
|
|
|
|
|
- Toggle active never changes participant position or tie order.
|
|
|
|
|
|
|
|
|
|
Reason: auto-advancing from toggle active makes a status edit count like a turn pass,
|
|
|
|
|
can wrap the round accidentally, and causes double-act/skip drift.
|
|
|
|
|
|
2026-07-03 17:18:00 -04:00
|
|
|
## Explicitly Forbidden
|
|
|
|
|
|
|
|
|
|
- `sort()` on every mutation. Overwrites drag order. Root cause of past drift.
|
|
|
|
|
- Separate display order vs turn order. Causes player/DM divergence.
|
|
|
|
|
- Re-sort on round wrap. Replays rounds, introduces skips.
|
|
|
|
|
- Cross-initiative drag. Contradicts initiative as the primary key.
|
|
|
|
|
- Auto-changing tie order on add/edit. Silently loses DM intent.
|
|
|
|
|
|
|
|
|
|
## Why
|
|
|
|
|
|
|
|
|
|
Sorting is destructive to manual ordering. A stable slot list with drag for
|
|
|
|
|
ties gives deterministic, DM-controllable order that never drifts between
|
|
|
|
|
display surfaces or combat rounds.
|