Add UI Overrides and Weapons Index documentation for Project Void
- Created ui-overrides.md detailing game-specific Widget Blueprint overrides, including purpose, widget index, visual styling, and accessibility requirements. - Established weapons-index.md outlining all held weapon actors, including their components, logic, and comparisons for gameplay mechanics.
This commit is contained in:
287
docs/game/state-gating-examples.md
Normal file
287
docs/game/state-gating-examples.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# State Gating Examples — Game-Specific State Rules
|
||||
|
||||
**Game:** Project Void | **Build Phase:** 14 (Data Asset configuration)
|
||||
**Framework Systems:** 130_BPC_StateManager, 131_DA_StateGatingTable
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines game-specific state gating rules added to `DA_StateGatingTable` (131). These rules determine what actions are permitted in each game state. Designers can modify these without touching any Blueprint code.
|
||||
|
||||
---
|
||||
|
||||
## How State Gating Works (Quick Refresher)
|
||||
|
||||
```
|
||||
Any system that wants to perform an action:
|
||||
|
||||
Actor → BPC_StateManager.IsActionPermitted(ActionTag)
|
||||
│
|
||||
├─ StateManager checks DA_StateGatingTable for rule matching ActionTag
|
||||
├─ Rule specifies which states BLOCK this action
|
||||
├─ If current state matches blocked state:
|
||||
│ └─ Return { bPermitted = false, BlockReason = "Cannot [Action] — [Reason]" }
|
||||
└─ If current state doesn't match:
|
||||
└─ Return { bPermitted = true }
|
||||
|
||||
Result struct: S_ActionPermissionResult
|
||||
├─ bPermitted: Boolean
|
||||
├─ BlockReason: FText (shown to player via InteractionPromptDisplay)
|
||||
└─ BlockingState: GameplayTag (for debug/logging)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Framework Default Rules (from DA_StateGatingTable, 37 rules)
|
||||
|
||||
These come from the framework and apply to **all** games:
|
||||
|
||||
| Action | Blocked By |
|
||||
|--------|-----------|
|
||||
| `Move` | Death, Cutscene, Loading, Exhausted |
|
||||
| `Look` | Cutscene, Loading |
|
||||
| `Interact` | Death, Cutscene, Loading, Hiding, Reloading |
|
||||
| `Fire` | Death, Cutscene, Loading, Hiding, Reloading, Exhausted, Sprinting |
|
||||
| `Reload` | Death, Cutscene, Loading, Hiding, Exhausted |
|
||||
| `Sprint` | Death, Cutscene, Loading, Crouching, Exhausted |
|
||||
| `Crouch` | Death, Cutscene, Loading, Sprinting |
|
||||
| `Jump` | Death, Cutscene, Loading, Crouching |
|
||||
| `Equip` | Death, Cutscene, Loading, Hiding, Reloading |
|
||||
| `UseItem` | Death, Cutscene, Loading, Hiding |
|
||||
| `Hide` | Death, Cutscene, Loading, Sprinting, Exhausted, InCombat |
|
||||
| `Pause` | Death, Cutscene, Loading, AltDeathSpace |
|
||||
| ... | (30+ more rules — see 131_DA_StateGatingTable.md) |
|
||||
|
||||
---
|
||||
|
||||
## Game-Specific Rules (Project Void)
|
||||
|
||||
These are added on top of the framework defaults. They represent horror-game-specific restrictions.
|
||||
|
||||
### 1. Combat Rules
|
||||
|
||||
| Action Tag | Blocked By | Block Reason | Notes |
|
||||
|-----------|-----------|-------------|-------|
|
||||
| `Fire` | `State.InVoidSpace` | "Your weapon has no power here." | Weapons don't work in void space |
|
||||
| `Fire` | `State.Catatonic` | "Your hands shake too much to aim." | Stress 100 = can't shoot |
|
||||
| `Reload` | `State.InVoidSpace` | "Ammunition is meaningless in the void." | Void space blocks reload |
|
||||
| `Melee` | `State.InVoidSpace` | "You swing at shadows." | Melee also useless in void |
|
||||
|
||||
### 2. Void Space Rules
|
||||
|
||||
| Action Tag | Blocked By | Block Reason | Notes |
|
||||
|-----------|-----------|-------------|-------|
|
||||
| `Interact` | `State.VoidShiftActive` | "Reality is unstable. Nothing responds correctly." | During void shift events, interaction is unreliable (50% chance success) |
|
||||
| `Move` | `State.VoidParalyzed` | "The void holds you still." | Scripted moments where player is frozen |
|
||||
| `Pause` | `State.AltDeathSpace` | "There is no escape from the void." | No pause menu in void space |
|
||||
| `OpenInventory` | `State.AltDeathSpace` | "Your belongings feel distant here." | No inventory in void space |
|
||||
| `UseItem` | `State.AltDeathSpace` | "Items from your world have no effect." | Can't use consumables in void space |
|
||||
|
||||
### 3. Horror-Specific Rules
|
||||
|
||||
| Action Tag | Blocked By | Block Reason | Notes |
|
||||
|-----------|-----------|-------------|-------|
|
||||
| `Sprint` | `State.Exhausted` | "You're too exhausted to run." | After stamina depleted for 3+ seconds |
|
||||
| `Sprint` | `State.Catatonic` | "Your body won't obey." | Stress 100 = no sprint |
|
||||
| `Interact` | `State.InCombat` | "Too dangerous! Find cover first." | Can't search drawers while enemy is attacking |
|
||||
| `Hide` | `State.InCombat` | "Hide quickly before they see you!" | Transition period of 2s after combat starts, then allowed |
|
||||
| `Hide` | `State.Catatonic` | "You can't think clearly enough to hide." | Stress 100 = can't hide |
|
||||
| `Flashlight` | `State.Exhausted` | "Your arm is too weak to hold the light." | Exhausted state dims flashlight to 25% instead of blocking |
|
||||
| `OpenWatch` | `State.Hiding` | — | **ALLOWED** (override framework block) — can check inventory while hiding |
|
||||
|
||||
### 4. Narrative/Dialogue Rules
|
||||
|
||||
| Action Tag | Blocked By | Block Reason | Notes |
|
||||
|-----------|-----------|-------------|-------|
|
||||
| `All` (wildcard) | `State.InDialogueChoice` | "Make your choice." | ALL actions blocked during dialogue choice |
|
||||
| `Move` | `State.InDialogueChoice` | "You stand before the entity, frozen." | Can't walk away mid-choice |
|
||||
| `Equip` | `State.InCutscene` | — | Framework default already blocks |
|
||||
| `Pause` | `State.InEndingSequence` | "This moment cannot be paused." | Ending cutscene blocks pause |
|
||||
|
||||
### 5. Death State Rules
|
||||
|
||||
| Action Tag | Blocked By | Block Reason | Notes |
|
||||
|-----------|-----------|-------------|-------|
|
||||
| `All` (wildcard) | `State.Dead` | "You are dead." | ALL actions blocked |
|
||||
| `Pause` | `State.Dead` | "Press Continue to respawn." | Pause menu blocked on death screen (death screen is the menu) |
|
||||
| `Look` | `State.Dead` | — | **ALLOWED** (override) — camera still follows ragdoll briefly |
|
||||
|
||||
---
|
||||
|
||||
## DA_StateGatingTable Game-Specific Configuration
|
||||
|
||||
### How to Add These Rules in UE5
|
||||
|
||||
1. Open `DA_StateGatingTable` (Content/Framework/State/)
|
||||
2. **Duplicate** it → `DA_StateGatingTable_Horror` (Content/Game/DataAssets/)
|
||||
3. The framework `DA_StateGatingTable` has 37 base rules. The game-specific table **inherits** them.
|
||||
4. Add new entries for game-specific rules.
|
||||
|
||||
**Rule: NEVER modify `DA_StateGatingTable` in Framework/. Use your game copy.**
|
||||
|
||||
### Rule Entry Structure
|
||||
|
||||
```
|
||||
S_StateGatingRule (struct):
|
||||
├─ ActionTag: GameplayTag (e.g., Framework.Action.Fire)
|
||||
├─ BlockedStateTags: Array<GameplayTag> (e.g., State.InVoidSpace)
|
||||
├─ BlockReason: FText (shown to player)
|
||||
├─ Priority: Int32 (higher = overrides lower priority rules)
|
||||
└─ bOverrideFramework: Boolean (true = replaces framework rule for this action)
|
||||
```
|
||||
|
||||
### Example Entry: Block Fire in Void Space
|
||||
|
||||
```
|
||||
ActionTag: Framework.Action.Fire
|
||||
BlockedStates: [State.InVoidSpace, State.AltDeathSpace]
|
||||
BlockReason: "Your weapon has no power here."
|
||||
Priority: 100
|
||||
OverrideFramework: false (ADD to framework blocks, not REPLACE)
|
||||
```
|
||||
|
||||
### Example Entry: ALLOW Interact During Hiding (Override)
|
||||
|
||||
```
|
||||
ActionTag: Framework.Action.OpenWatch
|
||||
BlockedStates: [] (empty = no blocks = ALWAYS permitted)
|
||||
BlockReason: ""
|
||||
Priority: 200 (HIGHER than framework default)
|
||||
OverrideFramework: true (REPLACE framework rule — framework blocks OpenWatch during Hiding)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Runtime State Management (BPC_StateManager Integration)
|
||||
|
||||
### Force Push States (Scripted Moments)
|
||||
|
||||
```
|
||||
States that are force-pushed by game systems:
|
||||
|
||||
BPC_CutsceneBridge → ForcePushState(InCutscene)
|
||||
└─ Blocks: All actions except SkipCutscene
|
||||
|
||||
BPC_DeathHandlingSystem → ForcePushState(Dead)
|
||||
└─ Blocks: All actions
|
||||
|
||||
BPC_VoidShiftSystem → ForcePushState(VoidShiftActive)
|
||||
└─ Blocks: Fire, Reload, Melee, Interact(50%)
|
||||
|
||||
BPC_DialogueChoiceSystem → ForcePushState(InDialogueChoice)
|
||||
└─ Blocks: All actions except dialogue input
|
||||
|
||||
BPC_StressSystem (at Catatonic) → ForcePushState(Catatonic)
|
||||
└─ Blocks: Fire, Sprint, Hide
|
||||
```
|
||||
|
||||
### Overlay States (Simultaneous)
|
||||
|
||||
```
|
||||
States that layer on top of base state:
|
||||
|
||||
BPC_HidingSystem → SetOverlayState(Hiding)
|
||||
└─ Blocks: Fire, Reload, Sprint, Jump
|
||||
└─ Allows: Look, Interact (exit hide), Crouch
|
||||
|
||||
BPC_EquipmentSlotSystem → SetOverlayState(Aiming)
|
||||
└─ Blocks: Sprint, Jump
|
||||
└─ Allows: Fire (with ADS bonus), Reload, Crouch
|
||||
|
||||
BPC_StaminaSystem → SetOverlayState(Exhausted)
|
||||
└─ Blocks: Sprint, Jump
|
||||
└─ Allows: Move (walk only), Interact, Fire
|
||||
```
|
||||
|
||||
### Vital Signals (BPC_StateManager tracks)
|
||||
|
||||
```
|
||||
BPC_StateManager.UpdateVitalSignals() is called every 0.5s:
|
||||
|
||||
E_PlayerVitalSignals:
|
||||
├─ Normal → Health > 50 AND Stress < 50 AND Stamina > 30
|
||||
├─ Wounded → Health < 50
|
||||
├─ Stressed → Stress > 50
|
||||
├─ Exhausted → Stamina < 20
|
||||
└─ Critical → Health < 25 OR Stress > 90
|
||||
|
||||
Systems read vital signals to modify behavior:
|
||||
├─ WBP_DiegeticHUDFrame → changes health bar color per signal
|
||||
├─ SS_AudioManager → modifies heartbeat audio parameter
|
||||
├─ BPC_CameraStateLayer → adjusts FOV and blur per signal
|
||||
└─ BPC_MemoryDriftSystem → increases hallucination intensity
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GASP Liaison (Movement ↔ State)
|
||||
|
||||
### Movement State → Action State Mapping
|
||||
|
||||
```
|
||||
BPC_MovementStateSystem reports movement mode to BPC_StateManager:
|
||||
|
||||
MovingMode.Walking → State.Walking
|
||||
MovingMode.Sprinting → State.Sprinting
|
||||
MovingMode.Crouching → State.Crouching
|
||||
MovingMode.Falling → State.Falling (no jump/equip actions)
|
||||
MovingMode.Swimming → State.Swimming (if water areas added)
|
||||
MovingMode.Ladder → State.Climbing (no fire/equip actions)
|
||||
|
||||
BPC_StateManager enforces:
|
||||
├─ Can't Sprint → if State.Is(Exhausted) OR State.Is(Catatonic)
|
||||
├─ Can't Crouch → if State.Is(Sprinting)
|
||||
└─ Can't Jump → if State.Is(Crouching) OR State.Is(Exhausted)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging State Gating
|
||||
|
||||
### In WBP_DebugMenu → State Viewer tab:
|
||||
|
||||
```
|
||||
Display:
|
||||
├─ Current Action State: "Walking"
|
||||
├─ Current Overlay States: ["Hiding"]
|
||||
├─ Vital Signal: "Wounded"
|
||||
├─ Force Stack Depth: 2
|
||||
│ ├─ [0] InCutscene (pushed by BPC_CutsceneBridge)
|
||||
│ └─ [1] Dead (pushed by BPC_DeathHandlingSystem)
|
||||
│
|
||||
├─ Action Test:
|
||||
│ ├─ [Fire] → BLOCKED: "Cannot Fire — you are in Hiding"
|
||||
│ ├─ [Interact] → BLOCKED: "Cannot Interact — cutscene playing"
|
||||
│ └─ [Look] → PERMITTED
|
||||
│
|
||||
└─ Gating Table Source: DA_StateGatingTable_Horror (Game/DataAssets/)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Blueprint Wiring Checklist
|
||||
|
||||
- [ ] Duplicate `DA_StateGatingTable` → `DA_StateGatingTable_Horror` in `Game/DataAssets/`
|
||||
- [ ] Add all 15+ game-specific gating rules
|
||||
- [ ] Configure `BP_HorrorPlayerCharacter` → BPC_StateManager → set `GatingTable = DA_StateGatingTable_Horror`
|
||||
- [ ] Wire all force-push states (cutscene, death, void shift, dialogue choice, catatonic)
|
||||
- [ ] Wire all overlay states (hiding, aiming, exhausted)
|
||||
- [ ] Wire GASP liaison: MovementState → BPC_StateManager movement update
|
||||
- [ ] Test every blocked action shows correct `BlockReason` in HUD
|
||||
- [ ] Verify `WBP_InteractionPromptDisplay` reads `OnActionDenied` dispatcher
|
||||
|
||||
---
|
||||
|
||||
## Notes for Expansion
|
||||
|
||||
- New states can be added by creating a new **GameplayTag** in `DT_Tags_State.csv`
|
||||
- Designers can add gating rules to `DA_StateGatingTable_Horror` without touching any Blueprint
|
||||
- Priority system allows game rules to override framework rules cleanly
|
||||
- Consider adding **"semi-permitted"** actions: permitted but with penalty (e.g., flashlight dims when exhausted)
|
||||
- Add **per-state camera layers**: each state automatically configures FOV, offset, blur
|
||||
- Multiplayer: state gating is server-authoritative; client requests are validated server-side
|
||||
|
||||
---
|
||||
|
||||
*State Gating Examples for Project Void. See [GAMEINDEX.md](GAMEINDEX.md) for full game structure. See [bpc-statemanager.md](../architecture/bpc-statemanager.md) for full State Manager architecture. See [130_BPC_StateManager.md](../blueprints/16-state/130_BPC_StateManager.md) for State Manager spec.*
|
||||
Reference in New Issue
Block a user