# 131 — State Gating Table (`DA_StateGatingTable`)

> **⚡ C++ Status: Stub** — `Source/PG_Framework/Public/State/DA_StateGatingTable.h` provides the `FStateGatingRule` struct (ActionTag, BlockedByState, bIsBlocked) and `IsActionGated()` query. **Create a Data Asset instance** (Right-click → Miscellaneous → Data Asset → `DA_StateGatingTable`). Populate `GatingRules` with 37 rules. The C++ `BPC_StateManager` reads this asset — no BP logic to build. Designers modify gating rules in this Data Asset without touching code. See `docs/developer/cpp-integration-guide.md`.
>
> ---

## Purpose
Data Asset that holds all state gating rules for the framework. Loaded by `BPC_StateManager` on BeginPlay to populate its `GatingRules` array. Designers modify gating rules entirely through this Data Asset — no blueprint changes required to add, remove, or tweak which states block which actions.

## Dependencies
- **Requires:** `BPC_StateManager` (130 — loads this DA during Initialize), `E_PlayerActionState` (defined in BPC_StateManager), `S_StateGatingRule` (struct defined in BPC_StateManager), `E_GamePhase` (defined in GI_GameFramework / GS_CoreGameState)
- **Required By:** `BPC_StateManager` (130 — direct consumer), Design Team (primary editor target)
- **Engine/Plugin Requirements:** GameplayTags plugin

## Class Info
| Property | Value |
|----------|-------|
| **Parent Class** | `PrimaryDataAsset` |
| **Class Type** | Data Asset |
| **Asset Path** | `Content/Framework/Core/DA_StateGatingTable.uasset` |
| **Implements Interfaces** | *(none)* |

---

## 1. Enums

*Uses enums defined in BPC_StateManager (130) and GI_GameFramework (04):*
- `E_PlayerActionState` — 45 exclusive action states
- `E_GamePhase` — Game phases (MainMenu, InGame, Cutscene, Loading, etc.)

---

## 2. Structs

*Uses struct defined in BPC_StateManager (130):*

### `S_StateGatingRule` (repeated from 130 for reference)
| Field | Type | Description |
|-------|------|-------------|
| `ActionTag` | `GameplayTag` | The action being gated (e.g., `Action.Weapon.Fire`, `Action.Move.Jump`) |
| `BlockedStates` | `Array<E_PlayerActionState>` | States that block this action |
| `BlockedGamePhases` | `Array<E_GamePhase>` | Game phases that block this |
| `RequiredTags` | `GameplayTagContainer` | Tags the player must have |
| `BlockedTags` | `GameplayTagContainer` | Tags the player must NOT have |
| `BlockReason` | `Text` | Reason shown to player when blocked |
| `Priority` | `Integer` | Rule evaluation order (lower = checked first) |

---

## 3. Variables

### Configuration (Instance Editable)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `GatingRules` | `Array<S_StateGatingRule>` | *(see default rules below)* | `State Gating` | All gating rules evaluated at runtime |
| `DefaultStateTransitionDelay` | `Float` | `0.0` | `State Config` | Minimum seconds between state changes (anti-spam) |
| `DefaultInjuryHealthThreshold` | `Float` | `0.30` | `State Config` | Health ratio (0-1) below which player becomes Injured |
| `DefaultHeartRateBase` | `Float` | `70.0` | `State Config` | Base heart rate in BPM when calm |
| `DefaultHeartRateMax` | `Float` | `180.0` | `State Config` | Maximum heart rate in BPM |
| `DefaultState` | `E_PlayerActionState` | `Idle` | `State Config` | Default state on spawn/respawn |
| `DefaultOverlay` | `E_OverlayState` | `Empty` | `State Config` | Default upper-body overlay |

---

## 4. Default Gating Rules — Complete Rule Set

The table below defines the **37 action gating rules** that ship as defaults in this Data Asset. Each row represents one `S_StateGatingRule` entry in the `GatingRules` array.

### Movement Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 1 | `Action.Move.Walk` | Dead, InCutscene, InDialogue, KnockedDown, Panicked, Exhausted, Sitting, InInventory, InJournal, InPauseMenu, UsingObject, GrabbingObject, InPhotoMode | MainMenu, Loading | Movement disabled |
| 2 | `Action.Move.Sprint` | Dead, InCutscene, InDialogue, Crouching, Crawling, Hiding, Peeking, Sitting, KnockedDown, Exhausted, Panicked, Reloading, UsingConsumable, Injured | MainMenu, Loading | Sprint requires standing + uninjured |
| 3 | `Action.Move.Crouch` | Dead, Vaulting, Climbing, Sliding, InCutscene, InDialogue, Sitting, KnockedDown, Exhausted, Panicked | MainMenu, Loading | Cannot crouch during traversal |
| 4 | `Action.Move.Crawl` | Dead, Vaulting, Climbing, InCutscene, Sitting, KnockedDown | MainMenu, Loading | Must be prone first |
| 5 | `Action.Move.Jump` | Dead, Hiding, Peeking, Crawling, InCutscene, InDialogue, Sitting, KnockedDown, Panicked, Exhausted, UsingObject, InInventory, InPauseMenu | MainMenu, Loading | Jump blocked |
| 6 | `Action.Move.Sit` | Dead, Vaulting, Climbing, Hiding, SwingMelee, FiringFirearm, Reloading, KnockedDown, Panicked, InInventory, InCutscene, InDialogue | MainMenu, Loading | Sit requires neutral standing state |
| 7 | `Action.Move.StandUp` | *(none — requires Sitting state, checked in BPC_StateManager)* | MainMenu, Loading | Must be sitting first |

### Traversal Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 10 | `Action.Traversal.Vault` | Dead, Hiding, Peeking, InCutscene, InDialogue, Reloading, SwingMelee, FiringFirearm, KnockedDown, Panicked | MainMenu, Cutscene, Loading | Traversal requires free hands |
| 11 | `Action.Traversal.Climb` | Dead, InCutscene, InDialogue, Reloading, SwingMelee, KnockedDown, Panicked | MainMenu, Cutscene, Loading | Climbing requires free hands |
| 12 | `Action.Traversal.Slide` | Dead, InCutscene, InDialogue, Reloading, SwingMelee, KnockedDown, Panicked | MainMenu, Cutscene, Loading | Slide requires two hands |

### Hiding Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 20 | `Action.Hide.Enter` | Dead, InCutscene, InDialogue, SwingMelee, FiringFirearm, Reloading, Vaulting, Climbing, KnockedDown, Panicked, Exhausted, GrabbingObject | MainMenu, Cutscene, Loading | Hide requires exposed state |
| 21 | `Action.Hide.Peek` | Dead, SwingMelee, FiringFirearm, Reloading | *(none)* | Peek only from hidden |
| 22 | `Action.Hide.Exit` | InCutscene | *(none)* | Forced exit allowed |

### Interaction Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 30 | `Action.Interact.Hold` | Dead, InCutscene, SwingMelee, FiringFirearm, Reloading, Hiding, Peeking, Vaulting, Climbing, KnockedDown, Panicked, InInventory, InPauseMenu, InDialogue, UsingObject | MainMenu, Cutscene, Loading | Interaction requires free state |
| 31 | `Action.Interact.Instant` | Dead, InCutscene, KnockedDown, Panicked | MainMenu, Loading | Instant interaction only blocked by critical |

### Inventory Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 40 | `Action.Inventory.Open` | Dead, InCutscene, Vaulting, Climbing, SwingMelee, FiringFirearm, Reloading, KnockedDown, Panicked, Hiding, GrabbingObject, InDialogue, InPuzzle, InTrialScenario | MainMenu, Cutscene, Loading | Inventory blocked during actions |
| 41 | `Action.Inventory.Close` | *(none)* | *(none)* | Close always works |
| 42 | `Action.Inventory.Equip` | Dead, InCutscene, Vaulting, Climbing, KnockedDown, Panicked | MainMenu, Loading | Equip requires stability |
| 43 | `Action.Inventory.UseItem` | Dead, InCutscene, Vaulting, Climbing, KnockedDown, Panicked, Hiding | MainMenu, Loading | Use requires stable state |

### Weapon Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 50 | `Action.Weapon.Fire` | Dead, Hiding, Peeking, Reloading, Vaulting, Climbing, InCutscene, InDialogue, KnockedDown, Panicked, InInventory, InPauseMenu, UsingConsumable, GrabbingObject | MainMenu, Loading | Cannot fire in these states |
| 51 | `Action.Weapon.Aim` | Dead, Hiding, Peeking, Vaulting, Climbing, InCutscene, InDialogue, KnockedDown, Panicked, InInventory, InPauseMenu, GrabbingObject | MainMenu, Loading | Cannot aim |
| 52 | `Action.Weapon.Reload` | Dead, Hiding, Peeking, Vaulting, Climbing, SwingMelee, InCutscene, InDialogue, KnockedDown, Panicked, InPauseMenu, GrabbingObject | MainMenu, Loading | Cannot reload |
| 53 | `Action.Weapon.Melee` | Dead, Hiding, Peeking, Reloading, Vaulting, Climbing, InCutscene, InDialogue, KnockedDown, Panicked, InInventory, InPauseMenu, GrabbingObject, UsingConsumable | MainMenu, Loading | Cannot melee |
| 54 | `Action.Weapon.Block` | Dead, Reloading, Vaulting, Climbing, InCutscene, KnockedDown, Panicked, Hiding, InInventory, InPauseMenu | MainMenu, Loading | Cannot block |

### Dialogue / Narrative Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 60 | `Action.Dialogue.Start` | Dead, InCutscene, Vaulting, Climbing, SwingMelee, FiringFirearm, Hiding, InInventory, InPauseMenu, Reloading, KnockedDown, Panicked | MainMenu, Cutscene, Loading | Dialogue requires neutral state |
| 61 | `Action.Cutscene.Skip` | *(checked via bCanSkip flag in BPC_CutsceneBridge)* | *(none)* | Must be in cutscene |
| 62 | `Action.HoldBreath` | *(only Hidable states, not Peeking — checked by BPC_HidingSystem)* | *(none)* | Breath hold only while hidden |

### Physics / World Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 70 | `Action.Grab.PhysicsObject` | Dead, InCutscene, Hiding, Vaulting, Climbing, Reloading, SwingMelee, FiringFirearm, KnockedDown, Panicked, InInventory, InPauseMenu | MainMenu, Loading | Grab requires free hands |
| 71 | `Action.Puzzle.Use` | Dead, InCutscene, InDialogue, Vaulting, Climbing, Hiding, SwingMelee, FiringFirearm, Reloading, KnockedDown, Panicked | MainMenu, Loading | Puzzle requires focus |
| 72 | `Action.Consumable.Use` | Dead, InCutscene, Vaulting, Climbing, Hiding, SwingMelee, FiringFirearm, Reloading, KnockedDown, Panicked, InInventory | MainMenu, Loading | Consumable requires free hands |

### UI / Menu Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 80 | `Action.Pause.Open` | InCutscene, Dead, InMainMenu | Loading | Cannot pause in cutscene/death |
| 81 | `Action.Pause.Close` | *(none)* | *(none)* | Close always works |
| 82 | `Action.Journal.Open` | Dead, InCutscene, InDialogue, Vaulting, Climbing, Hiding, SwingMelee, FiringFirearm, Reloading, KnockedDown, Panicked, InInventory, InPuzzle, InTrialScenario | MainMenu, Cutscene, Loading | Journal requires neutral state |
| 83 | `Action.Settings.Open` | *(none)* | Cutscene, Loading | Settings limited during cutscene |
| 84 | `Action.Map.Open` | Dead, InCutscene, Vaulting, Climbing, Hiding, InInventory, InPauseMenu | MainMenu, Loading | Map in neutral/explore states |

### Throwable / Photo Actions

| Priority | ActionTag | BlockedStates | BlockedGamePhases | BlockReason |
|----------|-----------|---------------|-------------------|-------------|
| 90 | `Action.Throwable.Aim` | Dead, Hiding, Peeking, Vaulting, Climbing, InCutscene, InDialogue, Reloading, KnockedDown, Panicked, InInventory, InPauseMenu | MainMenu, Loading | Throw requires free hands |
| 91 | `Action.Throwable.Throw` | Dead, Hiding, Peeking, Vaulting, Climbing, InCutscene, InDialogue, Reloading, KnockedDown, Panicked, InInventory, InPauseMenu | MainMenu, Loading | Must be aiming first |
| 92 | `Action.PhotoMode.Enter` | Dead, InCutscene, InDialogue, Vaulting, Climbing, Hiding, SwingMelee, FiringFirearm, KnockedDown, Panicked | MainMenu, Loading | Photo mode requires neutral state |
| 93 | `Action.PhotoMode.Exit` | *(none — checked by state)* | *(none)* | Must be in photo mode |

---

## 5. Functions

### Public Functions

#### `GetRulesForAction` → `Array<S_StateGatingRule>`
- **Description:** Returns all gating rules that match a given ActionTag. Called by `BPC_StateManager.IsActionPermitted`.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `ActionTag` | `GameplayTag` | The action tag to look up |
- **Blueprint Authority:** Any (Pure)
- **Flow:** Iterates `GatingRules` array, returns all entries where `ActionTag` matches.

#### `GetRuleByPriority` → `S_StateGatingRule`
- **Description:** Returns the highest-priority (lowest Priority value) rule for a given action tag. If multiple rules match, the one with the lowest `Priority` wins.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `ActionTag` | `GameplayTag` | The action tag to look up |
- **Blueprint Authority:** Any (Pure)

#### `HasAnyBlockedState` → `Boolean`
- **Description:** Returns true if any rule's `BlockedStates` contains the given state. Used for debugging/validation.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `State` | `E_PlayerActionState` | The state to check |
- **Blueprint Authority:** Any (Pure)

---

## 6. Data Asset Edibility Notes

### Designer Workflow
1. Open `DA_StateGatingTable` in the Content Browser
2. Edit the `GatingRules` array directly in the Details Panel
3. Each rule maps one `ActionTag` to its blocked states, blocked game phases, and required/blocked tags
4. Set `Priority` to control evaluation order (lower = checked first)
5. Set `BlockReason` to the text displayed to the player when this action is denied
6. Changes take effect on next `BeginPlay` — no recompilation required

### Adding a New Action
1. Create the `GameplayTag` (e.g., `Action.Weapon.Throw`)
2. Add a new `S_StateGatingRule` entry to the `GatingRules` array
3. Set `ActionTag` to the new tag
4. Populate `BlockedStates` with all states that should prevent this action
5. Set `BlockReason` to a user-facing message
6. Optionally set `RequiredTags` / `BlockedTags` for item/equipment-based gating

### Adding a New State
1. Add the new value to `E_PlayerActionState` enum
2. Update any existing gating rules whose `BlockedStates` should include the new state
3. Optionally create new gating rules that use the new state as a blocker
4. No blueprint changes needed in `BPC_StateManager` — it reads `GatingRules` dynamically

---

## 7. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| `BPC_StateManager` (130) | `Direct: Load Data Asset` on BeginPlay | Reads entire `GatingRules` array |
| `BPC_StateManager` (130) | `Function Call: GetRulesForAction` | Queries rules by `GameplayTag` |
| Design Team | Data Asset Editor | Edits `GatingRules`, `DefaultStateTransitionDelay`, thresholds |

---

## 8. Validation / Testing Checklist

- [ ] Data Asset loads correctly in `BPC_StateManager.BeginPlay`
- [ ] All 37 default gating rules are present in the array
- [ ] Each rule has a non-empty `ActionTag`
- [ ] Each rule with `BlockedStates` has at least one state
- [ ] Each rule has a non-empty `BlockReason` text
- [ ] Priority values are correctly ordered (movement=1-9, traversal=10-19, hiding=20-29, etc.)
- [ ] No duplicate `ActionTag` entries with the same `Priority` (ambiguity)
- [ ] `DefaultStateTransitionDelay` > 0 prevents rapid-fire state changes
- [ ] `DefaultInjuryHealthThreshold` between 0.0 and 1.0
- [ ] `DefaultHeartRateBase` < `DefaultHeartRateMax`
- [ ] Edge case: Empty `GatingRules` array → `BPC_StateManager` falls back to blueprint-default rules
- [ ] Edge case: Null `ActionTag` in a rule → skipped with warning log

---

## 9. Reuse Notes

- This Data Asset is the **designer-facing interface** to the entire state gating system. No blueprint access required.
- Multiple `DA_StateGatingTable` instances can exist for different game modes or difficulty levels (e.g., `DA_StateGatingTable_Hardcore`, `DA_StateGatingTable_Easy`).
- The `Priority` field in `S_StateGatingRule` controls evaluation order. Use standard ranges: Movement=1-9, Traversal=10-19, Hiding=20-29, Interaction=30-39, Inventory=40-49, Weapons=50-59, Narrative=60-69, Physics=70-79, UI=80-89, Throwable/Photo=90-99.
- `BlockedGamePhases` allows cutting off actions globally during MainMenu, Cutscene, and Loading without per-state rules.
- `RequiredTags` and `BlockedTags` enable item/equipment-based gating beyond state checking (e.g., "Sprint requires Tag.Equipment.NotExhausted").
- The `BlockReason` text is displayed directly to the player via `WBP_InteractionPromptDisplay` — use clear, localized strings.

---

*Blueprint Spec: DA_StateGatingTable — Designer-editable gating rules Data Asset. Reference architecture document: [`bpc-statemanager.md`](../../architecture/bpc-statemanager.md) Section 9.*
