Refactor GameplayTag documentation and implementation

- Updated references from GI_GameTagRegistry to DA_GameTagRegistry in architecture overview and implementation patterns documentation.
- Added new Blueprint specification for GI_StarterGameInstance, detailing its purpose, configuration, and integration pattern.
- Introduced DA_GameTagRegistry Blueprint specification, centralizing GameplayTag management and providing functions for tag validation and logging.
- Created documentation for the Starter GameInstance, outlining its role in the project setup and how other systems can integrate with it.
This commit is contained in:
Lefteris Notas
2026-05-20 14:31:52 +03:00
parent 3023ad3555
commit fee12b115f
17 changed files with 927 additions and 423 deletions

View File

@@ -0,0 +1,355 @@
# GI_StarterGameInstance — Blueprint Specification
> **Asset Type:** Game Instance (derives from `UGameInstance`)
> **UE Version:** 5.55.7
> **Category:** 00-Project-Setup / Starter
> **Build Phase:** Pre-Phase 0 — Project Initialization
> **Dependencies:** `DA_GameTagRegistry` (01), 11 per-category Data Tables, GameplayTags plugin
---
## 1. Purpose
A minimal, ready-to-use GameInstance Blueprint that serves as the project's **immediate** entry point. Set this as your `Game Instance Class` in Project Settings to get tag validation and framework bootstrapping working on day one. It loads `DA_GameTagRegistry`, validates that all 11 Data Tables are registered, and broadcasts `OnFrameworkReady` when initialization completes.
**This is intentionally simple.** As the project matures, replace it with `GI_GameFramework` (04) which adds full game-phase management, subsystem ownership, platform init, and save-slot orchestration. All systems that bind to `OnFrameworkReady` will continue working with either GameInstance.
---
## 2. Class Settings
| Setting | Value |
|---------|-------|
| **Parent Class** | `GameInstance` |
| **Blueprint Type** | Game Instance |
| **Asset Path** | `/Game/Framework/Core/GI_StarterGameInstance` |
| **Is Abstract** | No |
**UE5 Setup:** `Project Settings → Maps & Modes → Game Instance Class``GI_StarterGameInstance`
---
## 3. Enums
None. No custom enums are defined in this system.
---
## 4. Structs
None. No custom structs are defined in this system.
---
## 5. Variables
### Configuration (Instance Editable)
| Name | Type | Default | Category | Description |
|------|------|---------|----------|-------------|
| `TagRegistry` | `DA_GameTagRegistry` (Object Reference) | *Assigned in Class Defaults* | Config | Hard reference to the `DA_GameTagRegistry` Data Asset |
| `bValidateTagsOnInit` | `Boolean` | `true` | Config | If true, calls `DA_GameTagRegistry.GetAllRegisteredTags()` during `Event Init` and logs tag count |
| `bLogTagsOnInit` | `Boolean` | `false` | Debug | If true, calls `DA_GameTagRegistry.LogAllTags()` after validation (Editor-only; heavy logging) |
### Internal (Private)
| Name | Type | Default | Category | Description |
|------|------|---------|----------|-------------|
| `bFrameworkInitialized` | `Boolean` | `false` | State | Set to `true` after `Event Init` completes successfully |
---
## 6. Functions
### Public Functions
#### `GetTagRegistry()` → `DA_GameTagRegistry` *(Blueprint Pure)*
- **Description:** Returns the cached `TagRegistry` reference. Returns `None` if not yet loaded.
- **Parameters:** None
- **Flow:**
1. Return `TagRegistry` variable
#### `IsFrameworkReady()` → `Boolean` *(Blueprint Pure)*
- **Description:** Returns whether the framework has completed initialization. Systems should check this before querying tag-dependent services.
- **Parameters:** None
- **Flow:**
1. Return `bFrameworkInitialized`
### Protected / Private Functions
#### `ValidateFrameworkTags()` *(Blueprint Callable, Private)*
- **Description:** Loads the tag registry, counts registered tags, and logs warnings if zero tags are found. Called automatically during `Event Init`.
- **Parameters:** None
- **Flow:**
1. `IsValid(TagRegistry)`? → False: Print Error "TagRegistry not assigned!" → Return
2. Call `TagRegistry.GetAllRegisteredTags()``AllTags` (Array\<GameplayTag\>)
3. `Array Length(AllTags) == 0`?
- True: Print Warning "No Gameplay Tags registered! Check Project Settings → GameplayTags → Gameplay Tag Table List. All 11 Data Tables must be added."
- False: Print String "DA_GameTagRegistry initialized: {Array Length} tags registered across 11 Data Tables."
4. If `bLogTagsOnInit`: Call `TagRegistry.LogAllTags()`
---
## 7. Event Dispatchers
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnFrameworkReady` | — | Public | Fires after `Event Init` completes and tag validation passes. Other systems bind to this to defer initialization until the framework is ready. |
| `OnFrameworkInitFailed` | `ErrorReason: String` | Public | Fires if `TagRegistry` is invalid or zero tags are found during init. Systems should handle gracefully — show error UI, disable gameplay. |
---
## 8. Overridden Events
### Event: `Event Init`
- **Description:** UE5's GameInstance initialization event. Fires once when the game starts, before any level loads. This is where framework bootstrapping happens.
- **Flow:**
1. Call `Parent: Event Init` (important — don't skip)
2. Print String: "GI_StarterGameInstance: Init started"
3. `Branch: bValidateTagsOnInit?`
- False → Print String "Tag validation skipped (bValidateTagsOnInit = false)"
- True → Call `ValidateFrameworkTags()`
4. `Branch: IsValid(TagRegistry)?`
- False → Print Error "DA_GameTagRegistry reference is invalid!" → Call `OnFrameworkInitFailed("TagRegistry not assigned or invalid")` → Return
- True → Continue
5. Set `bFrameworkInitialized = true`
6. Call `OnFrameworkReady` (broadcast to all bound listeners)
7. Print String: "GI_StarterGameInstance: Init complete — OnFrameworkReady broadcast"
---
## 9. Blueprint Graph Logic Flow
```mermaid
flowchart TD
A[Event Init] --> B[Call Parent: Event Init]
B --> C{ bValidateTagsOnInit? }
C -->|True| D[Call ValidateFrameworkTags]
C -->|False| E[Skip validation]
D --> F{ IsValid TagRegistry? }
F -->|False| G[Print Error<br>Broadcast OnFrameworkInitFailed]
F -->|True| H[Set bFrameworkInitialized = true]
H --> I[Broadcast OnFrameworkReady]
I --> J[Print 'Init Complete']
```
### ValidateFrameworkTags Flow
```mermaid
flowchart TD
A[ValidateFrameworkTags] --> B{ IsValid TagRegistry? }
B -->|False| C[Print Error: TagRegistry not assigned]
B -->|True| D[Call GetAllRegisteredTags → AllTags]
D --> E{ Array Length == 0? }
E -->|True| F[Print Warning: No tags registered]
E -->|False| G[Print: N tags registered]
G --> H{ bLogTagsOnInit? }
H -->|True| I[Call LogAllTags]
H -->|False| J[Return]
I --> J
F --> J
C --> J
```
---
## 10. Communication Matrix
| Source | Target | Method | Direction | Data |
|--------|--------|--------|-----------|------|
| `GI_StarterGameInstance` | `DA_GameTagRegistry` | Direct function call | Outbound | Calls `GetAllRegisteredTags()`, `LogAllTags()`, `ValidateTag()` |
| `GI_StarterGameInstance` | All bound systems | `OnFrameworkReady` dispatcher | Outbound broadcast | No data — listeners query `IsFrameworkReady()` |
| `GI_StarterGameInstance` | All bound systems | `OnFrameworkInitFailed` dispatcher | Outbound broadcast | `ErrorReason: String` |
| Any system | `GI_StarterGameInstance` | `GetGameInstance()` → Cast | Inbound query | Systems call `IsFrameworkReady()` before initialization |
---
## 11. Validation Checklist
- [ ] `GI_StarterGameInstance` set as `Game Instance Class` in `Project Settings → Maps & Modes`
- [ ] `TagRegistry` variable assigned to `DA_GameTagRegistry` Data Asset in Class Defaults
- [ ] All 11 Data Tables registered in `Project Settings → GameplayTags → Gameplay Tag Table List`
- [ ] On PIE (Play In Editor): output log shows "N tags registered across 11 Data Tables"
- [ ] On PIE with `bLogTagsOnInit = true`: all tag names printed to output log
- [ ] If `TagRegistry` is unassigned: error prints and `OnFrameworkInitFailed` fires (test by clearing the variable)
- [ ] Other systems successfully bind to `OnFrameworkReady` and defer their init
- [ ] Edge case: 0 tags in Data Tables → warning prints, `OnFrameworkInitFailed` does NOT fire (empty tables are a warning, not a failure)
---
## 12. Reuse Notes
- **Replacement path:** When you are ready for the full `GI_GameFramework` (04), simply change the `Game Instance Class` in Project Settings. All systems that bind to `OnFrameworkReady` on either GameInstance will work — `GI_GameFramework` includes the same dispatcher.
- **Project-specific init:** Add custom initialization (achievement platform, analytics, save migration) after the `OnFrameworkReady` broadcast in `Event Init`.
- **Tag registry is a Data Asset, not a subsystem:** You must manually assign the `TagRegistry` reference in Class Defaults. It is NOT auto-discovered.
- **Multi-platform:** On consoles, `Event Init` fires before any level loads — same as PC. No platform-specific code is needed.
---
## 13. Manual Implementation Guide
> **For human implementer:** Follow these steps to build `GI_StarterGameInstance` in UE5 Blueprints. This is the FIRST Blueprint you should create — it enables tag validation for all other systems.
### 13.1 Class Setup
1. Right-click in Content Browser → **Blueprint Class**
2. Search for parent class: `GameInstance`
3. Name: `GI_StarterGameInstance`
4. Save to: `Content/Framework/Core/`
5. Open **Project Settings → Maps & Modes** → Set `Game Instance Class` to `GI_StarterGameInstance`
### 13.2 Variables
Add to Class Defaults:
| Variable | Type | Instance Editable | Default | Category |
|----------|------|------------------|---------|----------|
| `TagRegistry` | `DA_GameTagRegistry` (Object Reference) | ✓ | *Select `DA_GameTagRegistry` asset* | Config |
| `bValidateTagsOnInit` | `Boolean` | ✓ | `true` | Config |
| `bLogTagsOnInit` | `Boolean` | ✓ | `false` | Debug |
| `bFrameworkInitialized` | `Boolean` | ✗ (Private) | `false` | State |
**⚠️ Important:** For `TagRegistry`, use the type `DA_GameTagRegistry` (your specific Data Asset Blueprint class, NOT the generic `PrimaryDataAsset`). Compile `DA_GameTagRegistry` first so it appears in the type dropdown.
### 13.3 Event Dispatchers
Create two Event Dispatchers in the **My Blueprint** panel:
1. `OnFrameworkReady` — no parameters
2. `OnFrameworkInitFailed` — add one input parameter:
- `ErrorReason` (String)
### 13.4 Override Event Init
1. In the **My Blueprint** panel, hover over **Functions** → click **Override** → select `Event Init`
2. Build the following graph:
```
[Event Init]
Step 1: Call "Parent: Event Init" (right-click event node → "Add Call to Parent")
Step 2: Print String: "GI_StarterGameInstance: Init started"
→ Text (Format Text): "GI_StarterGameInstance: Init started"
Step 3: Branch (Condition: bValidateTagsOnInit)
True → Call ValidateFrameworkTags (see 13.5)
False → Print String: "Tag validation skipped (bValidateTagsOnInit = false)"
Step 4: IsValid(TagRegistry) → Branch
False:
→ Print String: "DA_GameTagRegistry reference is invalid!"
→ Call OnFrameworkInitFailed (ErrorReason = "TagRegistry not assigned or invalid")
→ Return Node
True: Continue
Step 5: Set bFrameworkInitialized = true
Step 6: Call OnFrameworkReady (no params)
Step 7: Print String: "GI_StarterGameInstance: Init complete — OnFrameworkReady broadcast"
```
**Nodes to Search:** `Event Init`, `Add Call to Parent`, `Print String`, `Format Text`, `Branch`, `IsValid`, `Set`, `Call OnFrameworkReady`, `Call OnFrameworkInitFailed`
### 13.5 Implement ValidateFrameworkTags
Create a new function: **BlueprintCallable**, Private, named `ValidateFrameworkTags`.
```
[Function: ValidateFrameworkTags] (BlueprintCallable, Private)
Step 1: IsValid(TagRegistry) → Branch
False: Print String "TagRegistry not assigned in GI_StarterGameInstance!" → Return
True: Continue
Step 2: Call TagRegistry → GetAllRegisteredTags() → store in "AllTags" (Array<GameplayTag>)
Step 3: Array Length(AllTags) → store in "TagCount" (Integer)
Step 4: Branch (Condition: TagCount == 0)
True: Print String (Color: Yellow): "WARNING: No Gameplay Tags registered! Check Project Settings → GameplayTags → Gameplay Tag Table List. All 11 Data Tables must be added."
False: Print String (Format Text): "DA_GameTagRegistry initialized: {TagCount} tags registered across 11 Data Tables."
Step 5: Branch (Condition: bLogTagsOnInit)
True: Call TagRegistry → LogAllTags()
False: Continue (no action)
Step 6: Return
```
**Nodes to Search:** `IsValid`, `GetAllRegisteredTags`, `Array Length`, `Branch`, `Print String`, `Format Text`, `LogAllTags`
### 13.6 Implement GetTagRegistry
Create a new function: **BlueprintPure**, Public, named `GetTagRegistry`.
```
[Function: GetTagRegistry] → DA_GameTagRegistry (BlueprintPure)
Return TagRegistry
```
### 13.7 Implement IsFrameworkReady
Create a new function: **BlueprintPure**, Public, named `IsFrameworkReady`.
```
[Function: IsFrameworkReady] → Boolean (BlueprintPure)
Return bFrameworkInitialized
```
### 13.8 How Other Systems Bind to OnFrameworkReady
In any other Blueprint that needs framework services (tag validation, subsystems, etc.):
```
[Event BeginPlay]
Step 1: Get Game Instance → Cast to GI_StarterGameInstance → Store as "GameInstance"
Step 2: Branch: IsValid(GameInstance)?
True:
→ Branch: GameInstance → IsFrameworkReady()?
True: Call "OnFrameworkReadyHandler" immediately (already initialized)
False: Bind "OnFrameworkReadyHandler" to GameInstance.OnFrameworkReady
False: Print Warning "GI_StarterGameInstance not found!"
```
**Custom Event: OnFrameworkReadyHandler**
```
[Custom Event: OnFrameworkReadyHandler]
Step 1: Unbind from GameInstance.OnFrameworkReady (if bound — prevents double-fire)
Step 2: ... proceed with system-specific initialization ...
```
### 13.9 Quick Node Reference
| Node | Where to Find | Used For |
|------|---------------|----------|
| `Event Init` | Override in My Blueprint → Functions | GameInstance startup |
| `Get Game Instance` | Right-click → "Get Game Instance" | Any Blueprint that needs the GameInstance |
| `Cast to GI_StarterGameInstance` | Right-click → "Cast to GI_StarterGameInstance" | Type-safe access to framework functions |
| `IsValid` | Right-click → "IsValid" | Null-checking object references |
| `Bind Event to OnFrameworkReady` | Right-click on dispatcher → "Bind Event" | Deferred initialization |
| `Unbind Event from OnFrameworkReady` | Right-click on dispatcher → "Unbind Event" | Clean up after handler fires |
---
## 14. Blueprint Build Checklist
- [ ] Create `GI_StarterGameInstance` Blueprint (Parent: `GameInstance`)
- [ ] Set as `Game Instance Class` in `Project Settings → Maps & Modes`
- [ ] Create `DA_GameTagRegistry` Data Asset first (required for `TagRegistry` variable type)
- [ ] Add variable `TagRegistry` (type: `DA_GameTagRegistry`) and assign the Data Asset
- [ ] Add variable `bValidateTagsOnInit` (Boolean, default `true`)
- [ ] Add variable `bLogTagsOnInit` (Boolean, default `false`)
- [ ] Add variable `bFrameworkInitialized` (Boolean, default `false`, Private)
- [ ] Create Event Dispatcher `OnFrameworkReady` (no params)
- [ ] Create Event Dispatcher `OnFrameworkInitFailed` (1 param: `ErrorReason` String)
- [ ] Override `Event Init` — add Call to Parent, validation branch, dispatcher broadcasts
- [ ] Implement `ValidateFrameworkTags()` — validate registry, count tags, optional log
- [ ] Implement `GetTagRegistry()` (BlueprintPure) — return TagRegistry reference
- [ ] Implement `IsFrameworkReady()` (BlueprintPure) — return bFrameworkInitialized
- [ ] Compile and test: PIE → output log shows "DA_GameTagRegistry initialized: N tags"
- [ ] Test error path: clear `TagRegistry` variable → `OnFrameworkInitFailed` fires
- [ ] Test with `bLogTagsOnInit = true` → all tags printed to output log
- [ ] Verify other systems can bind to `OnFrameworkReady` and defer init correctly
---
## 15. Multiplayer Networking
**Replication: None needed.** The GameInstance is a client-only singleton — each client has its own instance. The `DA_GameTagRegistry` Data Asset loads identically from disk on all clients and servers. Event Dispatchers (`OnFrameworkReady`, `OnFrameworkInitFailed`) fire locally on each instance.
**Authority: N/A.** No runtime state changes. Tag data is read-only configuration.
**Multiplayer Note:** In a networked game, `Event Init` fires on both server and each client's GameInstance. Tag validation runs independently on each — which is correct, since Data Tables and GameplayTags must be identical across all instances for networked tag replication to function.

View File

@@ -0,0 +1,402 @@
# DA_GameTagRegistry — Blueprint Specification
> **Asset Type:** Data Asset (derives from `UPrimaryDataAsset`)
> **UE Version:** 5.55.7
> **Category:** 01-Core / Foundation
> **Build Phase:** Phase 0 — Item 1
> **Dependencies:** None (this is the first system)
---
## 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.

View File

@@ -1,402 +1,19 @@
# GI_GameTagRegistry — Blueprint Specification
# RENAMED — See `01_DA_GameTagRegistry.md`
> **Asset Type:** Data Asset (derives from `UPrimaryDataAsset`)
> **UE Version:** 5.55.7
> **Category:** 01-Core / Foundation
> **Build Phase:** Phase 0 — Item 1
> **Dependencies:** None (this is the first system)
> **This file has been renamed.** The system is now `DA_GameTagRegistry` (Data Asset prefix, `UPrimaryDataAsset` parent), not `GI_GameTagRegistry` (Game Instance prefix).
---
## Why the rename?
## 1. Purpose
The `GI_` prefix implies a `GameInstance` class, but this system is architecturally a **Data Asset** — it has no lifecycle events (`BeginPlay`, `Tick`), no runtime state, and is loaded as a read-only configuration asset. The framework already has `GI_GameFramework` (#04) as the project's sole GameInstance class.
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.
Additionally, the new [`GI_StarterGameInstance`](../00-project-setup/GI_StarterGameInstance.md) (00-project-setup) provides the actual GameInstance entry point that loads and validates `DA_GameTagRegistry` during `Event Init`.
---
## Migration
## 2. Class Settings
If you were referencing this file:
- **Old path:** `docs/blueprints/01-core/01_GI_GameTagRegistry.md`
- **New path:** [`docs/blueprints/01-core/01_DA_GameTagRegistry.md`](01_DA_GameTagRegistry.md)
- **Old asset name:** `GI_GameTagRegistry`**New asset name:** `DA_GameTagRegistry`
- **Old asset path:** `/Game/Framework/Core/DA_GameTagRegistry` (asset path was already correct)
| 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_GameFramework.Init()` or `BPC_StateManager.BeginPlay()`:**
```
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_GameFramework.Init()` or `BPC_StateManager.BeginPlay()`
- [ ] 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.
All framework documentation has been updated to use `DA_GameTagRegistry`. No functionality has changed — only the prefix was corrected.

View File

@@ -4,7 +4,7 @@
The single source of truth for every item in the game. Each item is represented by one `DA_ItemData` Primary Data Asset. No item data lives in Blueprint logic; all item definitions are data-driven from these assets.
## Dependencies
- **Requires:** `GameplayTag` system (`GI_GameTagRegistry`), `UPrimaryDataAsset` (engine base)
- **Requires:** `GameplayTag` system (`DA_GameTagRegistry`), `UPrimaryDataAsset` (engine base)
- **Required By:** `BPC_InventorySystem`, `BPC_EquipmentSlotSystem`, `BPC_ConsumableSystem`, `BPC_AmmoResourceSystem`, `BPC_ItemCombineSystem`, `BPC_KeyItemSystem`, `BPC_ActiveItemSystem`, `DA_ItemDatabase` (collection)
- **Engine/Plugin Requirements:** `GameplayTags`, `AssetManager` (Primary Data Asset registration)
- **Parent Class:** `UPrimaryDataAsset`
@@ -171,7 +171,7 @@ flowchart LR
## 10. Reuse Notes
- Create one `DA_ItemData` per item. Name convention: `DA_Item_[ShortName]` (e.g. `DA_Item_MedKit`, `DA_Item_Flashlight`, `DA_Item_KeyCard_Omega`).
- All `ItemTag` values must be registered in `GI_GameTagRegistry` before use.
- All `ItemTag` values must be registered in `DA_GameTagRegistry` before use.
- The `CustomProperties` map future-proofs any per-project additions without modifying the base asset class.
- For non-stackable items (weapons, key items, tools), set `StackLimit = 1`.
- For stacks, choose a sensible `StackLimit` (e.g. ammo = 999, consumables = 5).

View File

@@ -244,7 +244,7 @@ Manages the player's ability to hide inside, behind, or under environmental obje
- **Description:** Initialises state, binds to input actions.
- **Flow:**
1. Set CurrentHideState = Exposed
2. Register with GI_GameTagRegistry if needed
2. Register with DA_GameTagRegistry if needed
3. Cache reference to CharacterMovementComponent for disabling during hide
### Custom Event: `ForceKickFromHide`

View File

@@ -195,7 +195,7 @@ flowchart TD
- 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 GI_GameTagRegistry — add project-specific rooms there
- 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.)
---

View File

@@ -91,7 +91,7 @@ Values:
- [ ] EventTag is unique and valid GameplayTag
- [ ] Probability is in range 0.01.0 (0.001 = 0.1%, 0.01 = 1%, 0.1 = 10%)
- [ ] EventConditions tags exist in GI_GameTagRegistry
- [ ] EventConditions tags exist in DA_GameTagRegistry
- [ ] EventActions array has at least one action
- [ ] S_RareEventAction.ActionType matches the data needed (audio uses ActionTag for cue, spawn uses ActionTag for actor class)
- [ ] bOncePerSession and bOncePerSaveFile properly gated (don't set both unless intended)

View File

@@ -4,7 +4,7 @@
Single source of truth for "what can the player do right now?" Every system queries `IsActionPermitted(Tag)` instead of checking other systems' states directly. Manages exclusive action states, upper-body overlay states, action action gating, vital signs (heart rate), and the force-stack pattern for nested overrides (death, cutscenes, void space). Communicates with GASP exclusively through overlay state variables — never touches motion matching internals.
## Dependencies
- **Requires:** `GI_GameFramework` (04 — game phase changes), `BPC_HealthSystem` (08 — death + injury bindings), `BPC_StressSystem` (10 — stress tier), `BPC_StaminaSystem` (09 — exhaustion), `BPC_MovementStateSystem` (11 — movement mode tracking), `GI_GameTagRegistry` (01 — tag queries), `SS_EnhancedInputManager` (128 — context switching), `ABP_GASP` (external — overlay + intensity variables)
- **Requires:** `GI_GameFramework` (04 — game phase changes), `BPC_HealthSystem` (08 — death + injury bindings), `BPC_StressSystem` (10 — stress tier), `BPC_StaminaSystem` (09 — exhaustion), `BPC_MovementStateSystem` (11 — movement mode tracking), `DA_GameTagRegistry` (01 — tag queries), `SS_EnhancedInputManager` (128 — context switching), `ABP_GASP` (external — overlay + intensity variables)
- **Required By:** EVERY gameplay system (central query point for action permission)
- **Engine/Plugin Requirements:** GameplayTags plugin, GASP plugin (read-only)
@@ -425,7 +425,7 @@ Values:
4. Populate default `GatingRules` from `DA_StateGatingTable` if assigned
5. Bind to `GI_GameFramework.OnGamePhaseChanged` (for game-phase-gated rules)
6. Bind to `BPC_HealthSystem.OnDeath` (auto-call `ForceStateChange(Dead, "Death")`)
7. Register with `GI_GameTagRegistry` for tag-based queries
7. Register with `DA_GameTagRegistry` for tag-based queries
8. Bind to `BPC_HealthSystem.OnHealthChanged` call `EvaluateInjuryState()`
9. Bind to `BPC_StressSystem.OnStressTierChanged` recalculate heart rate
10. Bind to `BPC_StaminaSystem.OnExhaustionStateChanged` recalculate heart rate

View File

@@ -1,6 +1,6 @@
# Master Blueprint Index — UE5 Modular Game Framework
**Version:** 3.0 | **Generated:** 2026-05-18 | **Total Files:** 135 numbered (129 original + 6 new)
**Version:** 3.1 | **Generated:** 2026-05-20 | **Total Files:** 135 numbered + 1 starter (136 total specs)
This document is the canonical index of every Blueprint specification file in the framework. Each entry links to its full spec document and includes: file name, asset type, parent class, purpose summary, and key dependencies.
@@ -14,6 +14,8 @@ docs/blueprints/
├── TEMPLATE.md ← Spec template v2.0
├── AUDIT_REPORT.md ← Clean slate audit
├── 00-project-setup/ ← Project Setup & Starter Assets (1 file)
│ └── GI_StarterGameInstance.md ← Minimal GameInstance; tag validation entry point
├── 01-core/ ← Foundation (7 files + 11 Data Table CSVs)
│ ├── data-tables/ ← Per-category Gameplay Tag Data Tables (NEW — replaces DT_ProjectTags.csv)
│ │ ├── DT_Tags_Player.csv (34 tags)
@@ -51,7 +53,8 @@ docs/blueprints/
| # | File Name | Asset Type | Parent Class | Short Purpose | Category |
|---|-----------|-----------|-------------|---------------|----------|
| 01 | [`01_GI_GameTagRegistry`](01-core/01_GI_GameTagRegistry.md) | `GI_` Game Instance | `GameInstance` | Central gameplay tag registry; maps tags to data/assets | 01-core |
| | [`GI_StarterGameInstance`](00-project-setup/GI_StarterGameInstance.md) | `GI_` Game Instance | `GameInstance` | Minimal GameInstance; loads DA_GameTagRegistry, validates tags, broadcasts OnFrameworkReady | 00-project-setup |
| 01 | [`01_DA_GameTagRegistry`](01-core/01_DA_GameTagRegistry.md) | `DA_` Data Asset | `PrimaryDataAsset` | Central gameplay tag registry; maps tags to data/assets | 01-core |
| 02 | [`02_FL_GameUtilities`](01-core/02_FL_GameUtilities.md) | `FL_` Function Library | `BlueprintFunctionLibrary` | Shared utility functions (logging, tag queries, math) | 01-core |
| 03 | [`03_I_InterfaceLibrary`](01-core/03_I_InterfaceLibrary.md) | `I_` Interface | `Interface` | All framework interfaces (I_Damageable, I_Interactable, I_Persistable, etc.) | 01-core |
| 04 | [`04_GI_GameFramework`](01-core/04_GI_GameFramework.md) | `GI_` Game Instance | `GameInstance` | Application kernel; owns subsystems, game phases, platform init | 01-core |
@@ -210,7 +213,7 @@ docs/blueprints/
| `BPC_` | Blueprint Component | 80 |
| `BP_` | Blueprint Actor | 11 |
| `WBP_` | Widget Blueprint | 14 |
| `DA_` | Data Asset | 18 |
| `DA_` | Data Asset | 19 |
| `SS_` | GameInstance Subsystem | 7 |
| `GI_` | Game Instance | 2 |
| `GM_` | Game Mode | 1 |
@@ -220,7 +223,7 @@ docs/blueprints/
| `AI_` | AI Controller | 1 |
| `BB_` | Blackboard | 1 |
| `E_` | Enum | 5 |
| **Total** | | **145** |
| **Total** | | **146** |
---
@@ -280,8 +283,9 @@ Below are the most cross-referenced systems — these are the ones the State Man
| `BPC_PerformanceScaler` | 91 | `BPC_PersistentCorpseSystem` | 40 | | |
| `BPC_PersistentWorldStateRecorder` | 41 | `BPC_PhysicsDragSystem` | 22 | | |
| `FL_GameUtilities` | 2 | `GI_GameFramework` | 4 | | |
| `GI_GameTagRegistry` | 1 | `GM_CoreGameMode` | 5 | | |
| `GS_CoreGameState` | 6 | `I_HidingSpot` | 17 | | |
| `GI_StarterGameInstance` | — | `GI_GameTagRegistry` | 1 | `GM_CoreGameMode` | 5 |
| `DA_GameTagRegistry` | 1 | `GM_CoreGameMode` | 5 | | |
| `GS_CoreGameState` | 6 | `HidingSpot` | 17 | | |
| `I_InterfaceLibrary` | 3 | `I_Persistable` | 36 | | |
| `SS_AchievementSystem` | 103 | `SS_EnhancedInputManager` | 128 | | |
| `SS_SaveManager` | 35 | `SS_SettingsSystem` | 105 | | |