# DA_GameTagRegistry — Blueprint Specification

> **Asset Type:** Data Asset (derives from `UPrimaryDataAsset`)
> **UE Version:** 5.5–5.7
> **Category:** 01-Core / Foundation
> **Build Phase:** Phase 0 — Item 1
> **Dependencies:** None (this is the first system)
>
> ---
>
> **⚡ C++ Status: Full Implementation** — `Source/PG_Framework/Public/Core/DA_GameTagRegistry.h` provides all tag query, validation, and export functions. The Blueprint spec below documents the API and Data Table configuration. **Do NOT create a Blueprint child** — create a **Data Asset instance** (Right-click → Miscellaneous → Data Asset → pick `DA_GameTagRegistry`). Assign the 11 `TagDataTables`. All functions are `BlueprintCallable` — call them from any BP. See `docs/developer/cpp-integration-guide.md` for exact setup steps.
>
> ---## 1. Purpose

Centralises every `GameplayTag` namespace used across the framework in a single asset. All other systems reference tags from this registry — never raw strings, never `FName` comparisons, never hardcoded booleans for state.

---

## 2. Class Settings

| Setting | Value |
|---------|-------|
| **Parent Class** | `UPrimaryDataAsset` |
| **Blueprint Type** | Data Asset |
| **Asset Path** | `/Game/Framework/Core/DA_GameTagRegistry` |
| **Is Abstract** | No |

---

## 3. Enums

None. This Data Asset uses only **Gameplay Tags** as the canonical state identifiers. No enums are defined here.

---

## 4. Structs

None. The registry is a flat collection of tag declarations.

---

## 5. Variables

| Name | Type | Category | Instance Editable | Description |
|------|------|----------|-------------------|-------------|
| `TagNamespace` | `FText` | Documentation | Yes | Human-readable description of the tag namespace (e.g. "Player.State") |
| `bIsFrameworkTag` | `bool` | Documentation | Yes | `true` for framework-defined tags, `false` for project-specific overrides |

**NOTE:** The tag definitions themselves live in the project's `DefaultGameplayTags.ini` file (or via the **Project Settings → Gameplay Tags** editor). This asset provides a centralised **documentation anchor** for those tags. The Blueprint graph does not hold tag data.

---

## 6. Functions

### 6.1 Blueprint Pure Functions

| Name | Inputs | Outputs | Category | Description |
|------|--------|---------|----------|-------------|
| `GetAllRegisteredTags` | — | `Array<FName>` | Query | Reads tags from all registered per-category Data Tables (see Section 14) |
| `GetTagDisplayName` | `Tag: FGameplayTag` | `Text` | Query | Returns the human-readable display name via `Get Tag Display Name` node |
| `ValidateTag` | `Tag: FGameplayTag` | `Boolean` | Validation | Returns `true` if the tag is valid via `Is Gameplay Tag Valid` node |

### 6.2 Blueprint Callable Functions

| Name | Inputs | Outputs | Category | Description |
|------|--------|---------|----------|-------------|
| `LogAllTags` | — | — | Debug | Prints all tags (from Data Table) to the output log (Editor-only) |
| `ExportTagNamespace` | `NamespacePrefix: String` | `String` | Tooling | Exports all tags matching a namespace prefix as a formatted string | |

---

## 7. Event Dispatchers

None. This Data Asset is passive — it has no runtime events.

---

## 8. Overridden Events

**Note:** Data Assets do NOT have `BeginPlay`, `Tick`, or `OnAssetLoaded` in Blueprint. All validation logic should be called externally from a GameInstance or Subsystem during initialization.

### Initialization Pattern (called externally):
```
[In GI_GameFramework.Init() or BPC_StateManager.BeginPlay:]
  ├─► Load DA_GameTagRegistry (hard reference or Get Data Asset)
  ├─► Call DA_GameTagRegistry.GetAllRegisteredTags()
  ├─► Array Length == 0?
  │     ├─► Yes → Print Warning: "No tags in registered Data Tables! Framework tags are unregistered."
  │     └─► No → Log: "N tags registered."
  └─► Optional: call LogAllTags() for debug output
```

## 9. Blueprint Graph Logic

### 9.1 GetAllRegisteredTags (Multi-Table Data Table Proxy)

**⚠️ UE5 Limitation:** `UGameplayTagsManager::RequestAllGameplayTags()` is C++ only — not exposed to Blueprints. This function uses a **Data Table proxy** with multiple per-category tables. All tables must be registered in `Project Settings → GameplayTags → Gameplay Tag Table List`.

```
[Function: GetAllRegisteredTags] → Array<GameplayTag>
  Step 1: Create empty Array<GameplayTag> → LocalTags
  Step 2: ForEachLoop over TagDataTables (outer loop):
    ├─► Branch: IsValid(current table)? → False: skip
    ├─► Get Data Table Row Names (current table)
    └─► ForEachLoop (RowNames) (inner loop):
          ├─► Get Data Table Row → Break GameplayTagTableRow → get "Tag"
          └─► Add "Tag" to LocalTags
  Step 3: Return LocalTags
```

**Key Change from v1:** The outer loop iterates `TagDataTables` (Array), not a single `TagDataTable`. This enables tags split across multiple CSV files by category.

### 9.2 ValidateTag

**⚠️ UE5 Limitation:** `UGameplayTagsManager::RequestGameplayTag()` is not a direct Blueprint node. Use `Is Gameplay Tag Valid` instead.

```
[Function: ValidateTag(Tag)] → Boolean
  Step 1: Is Gameplay Tag Valid (Tag)
    ├─► True → Return true
    └─► False → Print Warning: "Invalid Tag: {Get Tag Name(Tag)}" → Return false
```

**Node Search:** `Is Gameplay Tag Valid`, `Get Tag Name`

### 9.3 GetTagDisplayName

```
[Function: GetTagDisplayName(Tag)] → Text
  Step 1: Get Tag Display Name (Tag) → Return
```

**Node Search:** `Get Tag Display Name` (Blueprint pure node, available)

### 9.4 LogAllTags

```
[Function: LogAllTags] (Blueprint Callable)
  Step 1: GetAllRegisteredTags() → Store in LocalTags
  Step 2: ForEachLoop (LocalTags):
    ├─► Get Tag Name → ToString → Print String
  Step 3: Print String: "Total tags: {Array Length(LocalTags)}"
```

### 9.5 ExportTagNamespace(Prefix: String) → String

```
[Function: ExportTagNamespace]
  Step 1: GetAllRegisteredTags() → LocalTags
  Step 2: Create empty String → Output
  Step 3: ForEachLoop (LocalTags):
    ├─► Get Tag Name → ToString → TagString
    ├─► Branch: Does TagString start with Prefix?
    │     True → Append TagString + "\n" to Output
    └─► Continue
  Step 4: Return Output
```
[OnAssetLoaded]
  └─► Call GetAllRegisteredTags()
  └─► Length == 0?
      ├─► Yes → Print Warning: "No Gameplay Tags registered! /Game/Framework/Core/DA_GameTagRegistry is empty."
      └─► No → Log: "N tags registered."
```

### 9.2 Validation Function Logic (ValidateTag)

```
[ValidateTag(Tag)]
  └─► Use GameplayTag::RequestGameplayTag(Tag.TagName)
  └─► IsValid?
      ├─► Yes → return true
      └─► No → Print Warning: "Invalid Tag: {Tag}" → return false
```

---

## 10. Tag Namespace Reference (Framework Canonical)

All framework-level tags are defined in per-category Data Tables (CSV format, Row Structure: `GameplayTagTableRow`). These tables are registered in `Project Settings → GameplayTags → Gameplay Tag Table List`. The engine's `UGameplayTagsManager` merges all tables into one master list.

| Data Table | Namespaces Covered | Example Tags |
|------------|-------------------|--------------|
| `DT_Tags_Player` | `Framework.Player.State.*`, `*.Stress.*`, `*.Posture.*`, `*.Movement.*`, `*.Camera.*`, `*.Body.*`, `*.Overlay.*`, `*.Vitals.*` | Alive, Dead, Hidden, Sprinting, Crouching, Aiming, FullBody, Blood |
| `DT_Tags_Interaction` | `Framework.Interaction.Type.*`, `*.Context.*`, `*.Prompt.*`, `*.HidingSpot.*`, `*.Traversal.*`, `*.Door.*` | Pickup, Door, Container, Locked, OneShot, Vault, Mantle |
| `DT_Tags_Item` | `Framework.Item.Type.*`, `*.Slot.*`, `*.Rarity.*`, `*.Context.*` | Weapon, KeyItem, PrimaryWeapon, Legendary, Stackable |
| `DT_Tags_Narrative` | `Game.Narrative.Flag.*`, `*.Phase.*`, `*.Choice.*`, `*.Ending.*`, `*.Trial.*`, `*.Cutscene.*`, `*.Lore.*`, `Framework.Objective.*` | Chapter1Complete, Act2, GoodEnding, HospitalEscape, Intro |
| `DT_Tags_AI` | `Framework.AI.Alert.*`, `*.Archetype.*`, `*.Stimulus.*`, `*.Behavior.*`, `*.Memory.*` | Alerted, Stalker, Hearing, Aggressive, LastKnownLocation |
| `DT_Tags_Save` | `Framework.Save.*`, `*.DeathSpace.*`, `*.Checkpoint.*`, `*.Respawn.*`, `*.RunHistory.*` | Checkpoint, HardSave, Slot.1, Entered, Active, Reached, Start, Death |
| `DT_Tags_Environment` | `Game.Environment.Atmosphere.*`, `*.Scare.*`, `*.Light.*`, `*.Pacing.*`, `*.Performance.*` | Tense, MirrorJump, Flicker, Combat, High |
| `DT_Tags_Combat` | `Framework.Combat.Damage.*`, `*.Weapon.*`, `*.Ammo.*`, `*.FireMode.*`, `*.HitReaction.*`, `*.Feedback.*`, `*.Shield.*` | Physical, Firearm, Pistol, Flinch, HitMarker, Active |
| `DT_Tags_State` | `Framework.State.Action.*`, `*.Overlay.*`, `*.Vital.*`, `*.Gating.*` | Fire, Sprint, Menu, Health, BlockSprint |
| `DT_Tags_Audio` | `Framework.Audio.Bus.*`, `*.Room.*`, `*.Parameter.*`, `*.Surface.*` | SFX, Small, HeartRate, Concrete |
| `DT_Tags_Achievement` | `Game.Achievement.*` | FirstBlood, Survivor, Pacifist, Ghost, Collector, LoreMaster, TrueEnding, SpeedRunner, WeaponsMaster, Completionist |

**Usage Rule:** All systems must add the prefix `Framework.` to framework tags in code comments. Project-specific tags use `Game.` prefix. Example: `Framework.Item.Type.Weapon` vs `Game.Narrative.Flag.BasementDoorOpened`.

**CSV Format:** Each Data Table CSV uses columns: `Name,Tag,DevComment`. Name is a unique row identifier. Tag is the full gameplay tag string. DevComment explains the tag's purpose.

---

## 11. Communication Matrix

| Target System | Method | Direction | Data |
|---------------|--------|-----------|------|
| All other systems | `GameplayTag` comparisons | Read-only | Framework-defined tag values |

This asset does not talk to other systems directly. All communication is passive — other systems read tag values from the project's tag table.

---

## 12. Validation Checklist

- [ ] All namespace prefixes documented in the Data Asset's `TagNamespace` text field
- [ ] `bIsFrameworkTag` set to `true` for framework namespaces
- [ ] At least one project-specific tag exists (e.g. `Game.Narrative.Flag.PrologueComplete`) to validate the workflow
- [ ] `DefaultGameplayTags.ini` contains ALL documented tags
- [ ] No duplicate tag names across namespaces
- [ ] No raw string comparisons exist in any other system (all must use `HasTag` / `MatchesTag`)

---

## 13. Reuse Notes

- The `Game.` namespace is reserved for **project-specific** tags and is empty in the framework distribution.
- To add new tags: edit `DefaultGameplayTags.ini` or use the **Gameplay Tags** editor under **Project Settings**.
- The Data Asset is purely documentary — the real tag data lives in the project's tag table. This file exists so systems have a single place to look up "what tags exist in the framework" without reading the `.ini` file directly.

---

## 14. Manual Implementation Guide

> **For human implementer:** Follow these steps to build `DA_GameTagRegistry` in UE5 Blueprints.
> **⚠️ UE5 BP Limitation:** `UGameplayTagsManager::RequestAllGameplayTags()` is C++ only. This implementation uses an **Array of Data Tables** (11 per-category tables) as the 100% Blueprint workaround. All tables must be registered in `Project Settings → GameplayTags → Gameplay Tag Table List`.

### 14.0 Prerequisite: Create the Per-Category Data Tables

Before implementing the Data Asset, create **11 Data Tables**, one per category. Each follows the same format:

**Format:** Data Table with Row Structure = `GameplayTagTableRow`
**CSV Columns:** `Name,Tag,DevComment`
**Location in docs:** `docs/blueprints/01-core/data-tables/DT_Tags_*.csv`
**Location in UE5:** `Content/Framework/Core/DataTables/DT_Tags_*`

1. For each category, right-click in Content Browser → **Miscellaneous → Data Table**
2. Row Structure: `GameplayTagTableRow`
3. Name: `DT_Tags_{Category}` (e.g., `DT_Tags_Player`)
4. Import the corresponding CSV file (Right-click Data Table → Import → CSV)
5. **Critical:** Go to `Project Settings → GameplayTags → Gameplay Tag Table List` → click `+` 11 times → assign each table to a slot
   - This auto-registers ALL tags with the engine's tag manager.

### 14.1 Class Setup

1. Right-click in Content Browser → **Miscellaneous → Data Asset**
2. Select parent class: `PrimaryDataAsset`
3. Name: `DA_GameTagRegistry`
4. Save to: `Content/Framework/Core/`

### 14.2 Variables

Add to Class Defaults:
| Variable | Type | Instance Editable | Default | Category |
|----------|------|------------------|---------|----------|
| `TagNamespace` | `Text` | ✓ | *"Framework tag namespace documentation"* | Documentation |
| `bIsFrameworkTag` | `Boolean` | ✓ | `true` | Documentation |
| `TagDataTables` | `Array<Data Table Object Reference>` | ✓ | [DT_Tags_Player, DT_Tags_Interaction, DT_Tags_Item, DT_Tags_Narrative, DT_Tags_AI, DT_Tags_Save, DT_Tags_Environment, DT_Tags_Combat, DT_Tags_State, DT_Tags_Audio, DT_Tags_Achievement] | Config |

**⚠️ Multi-Table Design:** Tags are split into 11 per-category Data Tables (see Section 10). In UE5 `Project Settings → GameplayTags → Gameplay Tag Table List`, add ALL 11 tables. The engine's `UGameplayTagsManager` merges them automatically.

### 14.3 Function Implementations

#### `GetAllRegisteredTags()` → `Array<GameplayTag>` *(Blueprint Pure)*

**Purpose:** Returns all tags from ALL registered Data Tables. Uses an outer loop over `TagDataTables` array and inner loop over each table's rows.

**⚠️ UE5 Limitation:** `UGameplayTagsManager::RequestAllGameplayTags()` is C++ only — not exposed to Blueprints. This function uses the Data Table proxy approach with multiple tables.

**Node-by-Node Logic:**
```
[Function: GetAllRegisteredTags] (Pure, no execution pins)
  Step 1: Create empty Array<GameplayTag> → LocalTags
  Step 2: ForEachLoop over TagDataTables array (outer loop):
    ├─► Array Element = current Data Table
    ├─► Branch: IsValid(current table)?
    │     False → Skip to next table
    │     True → Continue
    ├─► Get Data Table Row Names (current table) → returns Array<Name>
    └─► ForEachLoop over RowNames (inner loop):
          ├─► Get Data Table Row (current table, Array Element)
          │     → Struct Pin: Break GameplayTagTableRow
          │     → Get "Tag" field (type: GameplayTag)
          └─► Add "Tag" to LocalTags array
  Step 3: Return LocalTags
```

**Nodes to Search:** `ForEachLoop` (outer over TagDataTables), `ForEachLoop` (inner over row names), `Get Data Table Row Names`, `Get Data Table Row`, `Break GameplayTagTableRow`, `Add`, `Array`, `IsValid`

**⚠️ Note:** If your UE version doesn't support loops in Pure functions, make this **BlueprintCallable** (impure) instead.

#### `GetTagDisplayName(Tag: GameplayTag)` → `Text` *(Blueprint Pure)*

**Node-by-Node Logic:**
```
[Function: GetTagDisplayName]
  Input Tag → Get Tag Display Name (Tag) → Return
```

**Node Search:** `Get Tag Display Name` — this IS available in Blueprint (part of GameplayTags plugin).

#### `ValidateTag(Tag: GameplayTag)` → `Boolean` *(Blueprint Pure)*

**⚠️ UE5 Limitation:** `UGameplayTagsManager::RequestGameplayTag()` is not directly available in BP. Use `Is Gameplay Tag Valid` instead.

**Node-by-Node Logic:**
```
[Function: ValidateTag]
  Step 1: Is Gameplay Tag Valid (Tag)
    ├─► True → Return true
    └─► False → Print Warning: "Invalid Tag: " + Get Tag Name(Tag) → Return false
```

**Node Search:** `Is Gameplay Tag Valid`, `Get Tag Name`

**⚠️ Note:** `Is Gameplay Tag Valid` returns true only if the tag is registered in the engine's tag table (which the 11 Data Tables populate via Project Settings). Tags NOT in any registered table will return false.

#### `LogAllTags()` → *(void)* *(Blueprint Callable)*

**Editor Only.** Prints all tags from all Data Tables to the output log.

**Node-by-Node Logic:**
```
[Function: LogAllTags]
  Step 1: Call GetAllRegisteredTags() → LocalTags
  Step 2: ForEachLoop (LocalTags):
    ├─►  Name (Array Element) → ToString → Print String
  Step 3: Print String: "Total tags across all tables: " + Array Length(LocalTags)
```

#### `ExportTagNamespace(NamespacePrefix: String)` → `String` *(Blueprint Callable)*

**Node-by-Node Logic:**
```
[Function: ExportTagNamespace]
  Step 1: Call GetAllRegisteredTags() → LocalTags
  Step 2: Create String variable → Output = ""
  Step 3: ForEachLoop (LocalTags):
    ├─► (Array Element) → ToString → TagString
    ├─► Branch: Does TagString start with NamespacePrefix?
    │     True → Append TagString + "\n" to Output (use "Append" or "Build String")
    └─► Continue
  Step 4: Return Output
```

### 14.4 External Initialization

Since Data Assets have no `BeginPlay`, call validation from your GameInstance or StateManager:

**In `GI_StarterGameInstance.Init()` or `GI_GameFramework.Init()`:**
```
  Step 1: Get DA_GameTagRegistry (hard reference or Load Asset)
  Step 2: Call DA_GameTagRegistry.GetAllRegisteredTags() → LocalTags
  Step 3: Branch: Array Length(LocalTags) == 0
    ├─► True → Print Warning: "No tags in registered Data Tables!"
    └─► False → Print String: "N tags registered: " + Array Length
  Step 4: [Debug builds only] Call DA_GameTagRegistry.LogAllTags()
```

### 14.5 Networking

No replication needed. This is a read-only Data Asset with a read-only Data Table reference. All clients load identical copies from disk.

### 14.6 Blueprint Build Checklist

- [ ] Create 11 Data Tables with Row Structure `GameplayTagTableRow`:
  - [ ] `DT_Tags_Player` — Player state, stress, posture, movement, camera, body, vitals
  - [ ] `DT_Tags_Interaction` — Interaction types, contexts, prompts, hiding spots, traversal, doors
  - [ ] `DT_Tags_Item` — Item types, slots, rarities, contexts
  - [ ] `DT_Tags_Narrative` — Flags, phases, choices, endings, trials, cutscenes, lore, objectives
  - [ ] `DT_Tags_AI` — Alert levels, archetypes, stimuli, behaviors, memory
  - [ ] `DT_Tags_Save` — Save types, death space, checkpoints, respawn
  - [ ] `DT_Tags_Environment` — Atmosphere, scares, lighting, pacing, performance
  - [ ] `DT_Tags_Combat` — Damage types, weapons, ammo, fire modes, hit reactions, shield
  - [ ] `DT_Tags_State` — Action states, overlay states, vitals, gating
  - [ ] `DT_Tags_Audio` — Audio buses, room acoustics, parameters, surfaces
  - [ ] `DT_Tags_Achievement` — Achievement identifiers
- [ ] Add ALL 11 tables to `Project Settings → GameplayTags → Gameplay Tag Table List`
- [ ] Create Data Asset: `DA_GameTagRegistry` (Parent: `PrimaryDataAsset`)
- [ ] Add variables: `TagNamespace` (Text), `bIsFrameworkTag` (Boolean), `TagDataTables` (Array<Data Table> — populate with all 11 tables)
- [ ] Implement `GetAllRegisteredTags` with OUTER loop over TagDataTables + INNER loop over row names
- [ ] Implement `GetTagDisplayName` using `Get Tag Display Name` node
- [ ] Implement `ValidateTag` using `Is Gameplay Tag Valid` node
- [ ] Implement `LogAllTags` (editor-only, prints tags from all tables)
- [ ] Implement `ExportTagNamespace` (string prefix filtering across all tables)
- [ ] Add external initialization call from `GI_StarterGameInstance.Init()` or `GI_GameFramework.Init()`
- [ ] Verify: all tags from Section 10 exist in the appropriate Data Table
- [ ] Verify: `ValidateTag` returns true for tags in any registered table, false for unregistered
- [ ] Verify: `GetAllRegisteredTags` returns ALL tags merged from all tables

---

## 15. Multiplayer Networking

**Replication: None needed.** This Data Asset is read-only configuration. All clients load identical copies from disk. GameplayTag data lives in `DefaultGameplayTags.ini` which is identical on all instances.

**Authority: N/A.** No runtime state changes.
