Files
stickman/plans/PHASE_4_TRIGGER_EVENTS.md
T
ryan f208127917 feat: Implement Phase 4 Trigger Events System
- Added a new event-driven system for reactive storytelling, allowing rules like "When X happens, do Y."
- Introduced TriggerArea class for placeable sensors in the stage.
- Enhanced StickmanRig to emit signals for actions and arrivals.
- Updated StageDirectorVisuals to render rules visually with labels and badges.
- Modified StageSpawner to support spawning TriggerAreas.
- Improved text baseline calculations in speech bubbles and rule labels.
- Added tests for text baseline fixes to ensure proper rendering.
- Documented the implementation plan for Phase 4 in PHASE_4_TRIGGER_EVENTS.md.
- Created a polish plan for Phase 4 in PHASE_4b_POLISH.md.
2026-09-01 08:58:07 -04:00

327 lines
17 KiB
Markdown

# Phase 4: Triggers & Event System — Implementation Plan
## 1. Overview
Phase 4 adds **reactive storytelling** to the Sandbox Stage. While Phase 3a gave directors _sequential_ control (actions in a fixed order), Phase 4 gives them _reactive_ control — **"When X happens, do Y."**
This unlocks:
- **Cross-stickman communication** (Stickman A arrives → Stickman B speaks)
- **Environmental reactions** (Stickman reaches crate → crate explodes)
- **Branching narratives** (Arrive at different waypoints → different reactions)
**Crucially:** Phase 4 **does not** replace or duplicate the Phase 3a Action Queue. Sequential actions for a single stickman (Walk → Wait → Speak → Walk) remain unchanged. Phase 4 adds **cross-object reactivity**.
---
## 2. Core Distinction
| Feature | Phase 3a (Already Works) | Phase 4 (New) |
| ----------------------------------------------- | ------------------------ | -------------- |
| Walk → Wait → Speak → Walk | ✅ Action Queue | ✅ (unchanged) |
| Waypoint → next action | ✅ Action Runner | ✅ (unchanged) |
| **Stickman A arrives → Stickman B speaks** | ❌ | ✅ NEW |
| **Stickman collides with prop → prop explodes** | ❌ | ✅ NEW |
| **Stickman enters area → all stickmen react** | ❌ | ✅ NEW |
| **Multiple reactions per event** | ❌ | ✅ NEW |
---
## 3. The User's Mental Model
The director should think of events as **"When → Then"** rules that exist _alongside_ the action queues.
- **Action Queue:** "Stickman A walks to the crate, waits, then speaks."
- **Event Rule:** "When Stickman A reaches the crate, Stickman B says 'Welcome!'"
The event rule is **not** part of Stickman A's queue. It's a separate rule that watches Stickman A and reacts independently.
---
## 4. Milestone Breakdown
| # | Milestone | Description |
| --- | --------------------------- | ------------------------------------------------------- |
| 4.1 | **Event Data Model** | Define rule structure and storage. |
| 4.2 | **Trigger System** | Detect and emit events from stickmen, props, and areas. |
| 4.3 | **Event Rule UI** | Visual rule builder (When → Then workflow). |
| 4.4 | **Trigger Areas** | Placeable `Area2D` sensors. |
| 4.5 | **Prop Interaction Events** | Prop collisions emit events. |
| 4.6 | **Chain Reactions** | Multiple actions per rule, executed in sequence. |
| 4.7 | **Integration & Polish** | Full end-to-end testing, bug fixes, UI polish. |
---
## 5. Milestone 4.3: Event Rule UI
### 5.1. The "When..." Option
```
The existing action popup is extended with a new section:
┌─────────────────────────────────────────────┐
│ 🚶 Walk To │
│ 💬 Speak │
│ ⏳ Wait │
│ 💥 Ragdoll │
│ 🔄 Recover │
│ ───────────────────────────────────────── │
│ ⚡ When... (opens trigger sub-menu) │
└─────────────────────────────────────────────┘
```
**Design note:** The "When..." option is visually separated (line divider) to signal it creates a _rule_, not a direct action.
### 5.2. Trigger Sub-Menu
```
When "When..." is clicked, the popup expands/replaces with trigger types:
┌─────────────────────────────────────────────┐
│ 📍 Arrives at a waypoint │
│ ✅ Completes any action │
│ 💬 Finishes speaking │
│ 🎯 Enters trigger area │
│ 💥 Collides with something │
│ ⬅ Back to actions │
└─────────────────────────────────────────────┘
```
Each trigger type corresponds to a signal emitted by stickmen or the stage.
### 5.3. The Rule Building Flow (6 Stages)
```
┌──────────────┐
│ STAGE 1 │ → User clicks stickman → popup opens
│ IDLE │
└──────┬───────┘
│ Click "When..."
┌──────────────┐
│ STAGE 2 │ → User selects trigger type
│ SELECT_TRIGGER│
└──────┬───────┘
│ (If trigger needs a target: waypoint, area, prop)
┌──────────────┐
│ STAGE 3 │ → User clicks the specific target
│ TARGET_ENTRY │ (e.g., a waypoint dot on the stage)
└──────┬───────┘
┌──────────────┐
│ STAGE 4 │ → User selects the action (Speak, Walk, etc.)
│ SELECT_ACTION│
└──────┬───────┘
│ (If action needs a target: a stickman or prop)
┌──────────────┐
│ STAGE 5 │ → User clicks the target stickman/prop
│ TARGET_ENTRY2│
└──────┬───────┘
│ (If action needs params: text, duration, etc.)
┌──────────────┐
│ STAGE 6 │ → User fills in params
│ PARAMS │
└──────┬───────┘
┌──────────────┐
│ STAGE 7 │ → Rule is stored. Visuals update.
│ DONE │
└──────────────┘
```
**Escape** at any stage cancels rule creation and returns to IDLE.
---
## 6. Complete UI Walkthrough: "A Reaches Waypoint → B Speaks"
### Step 0: Prerequisites (Edit Mode)
- Stickman A and Stickman B are placed on the stage.
- Stickman A already has a **"Walk To"** action queued (with a visible waypoint marker on the stage), OR the user is about to create one.
### Step 1: Create Stickman A's Walk (If Not Done)
| # | User Action | System Response |
| --- | -------------------------------------------------- | ------------------------------------------------------------------------ |
| 1 | Click the **"Direct"** tool button in the palette. | Cursor changes to crosshair. |
| 2 | Click **Stickman A** on the stage. | Action popup appears. |
| 3 | Click **"🚶 Walk To"** in the popup. | Popup closes. Stage enters target placement mode. |
| 4 | Click a spot on the stage. | Blue waypoint dot appears. `walk_to` action added to Stickman A's queue. |
### Step 2: Create the Reactive Event Rule
| # | User Action | System Response |
| --- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| 5 | Click the **"Direct"** tool again (if it was deselected). | Cursor changes to crosshair. |
| 6 | Click **Stickman A** on the stage. | Action popup appears with new "When..." option. |
| 7 | Click **"⚡ When..."** | Trigger sub-menu opens. |
| 8 | Click **"📍 Arrives at a waypoint"** | Popup closes. Cursor changes to target selector. Status bar: _"Click the waypoint you want to trigger on."_ |
| 9 | Click **the blue waypoint dot** on the stage. | Waypoint glows green briefly. Popup reappears with trigger confirmed. |
| 10 | Click **"💬 Speak"** | Popup closes. Cursor changes to target selector. Status bar: _"Click the stickman who will speak."_ |
| 11 | Click **Stickman B** on the stage. | Stickman B glows yellow. Text dialog appears. |
| 12 | Type **"Hello there!"** and click **[OK]** | Dialog closes. Toast: _"Rule created!"_ |
### Step 3: Visual Feedback (Edit Mode)
| Element | Appearance | Description |
| ---------------- | ------------------------------------------- | --------------------------------------- |
| **Dashed line** | White dashed line | Connects waypoint to Stickman B. |
| **Label** | _"When arrives → Speak 'Hello there!'"_ | Centered on the line. |
| **Color coding** | Green waypoint + orange badge on Stickman B | Shows trigger source and action target. |
| **Rule badge** | ⚡ icon on the label | Hover shows full rule details. |
| **Delete icon** | ✕ on the label | Click to remove rule. |
### Step 4: Test in Play Mode
| # | User Action | System Response |
| --- | ------------------------------------- | ----------------------------------------------------------- |
| 13 | Click **"Play"** button. | All queues start executing. |
| 14 | Stickman A walks to waypoint. | Normal Phase 3a behavior. |
| 15 | When Stickman A arrives, event fires. | Stickman B says **"Hello there!"** (speech bubble appears). |
---
## 7. Visual Feedback (Edit Mode Only)
### 7.1. Rule Visualization Elements
| Element | Color/Style | Position |
| ------------------- | ----------------------------- | ---------------------- |
| **Trigger badge** | Green, small, "⚡" | Near source object. |
| **Action badge** | Orange, small, "→" | Near target object. |
| **Connection line** | Dashed white, alpha 0.6 | From source to target. |
| **Label** | White text on dark background | Centered on line. |
| **Waypoint glow** | Green (if trigger source) | On the waypoint dot. |
### 7.2. Rule Interaction
| Action | Behavior |
| --------------------- | ----------------------------------------- |
| **Click rule label** | Opens edit popup for that rule. |
| **Click delete icon** | Removes the rule (confirmation optional). |
| **Hover rule label** | Shows tooltip with full rule details. |
### 7.3. What the User Sees on the Stage
```
Stickman A Stickman B
┌──────┐ ┌──────┐
│ 🔵 │ │ 🔵 │
│ (A) │ │ (B) │
└──┬───┘ └──┬───┘
│ │
│ ════════════╗ │
│ (When arrives) │ │
│ ════════════╝ │
│ ── ── ── ── ── ── ── ── →│
│ (Then Speak "Got it!") │
│ │
┌──┴──────────────────────────────────┐│
│ 📍 Waypoint 3 ││
└──────────────────────────────────────┘
```
---
## 8. Event Data Model
### 8.1. Rule Structure
Rules are stored in the stage's event registry and have three parts:
**Trigger** — The "When" part.
| Trigger Type | Source | Target | Description |
| --------------------- | ------------- | ------------ | ------------------------------------ |
| `arrived_at_waypoint` | Stickman | Waypoint | Stickman completes a walk. |
| `action_finished` | Stickman | Action type | Stickman finishes any action. |
| `speech_finished` | Stickman | (none) | Stickman finishes speaking. |
| `entered_area` | Stickman/Prop | Trigger Area | Object enters a trigger area. |
| `collided` | Stickman/Prop | Object | Object collides with another object. |
**Action** — The "Then" part.
| Action Type | Target | Params |
| -------------- | -------- | ----------------------------------- |
| `walk_to` | Stickman | `target` (Vector2) |
| `speak` | Stickman | `text` (String), `duration` (float) |
| `wait` | Stickman | `duration` (float) |
| `ragdoll` | Stickman | (none) |
| `recover` | Stickman | (none) |
| `explode_prop` | Prop | (none) — future |
| `spawn_prop` | Stage | `type` (String) — future |
### 8.2. Rule Storage
Rules are stored in `SandboxStage._event_rules` and persist across mode toggles (Play ↔ Edit). They are **not** saved to disk in Phase 4 (deferred to Phase 5).
### 8.3. Rule Evaluation
Rules are evaluated **in order** when an event occurs. If a rule's trigger matches the event, its actions are executed.
---
## 9. What's NOT in Phase 4
| Feature | Why Excluded |
| ----------------------------------------------------------- | -------------------------------------------------- |
| "When Stickman A arrives → Stickman A speaks" | This is just a sequential queue action (Phase 3a). |
| "When Stickman A finishes walking → Stickman A walks again" | Same as above. |
| Conditions (AND/OR logic) | Too complex for Phase 4; deferred to future. |
| Variables / counters | Deferred to future. |
| Save/Load rules to disk | Phase 5. |
| Edit/Delete actions | Phase 3c. |
| Stickman/Prop selector grids | Phase 3b. |
---
## 10. Acceptance Criteria
### 10.1. Cross-Stickman Events
- [ ] **"When..." option appears** in the action popup.
- [ ] **Trigger sub-menu opens** when "When..." is clicked.
- [ ] **Waypoint trigger works:** A arrives → B speaks.
- [ ] **Action completion trigger works:** A finishes speaking → B walks.
- [ ] **Speech completion trigger works:** A finishes speaking → B speaks.
- [ ] **Multiple actions per rule work:** Trigger → B speaks AND C walks.
### 10.2. Cross-Object Events
- [ ] **Area trigger works:** A enters area → B speaks.
- [ ] **Prop collision trigger works:** A hits crate → crate explodes.
- [ ] **Prop reaction works:** Trigger → prop explodes (disappears + particles).
### 10.3. UI & Visuals
- [ ] **Rule label shows summary:** "When arrives → Speak" text appears.
- [ ] **Delete icon works:** Click ✕ → rule removed.
- [ ] **Clicking rule label opens edit popup:** Click label → popup re-opens.
- [ ] **Rules persist across mode toggles:** Create rule → Play → Edit → rule still there.
- [ ] **Rules are cleaned up** when source/target objects are deleted.
### 10.4. Backward Compatibility
- [ ] **Sequential actions still work:** Walk → Wait → Speak → Walk works.
- [ ] **Existing queues unchanged:** Any Phase 3a scene loads and runs.
---
## 11. File Changes Summary
| File | Changes |
| ----------------------------------- | ------------------------------------------------------------- |
| `scripts/sandbox_stage.gd` | Add `_event_rules`, event evaluation, rule UI state machine. |
| `scripts/stickman_rig.gd` | Emit `arrived`, `action_finished`, `speech_finished` signals. |
| `scripts/stage_director_visuals.gd` | Draw rule lines, labels, and badges. |
| `scripts/trigger_area.gd` | NEW: Placeable `Area2D` sensor. |
| `scripts/prop_block.gd` | Emit `collided` signal. |
---