Vampire-Act-Base/docs/architecture/adr-004.md

91 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-004: Form Switch State Machine Design
**Status**: Accepted
**Date**: 2026-04-27
**Engine**: Unity 2022.3.62f3c1
**GDD Requirements Addressed**: Form Switch State Machine (systems-index.md #3)
---
## Context
Form switching is Nightborn's core operation — every switch is a risky commitment action. The state machine must balance "responsive feel" against "decisions have weight." It must also support future switch-speed upgrades from the Skill Tree.
## Decision
### Four-Phase Linear State Machine
```
RequestSwitch(Wolf)
Idle ─────────────────────────────→ Windup
↑ │
│ timer >= recovery │ timer >= windup
│ │
│ ┌─────────────────────────────┐ │
│ │ Hit during Windup → │←──│
│ │ OnSwitchInterrupted │ │
│ └─────────────────────────────┘ ↓
│ Switching (i-frames)
Recovery ←───────────────────────────┘
timer >= switch
```
### Phase Parameters (baseline, modifiable by Skill Tree)
| Phase | Duration | Can Act | Interruptible | Can Re-Switch |
|-------|----------|---------|---------------|---------------|
| **Idle** | — | Full | — | — |
| **Windup** | 0.25s | Cannot attack | Yes (hit → lose Blood Energy) | No |
| **Switching** | 0.10s | Cannot act | No (i-frames) | No |
| **Recovery** | 0.15s | Can attack/move | No | No |
**Total switch time**: 0.50s. Danger window: 0.25s (Windup).
### Interrupt Rules
- Hit during Windup → `OnSwitchInterrupted` → Blood Energy already spent, switch fails → return to Idle
- This IS the "switched at the wrong time" punishment — core to the Switch is Commitment pillar
### Post-Switch Cooldown
After Recovery ends, an additional 0.3s cooldown before another switch is allowed (minimum 0.8s between switches) — prevents switch spam and preserves rhythmic feel.
### Implementation
```csharp
// L0 — Pure C#, zero Unity
public class FormSwitchStateMachine
{
public FormType CurrentForm { get; private set; } = FormType.Human;
public SwitchPhase Phase { get; private set; } = SwitchPhase.Idle;
public float PhaseTimer { get; private set; }
// Tunable (Skill Tree can modify)
public float WindupDuration = 0.25f;
public float SwitchDuration = 0.10f;
public float RecoveryDuration = 0.15f;
public float CooldownDuration = 0.3f;
public SwitchResult RequestSwitch(FormType target, BloodEnergyEconomy energy);
public void Update(float deltaTime);
public void Interrupt();
public event Action<FormType, FormType> OnFormChanged;
public event Action<SwitchPhase> OnPhaseChanged;
public event Action<FormType> OnSwitchInterrupted;
}
```
### Why a Simple Linear FSM
- 4 phases progress sequentially — no Hierarchical FSM or Behavior Tree needed
- Only Idle accepts input — logic is straightforward for external developers
- If a future form needs a different flow, it can subclass with its own state machine
## Consequences
- Switch feel is controlled by exactly 4 parameters (WindupDuration, SwitchDuration, RecoveryDuration, CooldownDuration) — tuning is centralized
- Interrupt during Windup creates clear "wrong time to switch" punishment, reinforcing Switch is Commitment
- Skill Tree can directly modify these 4 parameters for switch-speed upgrades
- Windup duration (0.25s) is the critical feel parameter — MUST be validated through prototype, likely iterating between 0.15s0.35s