# FL_GameUtilities — Blueprint Function Library

> **⚡ C++ Status: Full Implementation** — `Source/PG_Framework/Public/Core/FL_GameUtilities.h` provides all utility functions (subsystem access, math, tags, text, screen, debug). All functions are `BlueprintCallable` — they appear under `Framework|Utilities` in every BP right-click menu. **Nothing to build.** The spec below documents each function's API for reference. The old "Blueprint-Only Alternative" section is kept for context but is no longer needed — the C++ class is the canonical implementation. See `docs/developer/cpp-integration-guide.md` for usage patterns.
>
> ---

## Asset Details

| Property | Value |
|----------|-------|
| **Class** | [`FL_GameUtilities`] |
| **Parent** | [`BlueprintFunctionLibrary`] |

> **⚠️ UE5 BP Limitation:** `BlueprintFunctionLibrary` requires C++ to create. This is the ONE file in the framework that needs a minimal C++ class. See Section "Blueprint-Only Alternative" below for the pure BP workaround using Macro Library + direct engine nodes.
| **Folder** | [`Framework/Core/`] |
| **Categorization** | [Core\Framework] |

## Purpose

A static Blueprint Function Library providing common utility functions available everywhere in the project without needing an object reference. Every Blueprint, component, widget, and AI asset can call these functions directly from the context menu.

## Does NOT Handle

- Game logic or state management
- Actor spawning or lifecycle
- Data asset lookups (those belong to the specific system)
- Any operation that requires a persistent reference or tick

## Structs

No structs are defined in this library. All input/output types are native Blueprint types or interface-derived.

## Enums

No enums are defined in this library.

## Variables

This is a pure Function Library. It has **no variables, no event dispatchers, no tick**. All functions are static and context-free (with the exception of `WorldContextObject` for world-dependent operations).

## Functions

### Utility — Null-Safe Subsystem Retrieval

| Function | Category | Inputs | Outputs | Description |
|----------|----------|--------|---------|-------------|
| [`GetSubsystemSafe`] | Utility\Subsystems | `WorldContextObject: Object`, `SubsystemClass: Class` | `Subsystem: Object` | Null-safe subsystem retrieval. Returns `None` instead of crashing if the subsystem doesn't exist. |
| [`GetGameFramework`] | Utility\Subsystems | `WorldContextObject: Object` | `GameInstance: GI_GameFramework Object` | Typed cast to [`GI_GameFramework`](04_GI_GameFramework.md). Returns `None` if cast fails. Includes error log. |
| [`GetPlayerController`] | Utility\Subsystems | `WorldContextObject: Object` | `Controller: PC_CoreController Object` | Typed cast to [`PC_CoreController`](02-player/01_PC_CoreController.md). Returns `None` if cast fails. Includes error log. |

### Actor Utility

| Function | Category | Inputs | Outputs | Description |
|----------|----------|--------|---------|-------------|
| [`FindComponentByInterface`] | Actor\Components | `TargetActor: Actor`, `InterfaceClass: Interface` | `Component: ActorComponent` | Returns the first component on the given actor that implements the specified interface. Returns `None` if none found. |
| [`FindNearestActorWithTag`] | Actor\Spatial | `Origin: Vector`, `Radius: Float`, `Tag: GameplayTag`, `ActorsToIgnore: Array Actor` | `NearestActor: Actor`, `Distance: Float` | Scans all actors within radius for those with the given gameplay tag. Returns the closest one. |

### Math Utilities

| Function | Category | Inputs | Outputs | Description |
|----------|----------|--------|---------|-------------|
| [`RemapFloat`] | Math\Float | `Value: Float`, `InMin: Float`, `InMax: Float`, `OutMin: Float`, `OutMax: Float` | `Result: Float` | Linear remap from input range to output range. Clamped to output range. |
| [`LerpClamped`] | Math\Float | `A: Float`, `B: Float`, `Alpha: Float` | `Result: Float` | Lerp with alpha clamped 0-1. |
| [`VectorToAngle2D`] | Math\Vector | `Direction: Vector` | `Angle: Float (Degrees)` | Converts a 2D direction vector to an angle in degrees (0-360). |
| [`AngleDifference`] | Math\Float | `AngleA: Float`, `AngleB: Float` | `Difference: Float` | Shortest signed angle between two angles. |

### Gameplay Tag Utilities

| Function | Category | Inputs | Outputs | Description |
|----------|----------|--------|---------|-------------|
| [`HasGameplayTag`] | GameplayTags\Query | `TargetActor: Actor`, `Tag: GameplayTag` | `bHasTag: Bool` | Safe check if an actor's gameplay tag container includes the specified tag. Returns false if actor has no tag container. |
| [`AddGameplayTagToActor`] | GameplayTags\Modify | `TargetActor: Actor`, `Tag: GameplayTag` | — | Adds a gameplay tag to the actor's tag container if it implements the interface. Logs warning if missing. |
| [`RemoveGameplayTagFromActor`] | GameplayTags\Modify | `TargetActor: Actor`, `Tag: GameplayTag` | — | Removes a gameplay tag from the actor's tag container. |
| [`MakeTagFromString`] | GameplayTags\Conversion | `TagString: String` | `Tag: GameplayTag` | Converts a string to a GameplayTag. Returns `None` if the tag doesn't exist in the tag table. |
| [`TagContainerHasAny`] | GameplayTags\Query | `Container: GameplayTagContainer`, `TagsToCheck: GameplayTagContainer` | `bHasAny: Bool` | OR query: true if container has any of the specified tags. |

### String & Text Formatting

| Function | Category | Inputs | Outputs | Description |
|----------|----------|--------|---------|-------------|
| [`FormatTime`] | Text\Formatting | `TotalSeconds: Float` | `FormattedText: Text` | Converts seconds to "HH:MM:SS" or "MM:SS" display format. |
| [`Pluralise`] | Text\Formatting | `Count: Integer`, `Singular: Text`, `Plural: Text` | `Result: Text` | Returns singular or plural form based on count. |
| [`OrdinalSuffix`] | Text\Formatting | `Number: Integer` | `Suffix: String` | Returns "st", "nd", "rd", or "th" for a given number. |
| [`TruncateText`] | Text\Formatting | `Input: Text`, `MaxChars: Integer` | `Output: Text`, `bTruncated: Bool` | Truncates text with "..." if exceeding max length. |

### Screen & Viewport Utilities

| Function | Category | Inputs | Outputs | Description |
|----------|----------|--------|---------|-------------|
| [`WorldToScreenSafe`] | Screen\Conversion | `WorldContext: Object`, `WorldLocation: Vector` | `ScreenPosition: Vector2D`, `bIsOnScreen: Bool` | Projects world location to screen coordinates. Returns false if behind camera or off-screen. |
| [`ClampToViewport`] | Screen\Conversion | `WidgetPosition: Vector2D`, `Padding: Float` | `ClampedPosition: Vector2D` | Clamps a widget position to stay within the viewport bounds with padding. |

### Debug Helpers

| Function | Category | Inputs | Outputs | Description |
|----------|----------|--------|---------|-------------|
| [`LogDebug`] | Debug\Logging | `Category: Name`, `Message: String`, `Color: LinearColor`, `WorldContext: Object` | — | Conditional screen + log output. Uses `Branch: Is Editor Build` → then Print String + Draw Debug String. Inactive in shipping builds. |
| [`DrawDebugSphere`] | Debug\Drawing | `WorldContext: Object`, `Center: Vector`, `Radius: Float`, `Color: LinearColor`, `Duration: Float` | — | Draws a debug sphere. **BP node exists:** `Draw Debug Sphere`. Stripped in shipping. |
| [`DrawDebugString3D`] | Debug\Drawing | `WorldContext: Object`, `Location: Vector`, `Text: String`, `Color: LinearColor`, `Duration: Float` | — | Draws 3D world-space debug string. **BP node exists:** `Draw Debug String`. Stripped in shipping. |

## Blueprint Flow

```
[Any Blueprint calls FL_GameUtilities function]
  └─► Function executes immediately (no async)
  └─► Returns value or performs side effect
  └─► Caller uses result in next node
```

Since this is a pure static library, there is no lifecycle. Every function is callable from any Blueprint's event graph, construction script, or function.

## Communicates With

| Target System | Method | Why |
|---------------|--------|-----|
| [`GI_GameFramework`](04_GI_GameFramework.md) | Direct cast | `GetGameFramework()` helper |
| [`PC_CoreController`](02-player/01_PC_CoreController.md) | Direct cast | `GetPlayerController()` helper |
| Any Actor | Interface + Tag | Actor utility functions |

## Blueprint Editor Usage

### How to Call

1. Right-click in any Event Graph or Function.
2. Search for the function name (e.g. `RemapFloat`, `FormatTime`).
3. The functions appear under their category name in the context menu.
4. Wire inputs and use output.

### Construction Script Usage

All functions can be called from Construction Scripts since they are pure (no world context required for math/text functions). Functions requiring `WorldContextObject` pass the `Self` reference from the construction script context.

## Reuse Notes

- This library ships as a minimal C++ `BlueprintFunctionLibrary` (required for static function libraries in UE5).
- Add project-specific helpers in a separate child library or Macro Library.
- Do **not** add game-specific functions here — extend with a new library.
- For a 100% Blueprint approach, see "Blueprint-Only Alternative" below.

## Success Criteria

1. Any Blueprint can call `RemapFloat` from the Math category without errors.
2. `GetSubsystemSafe` returns `None` instead of crashing when a subsystem doesn't exist.
3. `FormatTime(3661.0)` returns `01:01:01`.
4. `LogDebug` prints to both the output log and the viewport in editor builds.
5. `LogDebug` produces no output in a shipping build (via `Is Editor Build` branch).

## Blueprint-Only Alternative

If you cannot compile C++, replace `FL_GameUtilities` with direct Blueprint nodes or a **Blueprint Macro Library**:

| FL_GameUtilities Function | Pure BP Equivalent (no C++ needed) |
|--------------------------|-----------------------------------|
| `GetSubsystemSafe` | `Get Game Instance` → `Get Subsystem (Class)` → `Is Valid` branch |
| `GetGameFramework` | `Get Game Instance` → `Cast to GI_GameFramework` |
| `GetPlayerController` | `Get Player Controller (0)` → `Cast to PC_CoreController` |
| `HasGameplayTag` | `Does Actor Have Tag` (BP node) |
| `AddGameplayTagToActor` | `Get Actor Gameplay Tag Container` → `Add Tag` |
| `RemoveGameplayTagFromActor` | `Get Actor Gameplay Tag Container` → `Remove Tag` |
| `MakeTagFromString` | `Make Literal Gameplay Tag` OR `Get Gameplay Tag from Name` |
| `FindComponentByInterface` | `Get Component by Class` + `Does Implement Interface` |
| `RemapFloat` | `Map Range Clamped` (built-in BP math node) |
| `LerpClamped` | `Lerp` + `Clamp (Float)` |
| `FormatTime` | Custom BP function using division/modulo |
| `LogDebug` | `Branch: Is Editor Build` → `Print String` |
| `DrawDebugSphere` | `Draw Debug Sphere` (built-in BP node) |
| `DrawDebugString3D` | `Draw Debug String` (built-in BP node) |

**Blueprint Macro Library:** Create a **Macro Library** asset (`Content/Framework/Core/ML_GameUtilities`). Macros support `WorldContext`, execution pins, and can call engine nodes — no C++ required. The trade-off: macros are NOT "static pure" — they need execution flow pins.

---

## Multiplayer Networking

**Replication: None needed.** This is a static BlueprintFunctionLibrary with no state. All functions are callable from any Blueprint on any side (client or server).

**Authority: N/A.** Functions are context-free. World-context operations work identically on server and client.

**Note:** `GetSubsystemSafe()` returns local subsystems. On clients, only client-side subsystems are available. Never rely on a server-only subsystem being available on a client.