# BPC_BehaviourVariantSelector — Behaviour Variant Selector

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- **Requires:** [`BPC_PlaystyleClassifier`](../10-adaptive/BPC_PlaystyleClassifier.md) — Subscribes to `OnPlaystyleChanged` for variant selection
- **Requires:** [`BB_AgentBoard`](BB_AgentBoard.md) — Writes `PlayerPlaystyleTag` key
- **Requires:** [`DA_BehaviourVariant`](../14-data-assets/DA_BehaviourVariant.md) — Behaviour variant data assets
- **Required By:** [`AI_BaseAgentController`](AI_BaseAgentController.md) — Owns this component, uses variant for BT configuration
- **Required By:** Behaviour Tree nodes — Read `PlayerPlaystyleTag` from blackboard to adjust behaviour
- **Engine/Plugin Requirements:** GameplayTags

### Purpose
Selects which behaviour variant the AI agent uses based on the player's classified playstyle tag. Adapts AI difficulty, aggression, patrol patterns, investigation behaviour, and reaction times to match the player's approach. Enables dynamic difficulty adjustment without designer intervention.

---

## 1. Enums

*Uses `E_PlaystyleTag` from [`BPC_PlaystyleClassifier`](../10-adaptive/BPC_PlaystyleClassifier.md) — Aggressive, Cautious, Explorer, Passive, Speedrunner, Completionist (used as Gameplay Tags).*

---

## 2. Structs

*No new structs defined. Uses `DA_BehaviourVariant` data asset rows for variant configuration.*

---

## 3. Variables

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

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `VariantMap` | Map (GameplayTag → DA_BehaviourVariant) | Empty | BehaviourConfig | Playstyle tag to behaviour variant data asset lookup |
| `DefaultVariant` | DA_BehaviourVariant | None | BehaviourConfig | Fallback variant used when no mapping exists for current playstyle |

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

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `CurrentVariant` | DA_BehaviourVariant | None | Internal | Currently active behaviour variant |
| `bInitialised` | Bool | False | Internal | Whether initial variant has been applied |

---

## 4. Functions

### Public Functions

#### `SelectVariant` → `DA_BehaviourVariant`
- **Description:** Looks up the behaviour variant for a given playstyle tag. Returns DefaultVariant if no mapping exists.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `PlaystyleTag` | GameplayTag | Player's current playstyle classification |
- **Blueprint Authority:** Any
- **Flow:** Check VariantMap for PlaystyleTag → if found, return mapped DA_BehaviourVariant → else return DefaultVariant

#### `ApplyVariant` → `void`
- **Description:** Applies a behaviour variant by writing its properties to the blackboard and configuring agent parameters.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Variant` | DA_BehaviourVariant | Variant to apply |
- **Blueprint Authority:** Any
- **Flow:** Write variant tag to BB `PlayerPlaystyleTag` → update perception config if variant changes it → update patrol speed if variant changes it → broadcast OnVariantApplied

#### `GetCurrentVariant` → `DA_BehaviourVariant`
- **Description:** Returns the currently active behaviour variant.
- **Parameters:** None
- **Blueprint Authority:** Any

#### `ResetToDefault` → `void`
- **Description:** Reverts to the DefaultVariant regardless of current playstyle. Used when AI is force-reset or despawned.
- **Parameters:** None
- **Blueprint Authority:** Any

---

## 5. Event Dispatchers

| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnVariantChanged` | OldVariant: DA_BehaviourVariant, NewVariant: DA_BehaviourVariant | Public | Variant selection changed |
| `OnVariantApplied` | Variant: DA_BehaviourVariant | Public | Variant successfully written to blackboard and configured |

---

## 6. Overridden Events / Custom Events

### Event: `BeginPlay`
- **Description:** Subscribes to [`BPC_PlaystyleClassifier`](../10-adaptive/BPC_PlaystyleClassifier.md)`OnPlaystyleChanged` dispatcher. Applies the initial variant.
- **Flow:**
  1. Subscribe to BPC_PlaystyleClassifier.OnPlaystyleChanged
  2. If BPC_PlaystyleClassifier exists, get CurrentPlaystyleTag
  3. SelectVariant(CurrentPlaystyleTag) → ApplyVariant
  4. Set bInitialised = true

### Event: `OnPlaystyleChanged`
- **Description:** Called when the player's playstyle classification changes. Re-evaluates variant selection.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `NewPlaystyleTag` | GameplayTag | Updated playstyle classification |
- **Flow:**
  1. NewVariant = SelectVariant(NewPlaystyleTag)
  2. If NewVariant != CurrentVariant → ApplyVariant(NewVariant)
  3. Broadcast OnVariantChanged

---

## 7. Blueprint Graph Logic Flow

```mermaid
flowchart TD
    A[BeginPlay] --> B[Subscribe to BPC_PlaystyleClassifier.OnPlaystyleChanged]
    B --> C{PlaystyleClassifier exists?}
    C -->|Yes| D[Get CurrentPlaystyleTag]
    C -->|No| E[Apply DefaultVariant]
    D --> F[SelectVariant from VariantMap]
    E --> G[Write PlayerPlaystyleTag to BB]
    F --> H{Variant found in map?}
    H -->|Yes| I[CurrentVariant = mapped DA_BehaviourVariant]
    H -->|No| J[CurrentVariant = DefaultVariant]
    I --> G
    J --> G
    G --> K[Broadcast OnVariantApplied]
    K --> L[bInitialised = true]

    M[OnPlaystyleChanged fires] --> N[SelectVariant new tag]
    N --> O{NewVariant != CurrentVariant?}
    O -->|Yes| P[ApplyVariant]
    O -->|No| Q[No change needed]
    P --> R[Broadcast OnVariantChanged]
    R --> L
```

---

## 8. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| [`BPC_PlaystyleClassifier`](../10-adaptive/BPC_PlaystyleClassifier.md) | Dispatcher (`OnPlaystyleChanged`) | `NewPlaystyleTag: GameplayTag` |
| [`BB_AgentBoard`](BB_AgentBoard.md) | Blackboard write | `PlayerPlaystyleTag` |
| [`AI_BaseAgentController`](AI_BaseAgentController.md) | Direct (owns) | Tick calls, init |
| Behaviour Tree (`BT_Agent`) | Blackboard read | `PlayerPlaystyleTag` → BT switches behaviour subtree |
| [`BPC_AIPerceptionSystem`](BPC_AIPerceptionSystem.md) | Direct (on same agent) | Reconfigure perception radius, reaction time from variant data |
| [`DA_BehaviourVariant`](../14-data-assets/DA_BehaviourVariant.md) | Data asset read | Variant stats: AggressionLevel, PatrolSpeed, ReactionTime, SearchRadius, etc. |

---

## 9. Validation / Testing Checklist

- [ ] VariantMap is populated with entries for all E_PlaystyleTag values
- [ ] DefaultVariant is assigned as fallback
- [ ] SelectVariant returns DefaultVariant when playstyle tag is not in VariantMap
- [ ] ApplyVariant correctly writes PlayerPlaystyleTag to blackboard
- [ ] OnPlaystyleChanged triggers variant re-evaluation
- [ ] OnVariantChanged fires when variant actually changes (not on same variant)
- [ ] ResetToDefault reverts to DefaultVariant correctly
- [ ] Edge case: BPC_PlaystyleClassifier not present → DefaultVariant applied immediately
- [ ] Edge case: rapid playstyle changes → only last variant wins
- [ ] Edge case: invalid DA_BehaviourVariant in map → fall back to DefaultVariant with warning

---

## 10. Reuse Notes

- VariantMap is designer-configurable — each AI archetype can have different playstyle-to-variant mappings
- DefaultVariant ensures AI always has valid behaviour even without a playstyle classifier
- For non-adaptive games, set VariantMap to empty and use only DefaultVariant
- Behaviour tree uses PlayerPlaystyleTag to switch between behaviour subtrees (aggressive chase vs cautious patrol, etc.)
- Extend DA_BehaviourVariant with project-specific fields for combat style, dialogue behaviour, etc.

---

*Specification based on Master Section 10.5, line 3039.*