# 06 — Core GameState (`GS_CoreGameState`)

> **⚡ C++ Status: Full Implementation** — `Source/PG_Framework/Public/Core/GS_CoreGameState.h` provides 5 replicated state variables (ElapsedPlayTime, ActiveChapterTag, ActiveNarrativePhase, bEncounterActive, ActiveObjectiveTags) with `OnRep_` handlers and dispatchers. **Create a BP child** (Blueprint Class → All Classes → `GS_CoreGameState`). No logic to add — all replication works out of the box. Set in `BP_CoreGameMode` → Class Defaults → Classes → `Game State Class`. See `docs/developer/cpp-integration-guide.md`.
>
> ---

## Purpose
The single replicated game state object visible to all players (and potential future co-op clients). Tracks session-level progression data such as elapsed play time, active chapter, narrative phase, encounter activity, and active objectives.

## Dependencies
- **Requires:** `GI_GameFramework` (parent `GameStateBase`), `GameplayTag` system
- **Required By:** `GM_CoreGameMode`, `BPC_EncounterDirector`, `WBP_HUDController`, `WBP_ObjectiveDisplay`
- **Engine/Plugin Requirements:** GameplayTags, Networking (replication stubs)

## Class Info
| Property | Value |
|----------|-------|
| **Parent Class** | `GameStateBase` |
| **Class Type** | Blueprint (GameState) |
| **Asset Path** | `Content/Framework/Core/GS_CoreGameState` |
| **Implements Interfaces** | `I_Persistable` (optional – for persisting elapsed time across saves) |

---

## 1. Enums

No enums defined by this class. Enums consumed:
- `E_GamePhase` (from `GI_GameFramework`) — for phase sync

---

## 2. Structs

No custom structs defined by this class.

---

## 3. Variables

### Configuration (Instance Editable, Expose On Spawn)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| (none) | | | | |

### Internal (Private, No Expose)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `ElapsedPlayTime` | `Float` | `0.0` | Session | Session seconds accumulated across chapters |
| `ActiveChapterTag` | `GameplayTag` | `None` | Session | Current story chapter identifier |
| `ActiveNarrativePhase` | `GameplayTag` | `None` | Session | Sub-chapter narrative phase tag |
| `bEncounterActive` | `Bool` | `false` | Session | Is an AI encounter currently running |
| `ActiveObjectiveTags` | `Array of GameplayTag` | `Empty` | Session | Tags of currently active objectives |

### Replicated (if multiplayer)

| Variable | Type | Condition | Description |
|----------|------|-----------|-------------|
| `ElapsedPlayTime` | `Float` | `Replicated Using OnRep_ElapsedPlayTime` | Replicated session time |
| `ActiveChapterTag` | `GameplayTag` | `Replicated Using OnRep_ActiveChapterTag` | Replicated chapter tag |
| `ActiveNarrativePhase` | `GameplayTag` | `Replicated Using OnRep_ActiveNarrativePhase` | Replicated phase tag |
| `bEncounterActive` | `Bool` | `Replicated Using OnRep_EncounterActive` | Replicated encounter flag |
| `ActiveObjectiveTags` | `Array of GameplayTag` | `Replicated Using OnRep_ActiveObjectiveTags` | Replicated objective list |

---

## 4. Functions

### Public Functions

#### `SetElapsedPlayTime` → `void`
- **Description:** Sets the elapsed play time (called by time-tick timer).
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `NewTime` | `Float` | New elapsed time in seconds |
- **Blueprint Authority:** Server
- **Flow:** Update internal variable, broadcast `OnElapsedPlayTimeUpdated`.

#### `GetElapsedPlayTime` → `Float`
- **Description:** Returns current elapsed play time.
- **Parameters:** None
- **Blueprint Authority:** Any
- **Flow:** Return `ElapsedPlayTime`.

#### `SetActiveChapter` → `void`
- **Description:** Sets the current chapter tag and fires dispatcher.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `ChapterTag` | `GameplayTag` | New chapter identifier |
- **Blueprint Authority:** Server
- **Flow:** Update variable, broadcast `OnChapterChanged`.

#### `GetActiveChapter` → `GameplayTag`
- **Description:** Returns the active chapter tag.
- **Flow:** Return `ActiveChapterTag`.

#### `SetActiveNarrativePhase` → `void`
- **Description:** Sets the sub-chapter narrative phase tag.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `PhaseTag` | `GameplayTag` | New narrative phase |
- **Blueprint Authority:** Server
- **Flow:** Update variable, broadcast `OnNarrativePhaseChanged`.

#### `GetActiveNarrativePhase` → `GameplayTag`
- **Description:** Returns the active narrative phase tag.
- **Flow:** Return `ActiveNarrativePhase`.

#### `SetEncounterActive` → `void`
- **Description:** Sets whether an encounter is currently running.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `bActive` | `Bool` | Encounter active state |
- **Blueprint Authority:** Server
- **Flow:** Update variable, broadcast `OnEncounterActiveStateChanged`.

#### `GetEncounterActive` → `Bool`
- **Description:** Returns encounter active state.
- **Flow:** Return `bEncounterActive`.

#### `AddActiveObjectiveTag` → `void`
- **Description:** Adds an objective tag to the active list.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `ObjectiveTag` | `GameplayTag` | Objective to add |
- **Blueprint Authority:** Server
- **Flow:** Add to array (if not already present), broadcast `OnObjectiveTagsChanged`.

#### `RemoveActiveObjectiveTag` → `void`
- **Description:** Removes an objective tag from the active list.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `ObjectiveTag` | `GameplayTag` | Objective to remove |
- **Blueprint Authority:** Server
- **Flow:** Remove from array, broadcast `OnObjectiveTagsChanged`.

#### `GetActiveObjectiveTags` → `Array of GameplayTag`
- **Description:** Returns the array of active objective tags.
- **Flow:** Return `ActiveObjectiveTags`.

### Protected / Private Functions

#### `OnRep_ElapsedPlayTime` → `void`
- **Description:** Replication notification for `ElapsedPlayTime`.
- **Flow:** Broadcast `OnElapsedPlayTimeUpdated`.

#### `OnRep_ActiveChapterTag` → `void`
- **Description:** Replication notification for `ActiveChapterTag`.
- **Flow:** Broadcast `OnChapterChanged`.

#### `OnRep_ActiveNarrativePhase` → `void`
- **Description:** Replication notification for `ActiveNarrativePhase`.
- **Flow:** Broadcast `OnNarrativePhaseChanged`.

#### `OnRep_EncounterActive` → `void`
- **Description:** Replication notification for `bEncounterActive`.
- **Flow:** Broadcast `OnEncounterActiveStateChanged`.

#### `OnRep_ActiveObjectiveTags` → `void`
- **Description:** Replication notification for `ActiveObjectiveTags`.
- **Flow:** Broadcast `OnObjectiveTagsChanged`.

---

## 5. Event Dispatchers

| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnElapsedPlayTimeUpdated` | `NewTime: Float` | Public | Fires whenever elapsed time changes |
| `OnChapterChanged` | `NewChapterTag: GameplayTag` | Public | Fires when the active chapter changes |
| `OnNarrativePhaseChanged` | `NewPhaseTag: GameplayTag` | Public | Fires when narrative phase transitions |
| `OnEncounterActiveStateChanged` | `bEncounterActive: Bool` | Public | Fires when encounter state toggles |
| `OnObjectiveTagsChanged` | `ActiveTags: Array of GameplayTag` | Public | Fires when objective list changes |

---

## 6. Overridden Events / Custom Events

### Event: `BeginPlay`
- **Description:** Initialise game state defaults and bind to `GI_GameFramework.OnGamePhaseChanged` to reset elapsed time on new game.
- **Flow:**
  1. Call parent `BeginPlay`
  2. Set `ElapsedPlayTime = 0`
  3. Bind to `GI_GameFramework.OnGamePhaseChanged` dispatcher
  4. If `I_Persistable` implemented, register with `SS_SaveSystem`

### Event: `Tick`
- **Description:** Accumulate `ElapsedPlayTime` while game phase is `InGame`.
- **Flow:**
  1. Check `GI_GameFramework.CurrentGamePhase == InGame`
  2. If true: `ElapsedPlayTime += DeltaTime`
  3. If change exceeds 1 second threshold, broadcast `OnElapsedPlayTimeUpdated`

---

## 7. Blueprint Graph Logic Flow

```mermaid
flowchart TD
    A[BeginPlay] --> B[Init variables to 0 / None]
    B --> C[Bind to GI_GameFramework.OnGamePhaseChanged]
    C --> D[Tick - Is GamePhase InGame?]
    D -->|Yes| E[Accumulate ElapsedPlayTime]
    D -->|No| F[Skip time accumulation]
    E --> G[Fire OnElapsedPlayTimeUpdated]
    G --> H[Wait next Tick]
    H --> D
    F --> H

    I[GM_CoreGameMode calls SetActiveChapter] --> J[Update ActiveChapterTag]
    J --> K[Broadcast OnChapterChanged]
    K --> L[UI + Narrative systems react]

    M[BPC_EncounterDirector sets EncounterActive] --> N[Update bEncounterActive]
    N --> O[Broadcast OnEncounterActiveStateChanged]
    O --> P[HUD shows encounter status]

    Q[BPC_ObjectiveSystem adds/removes objective] --> R[Update ActiveObjectiveTags]
    R --> S[Broadcast OnObjectiveTagsChanged]
    S --> T[WBP_ObjectiveDisplay refreshes]
```

---

## 8. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| `GI_GameFramework` | `OnGamePhaseChanged` Dispatcher | Game phase events |
| `GM_CoreGameMode` | Direct method call | `SetActiveChapter`, `SetActiveNarrativePhase` |
| `BPC_EncounterDirector` | Direct method call | `SetEncounterActive` |
| `BPC_ObjectiveSystem` | Direct method call | `AddActiveObjectiveTag`, `RemoveActiveObjectiveTag` |
| `WBP_HUDController` | `OnChapterChanged` / `OnElapsedPlayTimeUpdated` Dispatchers | Chapter and time data |
| `WBP_ObjectiveDisplay` | `OnObjectiveTagsChanged` Dispatcher | Active objective list |
| `BPC_RunHistoryTracker` | Direct read | `ElapsedPlayTime`, `ActiveObjectiveTags` |

---

## 9. Validation / Testing Checklist

- [ ] `BeginPlay` initialises all variables to correct defaults
- [ ] `ElapsedPlayTime` increments only when `GamePhase == InGame`
- [ ] `SetActiveChapter` updates variable and fires `OnChapterChanged`
- [ ] `SetActiveNarrativePhase` updates variable and fires `OnNarrativePhaseChanged`
- [ ] `SetEncounterActive` toggles correctly and fires `OnEncounterActiveStateChanged`
- [ ] `AddActiveObjectiveTag` / `RemoveActiveObjectiveTag` modify array and fire dispatcher
- [ ] Duplicate objective tags are not added twice
- [ ] `OnRep_*` functions fire corresponding dispatchers on clients
- [ ] Edge case: rapid chapter changes in the same tick (dispatchers fire correctly)
- [ ] Edge case: empty objective list and removal from empty list (no crash)
- [ ] Edge case: time accumulation stops correctly on phase change to Paused/Loading

---

## 10. Reuse Notes

- This class is intentionally lightweight. It is a singleton per session.
- For multiplayer: mark all variables `Replicated Using` with `OnRep` notification functions. Currently stubbed as single-player only.
- For save persistence: implement `I_Persistable` to save/restore `ElapsedPlayTime` and `ActiveChapterTag` via `SS_SaveSystem`.
- The `ActiveObjectiveTags` array is read-only for UI. All modification happens through `BPC_ObjectiveSystem` which calls `GS_CoreGameState` methods.
- `bEncounterActive` is written by `BPC_EncounterDirector` and read by UI and adaptive atmosphere controllers.
- No new enums or structs are needed — all data is simple types or `GameplayTag` arrays.
- To add new replicated state (e.g. `bIsInCombat`), follow the same pattern: variable + setter + dispatcher + `OnRep`.

---

## 11. Multiplayer Networking

### Full Replication Map

All 5 state variables are replicated with `OnRep` handlers. GS_CoreGameState is the **primary replicated state bus** — every system that needs shared state writes through this object.

| Variable | Replication | OnRep Handler | Writer (Authority) | Consumer |
|----------|-------------|---------------|---------------------|----------|
| `ElapsedPlayTime` | `Replicated Using` | `OnRep_ElapsedPlayTime` → dispatcher | Tick (server-only) | RunHistoryTracker, HUD |
| `ActiveChapterTag` | `Replicated Using` | `OnRep_ActiveChapterTag` → dispatcher | GM_CoreGameMode | NarrativeSystem, HUD |
| `ActiveNarrativePhase` | `Replicated Using` | `OnRep_ActiveNarrativePhase` → dispatcher | BPC_NarrativeStateSystem | UI, narrative triggers |
| `bEncounterActive` | `Replicated Using` | `OnRep_EncounterActive` → dispatcher | BPC_EncounterDirector | HUD, atmosphere controller |
| `ActiveObjectiveTags` | `Replicated Using` | `OnRep_ActiveObjectiveTags` → dispatcher | BPC_ObjectiveSystem | WBP_ObjectiveDisplay, journal |

### Authority Notes

- **All setter functions are Server-only.** Call with `HasAuthority()` check.
- **All getter functions are Any.** Clients can read replicated state freely.
- **OnRep fires dispatcher** — consumers bind to dispatcher, not variable. Identical SP/MP code path.
- **Tick accumulation** is server-only (ElapsedPlayTime). Clients receive time via OnRep.

### Server RPCs (None)

GS_CoreGameState is a passive state bus. Clients never call RPCs on it directly — they call RPCs on the systems that write to it (e.g. `BPC_ObjectiveSystem.Server_CompleteObjective`).

### Multicast Events (None)

All state changes replicate via standard variable replication + OnRep dispatcher. No separate multicast needed.

### Cross-System Flow (Multiplayer)
```
Client: Player completes objective
  → Server_CompleteObjective RPC on BPC_ObjectiveSystem
  → Server validates completion conditions
  → Server calls GS_CoreGameState.RemoveActiveObjectiveTag
  → Variable replicates to all clients
  → OnRep_ActiveObjectiveTags fires OnObjectiveTagsChanged
  → WBP_ObjectiveDisplay (local per-client) refreshes
```

---

*Blueprint Spec v1.0 — GS_CoreGameState for UE5.5-5.7*