- 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.
11 KiB
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
- Open
DA_StateGatingTable(Content/Framework/State/) - Duplicate it →
DA_StateGatingTable_Horror(Content/Game/DataAssets/) - The framework
DA_StateGatingTablehas 37 base rules. The game-specific table inherits them. - 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_HorrorinGame/DataAssets/ - Add all 15+ game-specific gating rules
- Configure
BP_HorrorPlayerCharacter→ BPC_StateManager → setGatingTable = 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
BlockReasonin HUD - Verify
WBP_InteractionPromptDisplayreadsOnActionDenieddispatcher
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_Horrorwithout 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 for full game structure. See bpc-statemanager.md for full State Manager architecture. See 130_BPC_StateManager.md for State Manager spec.