diff --git a/CONTEXT.md b/CONTEXT.md index 905aa19..8b978b1 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -13,6 +13,7 @@ Single Source of Truth for the Unreal Engine 5.5-5.7 Blueprint-based Modular Gam - **Animation:** GASP Motion Matching + overlay notifies. Full catalog in [`docs/architecture/animation-catalog.md`](docs/architecture/animation-catalog.md) - **Audio:** 150+ sound triggers + 14-surface material table. Full catalog in [`docs/architecture/sound-catalog.md`](docs/architecture/sound-catalog.md) - **Networking:** Server-authoritative replication model. Full architecture in [`docs/architecture/multiplayer-networking.md`](docs/architecture/multiplayer-networking.md) +- **BP Limitations:** Catalog of C++-only UE5 functions + 100% Blueprint workarounds. See [`docs/architecture/blueprint-limitations-workarounds.md`](docs/architecture/blueprint-limitations-workarounds.md) ## Directory Structure ``` @@ -92,7 +93,7 @@ docs/ 09-ai-systems.md # AI, perception & encounters explained 10-adaptive-systems.md # Adaptive environment & atmosphere explained 11-16-systems.md # Meta, Settings, Polish, Data Assets, Input, State explained - architecture/ # Architecture & Design Documents (7 files) + architecture/ # Architecture & Design Documents (8 files) bpc-statemanager.md # BPC_StateManager full spec + Chooser Table Audit metasounds-audio-system.md # MetaSounds audio architecture (mix buses, room zones, settings) animation-catalog.md # Animation requirements for all 135 systems @@ -100,6 +101,7 @@ docs/ enhanced-input-system.md # Enhanced Input System architecture hud-overview.md # HUD system architecture — 14 widgets, wiring, integration points multiplayer-networking.md # Multiplayer networking architecture — authority model, RPCs, prediction + blueprint-limitations-workarounds.md # UE5 C++-only functions + 100% Blueprint workarounds (NEW) CLEAN_SLATE_PLAN.md # Clean slate refactoring plan reports/ # Condensed audit reports blueprint_condensed_summary.md # ASK agent audit of all 129 files @@ -108,7 +110,7 @@ docs/ enhanced-input-system.md bpc-statemanager.md # NEW — State Manager implementation checklist ``` -**Total: 135 numbered Blueprint files + 5 enums + 5 Data Assets + TEMPLATE.md + AUDIT_REPORT.md + INDEX.md + 11 developer docs + 7 architecture docs + 1 audit report = 165 files in 18 directory groups** +**Total: 135 numbered Blueprint files + 5 enums + 5 Data Assets + TEMPLATE.md + AUDIT_REPORT.md + INDEX.md + 11 developer docs + 8 architecture docs + 1 audit report = 166 files in 18 directory groups** ## Naming Conventions | Prefix | Type | @@ -190,6 +192,7 @@ Each file in `docs/blueprints/` follows the template defined in [`docs/blueprint 3. The relevant [`docs/developer/`](docs/developer/) category document — if the change modifies a system's behavior, dependencies, or implementation pattern 4. [`docs/architecture/animation-catalog.md`](docs/architecture/animation-catalog.md) — if the change adds/modifies animation requirements 5. [`docs/architecture/sound-catalog.md`](docs/architecture/sound-catalog.md) — if the change adds/modifies audio triggers or surfaces +6. [`docs/architecture/blueprint-limitations-workarounds.md`](docs/architecture/blueprint-limitations-workarounds.md) — if the change uses a new C++-only UE5 function that needs a Blueprint workaround No PR is accepted without these files being current. This ensures the animator, sound designer, developers, and all team members always have an up-to-date reference. diff --git a/docs/architecture/blueprint-limitations-workarounds.md b/docs/architecture/blueprint-limitations-workarounds.md new file mode 100644 index 0000000..889b748 --- /dev/null +++ b/docs/architecture/blueprint-limitations-workarounds.md @@ -0,0 +1,188 @@ +# UE5 Blueprint Limitations & Workarounds — Modular Game Framework + +**Version:** 1.0 | **Generated:** 2026-05-19 + +This document catalogs all UE5 engine functions that are C++ only (not exposed to Blueprints) which the framework's specification files reference, and provides 100% Blueprint workarounds for each. + +--- + +## 1. GameplayTags Limitations + +### 1.1 `Get All Gameplay Tags` (C++ Only) + +**Engine Function:** `UGameplayTagsManager::Get().RequestAllGameplayTags()` +**UE5 Node:** Does NOT exist in Blueprint +**Files Affected:** `01_GI_GameTagRegistry.md`, any system that needs to enumerate all tags + +**Blueprint Workaround — Data Table Proxy:** + +1. Create a Data Table: `DT_ProjectTags` with Row Structure = `GameplayTagTableRow` +2. Populate it with all framework tags (mirrors `DefaultGameplayTags.ini`) +3. Register in Project Settings → GameplayTags → Gameplay Tag Table List +4. In Blueprint: use `Get Data Table Row Names` → `ForEachLoop` → `Get Data Table Row` → extract `Tag` field +5. This provides a complete tag list without C++ + +**Trade-off:** Manual maintenance. Adding new tags requires updating both the `.ini` file AND the Data Table. Mitigation: use `ExportTagNamespace()` to audit for discrepancies. + +### 1.2 `RequestGameplayTag(String)` → GameplayTag (C++ Only) + +**Engine Function:** `UGameplayTagsManager::Get().RequestGameplayTag(FName)` +**UE5 Node:** Not directly available. The closest BP node is `Make Literal Gameplay Tag`. + +**Blueprint Workaround — Multiple options:** + +**Option A:** `Make Literal Gameplay Tag` — creates a GameplayTag from a literal string at compile time. Works only if the tag exists in the tag table. +**Option B:** `Is Gameplay Tag Valid` — for validation only (returns boolean). +**Option C:** `Get Gameplay Tag from Name` (available in some UE5 versions via `GameplayTagsBlueprintLibrary`). + +**Recommendation:** For `ValidateTag()` in `DA_GameTagRegistry`, use `Is Gameplay Tag Valid`. For runtime tag creation from strings, use `Make Literal Gameplay Tag` with fallback validation. + +### 1.3 `UGameplayTagsManager::Get()` Singleton (C++ Only) + +**Engine Pattern:** `UGameplayTagsManager::Get()` returns the singleton. +**UE5 Node:** Not available. The manager is accessed implicitly through GameplayTags Blueprint nodes. + +**Blueprint Workaround:** Never reference the manager directly. Use the Blueprint nodes listed above. All tag operations (match, compare, validate) have Blueprint equivalents. + +--- + +## 2. Subsystem Access Limitations + +### 2.1 Static Function Library Accessor Pattern (Requires C++ for Clean Implementation) + +**Pattern:** `FL_GameUtilities::GetUIManager()`, `FL_GameUtilities::GetInputManager()` +**Issue:** BlueprintFunctionLibrary static functions require C++ implementation for the static accessor pattern. In pure Blueprint, you cannot create a truly static accessor with clean syntax. + +**Blueprint Workaround:** + +Instead of `FL_GameUtilities::GetUIManager()`, use: +``` +Get Game Instance → Get Subsystem (SS_UIManager Class) +``` +OR create a Blueprint Macro Library with a macro that wraps the subsystem lookup. + +**Files Affected:** `02_FL_GameUtilities.md`, `44_SS_UIManager.md`, `128_SS_EnhancedInputManager.md` + +**Recommendation:** For a pure BP framework, document the direct `Get Game Instance → Get Subsystem` pattern. The FL_GameUtilities static accessors can be kept as documentation of the intent, but the implementation guide should show the direct BP node path. + +--- + +## 3. Data Asset Limitations + +### 3.1 `OnAssetLoaded` / `BeginPlay` on Data Assets (Not Available) + +**Engine Behavior:** `UPrimaryDataAsset` does not have `BeginPlay`, `Tick`, or event graphs. It's a pure data container. +**Files Affected:** `01_GI_GameTagRegistry.md`, all DA_* specs + +**Blueprint Workaround:** Move initialization and validation logic to an owning system: + +- **GameInstance** (`GI_GameFramework.Init()`) — load and validate Data Assets at game startup +- **Subsystem** (`BPC_StateManager.BeginPlay()`) — validate configuration during component init +- **Editor Utility** — create an Editor Utility Widget/Blueprint for pre-game validation + +**Pattern:** +``` +[In GI_GameFramework.Init()] + Load DA_GameTagRegistry (hard reference) + Call DA_GameTagRegistry.ValidateAllTags() + If failed → Print Error, optionally halt +``` + +### 3.2 `FPrimaryAssetId` / `FPrimaryAssetType` in Variables (Blueprint Types Exist) + +**Engine Types:** `FPrimaryAssetId`, `FPrimaryAssetType` +**Blueprint Equivalent:** `Primary Asset Id` (variable type), `Primary Asset Type` (variable type) + +**Workaround:** Use the Blueprint variable types `Primary Asset Id` and `Primary Asset Type`. The `Async Load Primary Asset` node works in Blueprint. Asset Manager configuration (types, labels) is done in `Project Settings → Asset Manager` or `DefaultGame.ini`. + +**Files Affected:** `07_DA_ItemData.md`, `118_DA_DataAssetArchitecture.md`, `119_DA_EncounterData.md`, `123_DA_ObjectiveData.md`, `27_BPC_CollectibleTracker.md` + +### 3.3 `AssetManager` / `StreamableManager` Async Loading (Blueprint Nodes Exist) + +**Blueprint Nodes Available:** +- `Async Load Primary Asset` — async loading with callback +- `Get Asset Manager` — returns the Asset Manager subsystem +- `Get Primary Asset Id List` — enumerates registered assets + +**⚠️ Limitation:** `UAssetManager::GetPrimaryAssetPath()` and some query functions are C++ only. For pure BP, use `Async Load Primary Asset` by `Primary Asset Id`. + +--- + +## 4. Animation & Physics Limitations + +### 4.1 Motion Warping Target Calculation (Blueprint Available) + +**UE5 Node:** `Add Motion Warping Target`, `Calculate Motion Warping Target` — these exist in Blueprint. + +**Files Affected:** `21_BPC_ContextualTraversalSystem.md` — no workaround needed, standard BP nodes available. + +### 4.2 Physics Constraint Component Creation at Runtime (Blueprint Available) + +**UE5 Node:** `Add Physics Constraint Component`, `Set Constrained Components` — available in Blueprint. + +**Files Affected:** `22_BPC_PhysicsDragSystem.md` — no workaround needed. + +--- + +## 5. Input System Limitations + +### 5.1 Enhanced Input Subsystem Access (Blueprint Available) + +**UE5 Node:** `Get Enhanced Input Local Player Subsystem`, `Add Mapping Context`, `Remove Mapping Context` — available in Blueprint. + +**Files Affected:** `128_SS_EnhancedInputManager.md` — no workaround needed. + +--- + +## 6. Debug & Development Limitations + +### 6.1 `DO_CHECK` / Preprocessor Stripping for Shipping (Requires C++ or Project Setting) + +**Issue:** C++ functions can use `#if !UE_BUILD_SHIPPING` to strip code from shipping builds. Blueprint functions can't do this natively. + +**Blueprint Workaround:** + +**Option A:** Editor-only Blueprint nodes — some nodes have an "Editor Only" checkbox. Mark debug functions as editor-only. +**Option B:** `Is Editor Build` branch — branch on `Is Editor` or development build check before executing debug logic. +**Option C:** Debug object channel — create a separate Blueprint with all debug logic; don't include it in shipping builds. + +**Files Affected:** `02_FL_GameUtilities.md`, `107_BPC_DevCheatManager.md`, `113_WBP_DebugMenu.md` + +**Recommendation:** Use `Is Editor Build` branch before all debug logic. Accept that some debug code will exist in shipping builds but be inactive at runtime. + +--- + +## 7. Quick Reference: Node Availability Map + +| Engine C++ Function | Available in BP? | BP Node Name | Workaround Needed? | +|---------------------|-----------------|--------------|-------------------| +| `UGameplayTagsManager::RequestAllGameplayTags()` | ❌ No | N/A | **Yes** — Data Table proxy | +| `UGameplayTagsManager::RequestGameplayTag()` | ⚠️ Partial | `Make Literal Gameplay Tag` | Use `Is Gameplay Tag Valid` for validation | +| `UGameplayTagsManager::Get()` | ❌ No | N/A | Never needed — use BP tag nodes | +| `GetSubsystem()` | ✅ Yes | `Get Subsystem (Class)` | No | +| `GetGameInstance()` | ✅ Yes | `Get Game Instance` | No | +| `UAssetManager::Get()` | ✅ Yes | `Get Asset Manager` | No | +| `StreamableManager::RequestAsyncLoad()` | ✅ Yes | `Async Load Primary Asset` | No | +| `CharacterMovementComponent` functions | ✅ Yes | Various BP nodes | No | +| `PlayerCameraManager` functions | ✅ Yes | `Get Player Camera Manager` | No | +| Enhanced Input functions | ✅ Yes | `Get Enhanced Input Local Player Subsystem` | No | +| Physics Constraint functions | ✅ Yes | `Add Physics Constraint Component` | No | +| `#if !UE_BUILD_SHIPPING` preprocessor | ❌ No | N/A | Use `Is Editor Build` branch | + +--- + +## 8. Implementation Rules for BP-Only Framework + +When writing or updating Blueprint spec files, follow these rules to avoid C++-only references: + +1. **Never reference `UGameplayTagsManager::Get()`** — use `Get Tag Display Name`, `Is Gameplay Tag Valid`, `Make Literal Gameplay Tag`. +2. **Never reference `Get All Gameplay Tags`** — use the Data Table proxy pattern (`DT_ProjectTags` → `Get Data Table Row Names`). +3. **Never use `FPrimaryAssetId` as a type name** — use `Primary Asset Id` (Blueprint type). +4. **Never use `TSoftObjectPtr` as a type name** — use `Soft Object Reference` (Blueprint type). +5. **Never put logic in Data Assets** — move initialization/validation to GameInstance, Subsystem, or Editor Utility. +6. **Never use C++ include guards or preprocessor** — use `Is Editor Build` for conditional logic. +7. **Prefer `Get Game Instance → Get Subsystem(Class)`** over static helper functions for subsystem access. + +--- + +*Blueprint Limitations & Workarounds v1.0 — Maintained alongside framework specs. Update when new engine limitations are discovered.* diff --git a/docs/blueprints/01-core/01_GI_GameTagRegistry.md b/docs/blueprints/01-core/01_GI_GameTagRegistry.md index 258d135..bae3e27 100644 --- a/docs/blueprints/01-core/01_GI_GameTagRegistry.md +++ b/docs/blueprints/01-core/01_GI_GameTagRegistry.md @@ -54,16 +54,16 @@ None. The registry is a flat collection of tag declarations. | Name | Inputs | Outputs | Category | Description | |------|--------|---------|----------|-------------| -| `GetAllRegisteredTags` | — | `Array` | Query | Returns all tags defined in this registry (reads from the project's tag table) | -| `GetTagDisplayName` | `Tag: FGameplayTag` | `FText` | Query | Returns the human-readable display name from the tag table | -| `ValidateTag` | `Tag: FGameplayTag` | `bool` | Validation | Returns `true` if the tag exists in the project's registered tag table | +| `GetAllRegisteredTags` | — | `Array` | Query | Reads tags from `DT_ProjectTags` Data Table (see Section 14 for UE5 BP workaround) | +| `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 registered tags to the output log (Editor-only) | -| `ExportTagNamespace` | `NamespacePrefix: FString` | `FString` | Tooling | Exports all tags matching a namespace prefix as a formatted string (for documentation generation) | +| `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 | | --- @@ -75,17 +75,82 @@ None. This Data Asset is passive — it has no runtime events. ## 8. Overridden Events -| Event | Description | -|-------|-------------| -| `OnAssetLoaded` | Logs a validation warning if no Gameplay Tags are registered in the project | -| `PreSaveGameplayTags` | Ensures the tag table is synchronised with the asset's documented namespaces | +**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 DT_ProjectTags! Framework tags are unregistered." + │ └─► No → Log: "N tags registered." + └─► Optional: call LogAllTags() for debug output +``` ## 9. Blueprint Graph Logic -### 9.1 Initialisation Flow +### 9.1 GetAllRegisteredTags (Data Table Proxy) +**⚠️ UE5 Limitation:** `UGameplayTagsManager::RequestAllGameplayTags()` is C++ only — not exposed to Blueprints. This function uses a **Data Table proxy** instead. Tags must be registered in `DT_ProjectTags` which mirrors `DefaultGameplayTags.ini`. + +``` +[Function: GetAllRegisteredTags] → Array + Step 1: Get Data Table Row Names (DT_ProjectTags) + Step 2: Create empty Array → LocalTags + Step 3: ForEachLoop (RowNames): + ├─► Get Data Table Row (DT_ProjectTags, RowName) + │ → Break the GameplayTagTableRow struct → get "Tag" field + ├─► Add "Tag" to LocalTags array + Step 4: Return LocalTags +``` + +**Node Search:** `Get Data Table Row Names`, `ForEachLoop`, `Get Data Table Row`, `Break GameplayTagTableRow`, `Add` + +### 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() @@ -179,104 +244,151 @@ This asset does not talk to other systems directly. All communication is passive ## 14. Manual Implementation Guide -> **For human implementer:** Follow these steps to build `DA_GameTagRegistry` in UE5. +> **For human implementer:** Follow these steps to build `DA_GameTagRegistry` in UE5 Blueprints. +> **⚠️ UE5 BP Limitation:** `UGameplayTagsManager::RequestAllGameplayTags()` is C++ only. This implementation uses a **Data Table proxy** (`DT_ProjectTags`) as the 100% Blueprint workaround. You must create and maintain `DT_ProjectTags` alongside your `DefaultGameplayTags.ini`. + +### 14.0 Prerequisite: Create the Tag Data Table + +Before implementing the Data Asset, create the proxy Data Table: + +1. Right-click in Content Browser → **Miscellaneous → Data Table** +2. Row Structure: `GameplayTagTableRow` +3. Name: `DT_ProjectTags` +4. Save to: `Content/Framework/Core/` +5. Add rows: one per tag (row name = anything, fill the "Tag" field with your GameplayTag) +6. Go to **Project Settings → GameplayTags → Gameplay Tag Table List** → click `+` → select `DT_ProjectTags` + - This auto-registers these 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` +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 | -|----------|------|------------------|---------| -| `TagNamespace` | `Text` | ✓ | *Framework tag namespace description* | -| `bIsFrameworkTag` | `Boolean` | ✓ | `true` | - -There are NO tag entries stored in this asset. Tags live in `Project Settings → GameplayTags` or `DefaultGameplayTags.ini`. +| Variable | Type | Instance Editable | Default | Category | +|----------|------|------------------|---------|----------| +| `TagNamespace` | `Text` | ✓ | *"Framework tag namespace documentation"* | Documentation | +| `bIsFrameworkTag` | `Boolean` | ✓ | `true` | Documentation | +| `TagDataTable` | `Data Table` (Object Reference) | ✓ | `DT_ProjectTags` | Config | ### 14.3 Function Implementations -#### `GetAllRegisteredTags` → `Array of GameplayTag` +#### `GetAllRegisteredTags()` → `Array` *(Blueprint Pure)* -**Purpose:** Returns every tag registered in the project. +**Purpose:** Returns all tags from the Data Table proxy. This replaces the C++-only `UGameplayTagsManager::RequestAllGameplayTags()`. -**Nodes to Use (Blueprint Implementable Function):** +**Node-by-Node Logic:** ``` -[Function: GetAllRegisteredTags] - └─ Get All Gameplay Tags (from GameplayTags subsystem) - └─ Return the array +[Function: GetAllRegisteredTags] (Pure, no execution pins) + Step 1: Get Data Table Row Names (TagDataTable) → returns Array + Step 2: Create empty Array → LocalTags + Step 3: ForEachLoop over RowNames: + ├─► Get Data Table Row (TagDataTable, Array Element) + │ → Struct Pin: Break GameplayTagTableRow + │ → Get "Tag" field (type: GameplayTag) + ├─► Add "Tag" to LocalTags array + Step 4: Return LocalTags ``` -**Node Search:** Right-click → "Get All Gameplay Tags" +**Nodes to Search:** `Get Data Table Row Names`, `ForEachLoop`, `Get Data Table Row`, `Break GameplayTagTableRow`, `Add`, `Array` -#### `GetTagDisplayName(Tag)` → `Text` +**⚠️ Note:** Since this is a **Pure** function, the ForEachLoop must be inside a **Pure function graph** (which supports loops in UE5). If your UE version doesn't support loops in Pure functions, make this a **BlueprintCallable** (impure) function instead. -**Nodes to Use (Blueprint Pure):** +#### `GetTagDisplayName(Tag: GameplayTag)` → `Text` *(Blueprint Pure)* + +**Node-by-Node Logic:** ``` [Function: GetTagDisplayName] - Input Tag → Get Tag Display Name (from GameplayTags) - └─ Return the text + Input Tag → Get Tag Display Name (Tag) → Return ``` -**Node Search:** Right-click → "Get Tag Display Name" +**Node Search:** `Get Tag Display Name` — this IS available in Blueprint (part of GameplayTags plugin). -#### `ValidateTag(Tag)` → `Boolean` +#### `ValidateTag(Tag: GameplayTag)` → `Boolean` *(Blueprint Pure)* -**Nodes to Use (Blueprint Pure / Callable):** +**⚠️ UE5 Limitation:** `UGameplayTagsManager::RequestGameplayTag()` is not directly available in BP. Use `Is Gameplay Tag Valid` instead. + +**Node-by-Node Logic:** ``` [Function: ValidateTag] - Input Tag → Is Valid Tag (from GameplayTags) - Branch on result: - True → Return true - False → Print Warning: "Invalid Tag: {Tag}" → Return false + Step 1: Is Gameplay Tag Valid (Tag) + ├─► True → Return true + └─► False → Print Warning: "Invalid Tag: " + Get Tag Name(Tag) → Return false ``` -**Node Search:** Right-click → "Is Gameplay Tag Valid" +**Node Search:** `Is Gameplay Tag Valid`, `Get Tag Name` -#### `LogAllTags` → *(void)* +**⚠️ Note:** `Is Gameplay Tag Valid` returns true only if the tag is registered in the engine's tag table (which `DT_ProjectTags` populates via Project Settings). Tags NOT in the table will return false. -**Blueprint Callable — Editor Only:** +#### `LogAllTags()` → *(void)* *(Blueprint Callable)* + +**Editor Only.** Prints all tags from the Data Table to the output log. + +**Node-by-Node Logic:** ``` [Function: LogAllTags] - ├─ Get All Gameplay Tags → ForEachLoop - │ └─ Print String: Tag.ToString() - └─ Print String: "Total tags: {Array Length}" + Step 1: Call GetAllRegisteredTags() → LocalTags + Step 2: ForEachLoop (LocalTags): + ├─► Get Tag Name (Array Element) → ToString → Print String + Step 3: Print String: "Total tags: " + Array Length(LocalTags) ``` -**Node Search:** Right-click → "ForEachLoop", "Print String" +**Node Search:** `ForEachLoop`, `Get Tag Name`, `ToString (String)`, `Print String`, `Array Length` -#### `ExportTagNamespace(NamespacePrefix)` → `String` +#### `ExportTagNamespace(NamespacePrefix: String)` → `String` *(Blueprint Callable)* -**Blueprint Callable:** +**Node-by-Node Logic:** ``` [Function: ExportTagNamespace] - ├─ Get All Gameplay Tags - ├─ ForEachLoop: - │ └─ Get Tag Name → ToString - │ └─ Does string start with NamespacePrefix? - │ True → Append to output string with newline - └─ Return output string + Step 1: Call GetAllRegisteredTags() → LocalTags + Step 2: Create String variable → Output = "" + Step 3: ForEachLoop (LocalTags): + ├─► Get Tag Name (Array Element) → ToString → TagString + ├─► Branch: Does TagString start with NamespacePrefix? (use "Starts With" string node) + │ True → Append TagString + "\n" to Output (use "Append" or "Build String") + └─► Continue + Step 4: Return Output ``` -### 14.4 Networking +**Node Search:** `Starts With (String)`, `Append`, `Build String`, `ForEachLoop` -No replication needed. This is a read-only Data Asset. All clients load identical copies from disk. +### 14.4 External Initialization -### 14.5 Blueprint Build Checklist +Since Data Assets have no `BeginPlay`, call validation from your GameInstance or StateManager: -- [ ] Create Data Asset: `DA_GameTagRegistry` (Parent: `PrimaryDataAsset`) -- [ ] Add `TagNamespace` (Text) and `bIsFrameworkTag` (Bool) variables -- [ ] Implement `GetAllRegisteredTags` function (Pure) -- [ ] Implement `GetTagDisplayName` function (Pure) -- [ ] Implement `ValidateTag` function (Pure) -- [ ] Implement `LogAllTags` (Editor-only) -- [ ] Implement `ExportTagNamespace` (Tooling) -- [ ] Document all tag namespaces in the asset's Description field (use Section 10 as reference) -- [ ] Verify: all tag namespaces from Section 10 exist in `DefaultGameplayTags.ini` +**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 DT_ProjectTags!" + └─► 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 Data Table `DT_ProjectTags` (Row Structure: `GameplayTagTableRow`) +- [ ] Populate `DT_ProjectTags` with all framework tags from Section 10 +- [ ] Add `DT_ProjectTags` to `Project Settings → GameplayTags → Gameplay Tag Table List` +- [ ] Create Data Asset `DA_GameTagRegistry` (Parent: `PrimaryDataAsset`) +- [ ] Add variables: `TagNamespace` (Text), `bIsFrameworkTag` (Boolean), `TagDataTable` (Data Table Ref → DT_ProjectTags) +- [ ] Implement `GetAllRegisteredTags` using Data Table Row iteration +- [ ] Implement `GetTagDisplayName` using `Get Tag Display Name` node +- [ ] Implement `ValidateTag` using `Is Gameplay Tag Valid` node +- [ ] Implement `LogAllTags` (editor-only, prints all tags) +- [ ] Implement `ExportTagNamespace` (string prefix filtering) +- [ ] Add external initialization call from `GI_GameFramework.Init()` or `BPC_StateManager.BeginPlay()` +- [ ] Verify: all tags from Section 10 exist in `DT_ProjectTags` +- [ ] Verify: `ValidateTag` returns true for registered tags, false for unregistered ---