# BPC_MemoryDriftSystem — Memory Drift System

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- **Requires:** [`BPC_AdaptiveEnvironmentDirector`](BPC_AdaptiveEnvironmentDirector.md) — Receives drift trigger requests
- **Requires:** [`DA_RoomMutation`](../14-data-assets/DA_RoomMutation.md) — Mutation definitions per room
- **Required By:** World room actors — Mutations applied to specific rooms
- **Required By:** [`GS_CoreGameState`](../01-core/06_GS_CoreGameState.md) — Tracks active mutations per session
- **Engine/Plugin Requirements:** GameplayTags (room tags, mutation tags), Level Streaming

### Purpose
Manages the "room swap" or "memory drift" effect — subtle environmental changes to rooms the player has already visited. Tracks room visit history and triggers mutations (moved objects, changed lighting, new content appearing) based on adaptive director input and story progression.

---

## 1. Enums

*Uses GameplayTags for room and mutation identification. No new enums defined.*

---

## 2. Structs

### `S_RoomVisitData`
| Field | Type | Description |
|-------|------|-------------|
| `RoomTag` | GameplayTag | Identifier for the room/area |
| `VisitCount` | Integer | Number of times player has entered this room |
| `LastVisitTime` | Float | Game time of most recent visit |
| `ActiveMutationTag` | GameplayTag | Currently active mutation in this room (None if unchanged) |

---

## 3. Variables

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

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `MutationRegistry` | Array of DA_RoomMutation | Empty | MutationConfig | Available mutations for all rooms |
| `DriftIntensity` | Float | 0.2 | MutationConfig | Global mutation intensity 0.0–1.0 (0=none, 1=max) |

### Internal (Private / Protected, No Expose)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `VisitedRooms` | Map (GameplayTag → S_RoomVisitData) | Empty | Internal | Per-room visit history |
| `ActiveMutations` | Set of GameplayTag | Empty | Internal | Currently active mutation tags |

---

## 4. Functions

### Public Functions

#### `RegisterRoomVisit` → `void`
- **Description:** Called when the player enters a room. Updates visit count and timestamp.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `RoomTag` | GameplayTag | Room being entered |
- **Blueprint Authority:** Any
- **Flow:** Check if RoomTag in VisitedRooms → if yes, increment VisitCount → if no, create new entry → update LastVisitTime

#### `TriggerDrift` → `void`
- **Description:** Triggers a room mutation for a specific room or the most recently revisited room.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `RoomTag` | GameplayTag | Target room (None = select automatically) |
  | `Intensity` | Float | Override intensity for this drift |
- **Blueprint Authority:** Any
- **Flow:** Select mutation from registry → apply to target room → add to ActiveMutations → broadcast OnDriftTriggered

#### `SelectMutation` → `DA_RoomMutation`
- **Description:** Picks an appropriate mutation for a room based on visit count, drift intensity, and story state.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `RoomTag` | GameplayTag | Room to mutate |
- **Blueprint Authority:** Any
- **Flow:** Filter MutationRegistry by RoomTag → filter by eligibility (visit count >= min visits, drift intensity >= min required) → select highest priority eligible mutation

#### `GetVisitedRooms` → `Array of S_RoomVisitData`
- **Description:** Returns all room visit records for external analysis.
- **Parameters:** None
- **Blueprint Authority:** Any

#### `GetActiveMutations` → `Set of GameplayTag`
- **Description:** Returns all currently active mutation tags.
- **Parameters:** None
- **Blueprint Authority:** Any

#### `ResetRoom` → `void`
- **Description:** Clears mutations from a room, restoring its original state.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `RoomTag` | GameplayTag | Room to reset |
- **Blueprint Authority:** Any

#### `SetDriftIntensity` → `void`
- **Description:** Updates the global drift intensity.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `NewIntensity` | Float | 0.0–1.0 |
- **Blueprint Authority:** Any

---

## 5. Event Dispatchers

| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnDriftTriggered` | RoomTag: GameplayTag, MutationTag: GameplayTag | Public | A room mutation was applied |
| `OnDriftCleared` | RoomTag: GameplayTag | Public | A room's mutations were cleared |
| `OnRoomFirstVisit` | RoomTag: GameplayTag | Public | First time player enters a room |
| `OnRoomRevisit` | RoomTag: GameplayTag, VisitCount: Integer | Public | Player re-enters a previously visited room |

---

## 6. Overridden Events / Custom Events

### Event: `BeginPlay`
- **Description:** Initialises mutation registry from level data and subscribes to room trigger volumes.
- **Flow:**
  1. Load MutationRegistry for current level
  2. Register room trigger volume overlap events
  3. Set initial DriftIntensity from game settings

---

## 7. Blueprint Graph Logic Flow

```mermaid
flowchart TD
    A[Player enters room trigger] --> B[RegisterRoomVisit RoomTag]
    B --> C{First visit?}
    C -->|Yes| D[Create new S_RoomVisitData]
    C -->|No| E[Increment VisitCount]
    D --> F[Broadcast OnRoomFirstVisit]
    E --> G[Broadcast OnRoomRevisit]
    F --> H
    G --> H{Due for mutation?}
    H -->|Yes| I[SelectMutation for RoomTag]
    H -->|No| J[Wait for next visit]
    I --> K{Mutation eligible?}
    K -->|Yes| L[Apply mutation to room]
    K -->|No| J
    L --> M[Add to ActiveMutations]
    M --> N[Broadcast OnDriftTriggered]

    O[AdaptiveDirector requests drift] --> P[TriggerDrift target room]
    P --> I
```

---

## 8. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| Room trigger volumes | Overlap event | `RoomTag: GameplayTag` |
| [`BPC_AdaptiveEnvironmentDirector`](BPC_AdaptiveEnvironmentDirector.md) | Direct call | `TriggerDrift(RoomTag, Intensity)` |
| [`DA_RoomMutation`](../14-data-assets/DA_RoomMutation.md) | Data asset read | Mutation definition: what to change, how, conditions |
| World room actors | Direct call | Apply mutation changes to specific room |
| [`GS_CoreGameState`](../01-core/06_GS_CoreGameState.md) | Direct write | Active mutation set for save persistence |

---

## 9. Validation / Testing Checklist

- [ ] S_RoomVisitData struct has all 4 fields
- [ ] RegisterRoomVisit correctly tracks first vs repeat visits
- [ ] VisitedRooms map updates VisitCount and LastVisitTime correctly
- [ ] SelectMutation filters by room tag and eligibility conditions
- [ ] TriggerDrift applies mutation and broadcasts OnDriftTriggered
- [ ] ResetRoom clears mutations and restores room to original state
- [ ] DriftIntensity gates which mutations are eligible
- [ ] Edge case: player revisits room many times → mutations escalate progressively
- [ ] Edge case: no eligible mutations for room → no change made
- [ ] Edge case: rapid room switching → visit counts tracked independently per room

---

## 10. Reuse Notes

- MutationRegistry is populated per level — each level defines which rooms can mutate and how
- DriftIntensity is ramped up by the adaptive director as the game progresses
- For non-horror games, leave MutationRegistry empty to disable the system
- Room tags are defined in DA_GameTagRegistry — add project-specific rooms there
- Extend DA_RoomMutation with new mutation types (actor spawn, light change, sound trigger, etc.)

---

*Specification based on Master Section 9.3, line 2760.*