feat: Add Enhanced Input Manager for context management and key rebinding
- Implemented USS_EnhancedInputManager to manage input contexts with priority. - Added methods for pushing, popping, and querying input contexts. - Integrated input mode switching and key rebinding functionality. feat: Introduce Inventory System Component for item management - Created UBPC_InventorySystem to handle inventory operations such as adding, removing, and sorting items. - Implemented weight management and slot organization features. - Added event dispatchers for inventory changes. feat: Develop Item Data Asset for item definitions - Established UDA_ItemData as a base class for all items, encapsulating properties like type, weight, and stack limits. - Included conditional sub-data structures for equipment, consumables, and inspect data. feat: Create State Manager Component for player state management - Developed UBPC_StateManager to manage player action states and overlays. - Implemented gating logic for action requests and vital sign tracking. feat: Implement Save Manager for game state persistence - Introduced USS_SaveManager for handling save/load operations and slot management. - Utilized FArchive for efficient binary serialization. feat: Implement Damage Reception System for combat mechanics - Created UBPC_DamageReceptionSystem to process incoming damage and apply resistance calculations. - Added event dispatchers for damage reception and hit reactions.
This commit is contained in:
105
Source/Framework/Public/Core/DA_GameTagRegistry.h
Normal file
105
Source/Framework/Public/Core/DA_GameTagRegistry.h
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — DA_GameTagRegistry (01)
|
||||
// Central gameplay tag registry Data Asset. Eliminates the 3 C++-only API workarounds
|
||||
// (RequestAllGameplayTags, RequestGameplayTag, UGameplayTagsManager singleton access).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Engine/DataTable.h"
|
||||
#include "DA_GameTagRegistry.generated.h"
|
||||
|
||||
/**
|
||||
* DA_GameTagRegistry — Central GameplayTag namespace registry.
|
||||
*
|
||||
* In C++, this directly wraps UGameplayTagsManager APIs instead of using the
|
||||
* Data Table proxy workaround required in Blueprint. Maintains the Data Table
|
||||
* references for the Blueprint implementation guide, but the C++ functions
|
||||
* bypass them entirely for performance and correctness.
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, meta = (DisplayName = "DA_GameTagRegistry"))
|
||||
class FRAMEWORK_API UDA_GameTagRegistry : public UPrimaryDataAsset
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UDA_GameTagRegistry();
|
||||
|
||||
// ========================================================================
|
||||
// Configuration
|
||||
// ========================================================================
|
||||
|
||||
/** Human-readable description of the tag namespace (e.g. "Player.State"). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Documentation")
|
||||
FText TagNamespace;
|
||||
|
||||
/** True for framework-defined tags, false for project-specific overrides. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Documentation")
|
||||
bool bIsFrameworkTag = true;
|
||||
|
||||
/**
|
||||
* Array of 11 per-category Data Tables used by Blueprint implementations.
|
||||
* C++ functions use UGameplayTagsManager directly and ignore this array.
|
||||
* Maintained for the Blueprint Manual Implementation Guide.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Config")
|
||||
TArray<TObjectPtr<UDataTable>> TagDataTables;
|
||||
|
||||
// ========================================================================
|
||||
// Query Functions
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Returns ALL registered gameplay tags from the engine's tag manager.
|
||||
* C++ implementation: single call to UGameplayTagsManager.
|
||||
* Blueprint equivalent: nested ForEachLoop over 11 Data Tables (workaround).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Tags|Query")
|
||||
TArray<FGameplayTag> GetAllRegisteredTags() const;
|
||||
|
||||
/**
|
||||
* Returns the human-readable display name of a gameplay tag.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Tags|Query")
|
||||
FText GetTagDisplayName(const FGameplayTag& Tag) const;
|
||||
|
||||
/**
|
||||
* Validates whether a gameplay tag is registered in the engine's tag table.
|
||||
* Returns false + logs warning for unregistered tags.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Tags|Validation")
|
||||
bool ValidateTag(const FGameplayTag& Tag) const;
|
||||
|
||||
/**
|
||||
* Validates that a tag exists AND returns it. Fails gracefully with warning.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Tags|Validation")
|
||||
FGameplayTag RequestTag(FName TagName, bool bLogWarning = true) const;
|
||||
|
||||
// ========================================================================
|
||||
// Debug / Tooling
|
||||
// ========================================================================
|
||||
|
||||
/** Prints all registered tags to the output log. Editor-only. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Tags|Debug")
|
||||
void LogAllTags() const;
|
||||
|
||||
/**
|
||||
* Exports all tags matching a namespace prefix as a formatted string.
|
||||
* Useful for auditing discrepancies between Data Tables and DefaultGameplayTags.ini.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Tags|Tooling")
|
||||
FString ExportTagNamespace(const FString& NamespacePrefix) const;
|
||||
|
||||
// ========================================================================
|
||||
// Overrides
|
||||
// ========================================================================
|
||||
|
||||
virtual void PostLoad() override;
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
#endif
|
||||
};
|
||||
169
Source/Framework/Public/Core/FL_GameUtilities.h
Normal file
169
Source/Framework/Public/Core/FL_GameUtilities.h
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — FL_GameUtilities (02)
|
||||
// Shared Blueprint Function Library. In C++, all functions are static template/inline
|
||||
// with proper null-safety — no BP workarounds needed.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "FL_GameUtilities.generated.h"
|
||||
|
||||
class UGI_GameFramework;
|
||||
class APC_CoreController;
|
||||
|
||||
/**
|
||||
* FL_GameUtilities — Static utility functions available from any Blueprint or C++.
|
||||
*
|
||||
* In C++, these are proper static functions with template type-safety.
|
||||
* The Blueprint version requires macro wrappers for subsystem access —
|
||||
* here we get clean UFUNCTION(BlueprintCallable) with fast native paths.
|
||||
*/
|
||||
UCLASS()
|
||||
class FRAMEWORK_API UFL_GameUtilities : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// ========================================================================
|
||||
// Subsystem Access (Null-Safe)
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Safe subsystem retrieval — returns nullptr instead of crashing.
|
||||
* Use this instead of raw GetSubsystem() everywhere.
|
||||
*/
|
||||
template<typename T>
|
||||
static T* GetSubsystemSafe(const UObject* WorldContextObject)
|
||||
{
|
||||
if (!WorldContextObject)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("FL_GameUtilities::GetSubsystemSafe — Invalid WorldContextObject"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const UGameInstance* GameInstance = WorldContextObject->GetWorld()->GetGameInstance();
|
||||
if (!GameInstance)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("FL_GameUtilities::GetSubsystemSafe — No GameInstance found"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
T* Subsystem = GameInstance->GetSubsystem<T>();
|
||||
if (!Subsystem)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("FL_GameUtilities::GetSubsystemSafe — Subsystem '%s' not found"),
|
||||
*T::StaticClass()->GetName());
|
||||
}
|
||||
|
||||
return Subsystem;
|
||||
}
|
||||
|
||||
// Blueprint-accessible subsystem getters (UFUNCTION wrappers for the template)
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Utilities",
|
||||
meta = (WorldContext = "WorldContextObject"))
|
||||
static UGI_GameFramework* GetGameFramework(const UObject* WorldContextObject);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Utilities",
|
||||
meta = (WorldContext = "WorldContextObject", DeterminesOutputType = "SubsystemClass"))
|
||||
static UGameInstanceSubsystem* GetSubsystemByClass(const UObject* WorldContextObject,
|
||||
TSubclassOf<UGameInstanceSubsystem> SubsystemClass);
|
||||
|
||||
// ========================================================================
|
||||
// Actor Utilities
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Finds the first component on an actor that implements a given interface.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Utilities")
|
||||
static UActorComponent* FindComponentByInterface(AActor* Actor,
|
||||
TSubclassOf<UInterface> InterfaceClass);
|
||||
|
||||
/**
|
||||
* Finds the nearest actor within a radius that has a specific gameplay tag.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Utilities",
|
||||
meta = (WorldContext = "WorldContextObject"))
|
||||
static AActor* FindNearestActorWithTag(const UObject* WorldContextObject,
|
||||
FVector Origin, float Radius, FGameplayTag RequiredTag);
|
||||
|
||||
// ========================================================================
|
||||
// Math Utilities
|
||||
// ========================================================================
|
||||
|
||||
/** Remap a value from [InMin, InMax] to [OutMin, OutMax]. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Math")
|
||||
static float RemapFloat(float Value, float InMin, float InMax, float OutMin, float OutMax);
|
||||
|
||||
/** Linear interpolation clamped to [0, 1]. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Math")
|
||||
static float LerpClamped(float A, float B, float Alpha);
|
||||
|
||||
/** Convert a direction vector to a 2D angle in degrees. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Math")
|
||||
static float VectorToAngle2D(FVector2D Direction);
|
||||
|
||||
/** Shortest signed angle difference between two angles in degrees. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Math")
|
||||
static float AngleDifference(float A, float B);
|
||||
|
||||
// ========================================================================
|
||||
// GameplayTag Utilities
|
||||
// ========================================================================
|
||||
|
||||
/** Safe gameplay tag check — returns false if actor has no tag container. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Tags")
|
||||
static bool HasGameplayTag(AActor* Actor, FGameplayTag Tag);
|
||||
|
||||
/**
|
||||
* Creates a gameplay tag from a string with validation.
|
||||
* Returns EmptyTag and logs warning if the tag isn't registered.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Tags")
|
||||
static FGameplayTag MakeTagFromString(const FString& TagString, bool bLogWarning = true);
|
||||
|
||||
// ========================================================================
|
||||
// Text Utilities
|
||||
// ========================================================================
|
||||
|
||||
/** Format seconds into HH:MM:SS string. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Text")
|
||||
static FText FormatTime(float TotalSeconds);
|
||||
|
||||
/** Returns singular or plural form based on count. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Text")
|
||||
static FText Pluralise(const FText& Singular, const FText& Plural, int32 Count);
|
||||
|
||||
/** Truncates text to MaxLength with ellipsis. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Text")
|
||||
static FText TruncateText(const FText& Text, int32 MaxLength);
|
||||
|
||||
// ========================================================================
|
||||
// Screen / Projection Utilities
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Projects a world position to screen space.
|
||||
* bIsOnScreen is false if the point is behind the camera.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Screen",
|
||||
meta = (WorldContext = "WorldContextObject"))
|
||||
static bool WorldToScreenSafe(const UObject* WorldContextObject, FVector WorldPosition,
|
||||
FVector2D& OutScreenPosition, bool& bIsOnScreen);
|
||||
|
||||
// ========================================================================
|
||||
// Debug (Shipping-safe)
|
||||
// ========================================================================
|
||||
|
||||
/** Debug log — stripped from shipping builds. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Debug")
|
||||
static void DebugLog(const FString& Message, bool bPrintToScreen = false,
|
||||
float ScreenDuration = 5.0f, FColor ScreenColor = FColor::Cyan);
|
||||
|
||||
/** Draw debug sphere in world — stripped from shipping builds. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Debug")
|
||||
static void DebugSphere(const UObject* WorldContextObject, FVector Location,
|
||||
float Radius = 50.0f, FColor Color = FColor::Green, float Duration = 5.0f);
|
||||
};
|
||||
226
Source/Framework/Public/Core/GI_GameFramework.h
Normal file
226
Source/Framework/Public/Core/GI_GameFramework.h
Normal file
@@ -0,0 +1,226 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — GI_GameFramework (04)
|
||||
// Application kernel GameInstance. Owns all SS_ subsystems, manages game phases,
|
||||
// platform initialization, save slot ownership, and service resolution.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "GI_GameFramework.generated.h"
|
||||
|
||||
// Forward declarations
|
||||
class UDA_GameTagRegistry;
|
||||
class USS_SaveManager;
|
||||
class USS_UIManager;
|
||||
class USS_SettingsSystem;
|
||||
class USS_EnhancedInputManager;
|
||||
class USS_AchievementSystem;
|
||||
class USS_AudioManager;
|
||||
|
||||
/**
|
||||
* Game Phase — top-level application state.
|
||||
* Transitions are server-authoritative; clients receive via OnRep_GamePhase.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EGamePhase : uint8
|
||||
{
|
||||
MainMenu UMETA(DisplayName = "Main Menu"),
|
||||
Loading UMETA(DisplayName = "Loading"),
|
||||
InGame UMETA(DisplayName = "In Game"),
|
||||
Paused UMETA(DisplayName = "Paused"),
|
||||
Cutscene UMETA(DisplayName = "Cutscene"),
|
||||
DeathLoop UMETA(DisplayName = "Death Loop"),
|
||||
AltDeathSpace UMETA(DisplayName = "Alt Death Space"),
|
||||
Credits UMETA(DisplayName = "Credits"),
|
||||
PostGame UMETA(DisplayName = "Post Game"),
|
||||
};
|
||||
|
||||
/** Platform type for platform-specific initialization routing. */
|
||||
UENUM(BlueprintType)
|
||||
enum class EPlatformType : uint8
|
||||
{
|
||||
Generic UMETA(DisplayName = "Generic (PC)"),
|
||||
Steam UMETA(DisplayName = "Steam"),
|
||||
PS5 UMETA(DisplayName = "PlayStation 5"),
|
||||
Xbox UMETA(DisplayName = "Xbox Series X|S"),
|
||||
Switch UMETA(DisplayName = "Nintendo Switch"),
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Delegates (Event Dispatchers)
|
||||
// ============================================================================
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGamePhaseChanged, EGamePhase, NewPhase);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnPlatformReady);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnFrameworkReady);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFrameworkInitFailed, const FString&, ErrorReason);
|
||||
|
||||
/**
|
||||
* GI_GameFramework — Application Kernel.
|
||||
*
|
||||
* The single persistent object that lives for the entire application session.
|
||||
* Owns all SS_ GameInstanceSubsystems, manages save slot ownership, provides
|
||||
* the canonical service resolver (GetService()), and tracks the top-level
|
||||
* game phase state machine.
|
||||
*
|
||||
* In C++, this replaces the Blueprint "Get Game Instance → Cast → Get Subsystem"
|
||||
* pattern with clean template access via GetService<T>().
|
||||
*/
|
||||
UCLASS()
|
||||
class FRAMEWORK_API UGI_GameFramework : public UGameInstance
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGI_GameFramework();
|
||||
|
||||
// ========================================================================
|
||||
// Lifecycle
|
||||
// ========================================================================
|
||||
|
||||
virtual void Init() override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
// ========================================================================
|
||||
// Configuration
|
||||
// ========================================================================
|
||||
|
||||
/** Hard reference to the tag registry Data Asset. Loaded during Init. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Framework|Config")
|
||||
TObjectPtr<UDA_GameTagRegistry> TagRegistry;
|
||||
|
||||
/** If true, validates all tags during Init. Recommended: true for development. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Framework|Config")
|
||||
bool bValidateTagsOnInit = true;
|
||||
|
||||
/** If true, logs all registered tags to the output log during Init. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Framework|Debug")
|
||||
bool bLogTagsOnInit = false;
|
||||
|
||||
/** Platform override. Determined automatically; can be overridden via command-line: -Platform=Steam */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Framework|Platform")
|
||||
EPlatformType PlatformType = EPlatformType::Generic;
|
||||
|
||||
// ========================================================================
|
||||
// Game Phase State Machine
|
||||
// ========================================================================
|
||||
|
||||
/** Current top-level game phase. Server-authoritative; replicated to clients. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Framework|State")
|
||||
EGamePhase CurrentGamePhase = EGamePhase::MainMenu;
|
||||
|
||||
/**
|
||||
* Sets the game phase and broadcasts OnGamePhaseChanged.
|
||||
* Server-authoritative. No-ops if phase is unchanged.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|State")
|
||||
void SetGamePhase(EGamePhase NewPhase);
|
||||
|
||||
/** Returns whether the framework has completed initialization. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|State")
|
||||
bool IsFrameworkReady() const { return bFrameworkInitialized; }
|
||||
|
||||
// ========================================================================
|
||||
// Session Flags (Transient, Non-Persisted)
|
||||
// ========================================================================
|
||||
|
||||
/** Gets a session flag value. Returns false if the flag doesn't exist. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Session")
|
||||
bool GetSessionFlag(FGameplayTag FlagTag) const;
|
||||
|
||||
/** Sets a session flag. Creates it if it doesn't exist. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Session")
|
||||
void SetSessionFlag(FGameplayTag FlagTag, bool bValue);
|
||||
|
||||
/** Clears all session flags. Called on new game start. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Session")
|
||||
void ClearAllSessionFlags();
|
||||
|
||||
// ========================================================================
|
||||
// Save Slot Management
|
||||
// ========================================================================
|
||||
|
||||
/** Currently active save slot index (-1 = none). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Framework|Save")
|
||||
int32 ActiveSlotIndex = -1;
|
||||
|
||||
/** Designates the active save slot. Does NOT trigger a load. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Save")
|
||||
void SetActiveSlot(int32 SlotIndex);
|
||||
|
||||
// ========================================================================
|
||||
// Service Resolution
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Canonical subsystem accessor. Maps a GameplayTag to a subsystem class.
|
||||
* Returns nullptr and logs warning if tag isn't mapped or subsystem unavailable.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Services")
|
||||
UGameInstanceSubsystem* GetService(FGameplayTag ServiceTag) const;
|
||||
|
||||
/** Template accessor for type-safe subsystem retrieval. */
|
||||
template<typename T>
|
||||
T* GetService() const
|
||||
{
|
||||
return GetSubsystem<T>();
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// First-Launch State
|
||||
// ========================================================================
|
||||
|
||||
/** True until onboarding/intro sequence clears it. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Framework|State")
|
||||
bool bFirstLaunch = true;
|
||||
|
||||
// ========================================================================
|
||||
// Event Dispatchers
|
||||
// ========================================================================
|
||||
|
||||
/** Broadcast when game phase changes. All systems react to this — never poll CurrentGamePhase. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnGamePhaseChanged OnGamePhaseChanged;
|
||||
|
||||
/** Broadcast when platform-specific initialization is complete. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnPlatformReady OnPlatformReady;
|
||||
|
||||
/** Broadcast when framework initialization is complete and tag registry is validated. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnFrameworkReady OnFrameworkReady;
|
||||
|
||||
/** Broadcast if framework initialization fails (missing tag registry, zero tags, etc.). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnFrameworkInitFailed OnFrameworkInitFailed;
|
||||
|
||||
protected:
|
||||
// ========================================================================
|
||||
// Internal State
|
||||
// ========================================================================
|
||||
|
||||
bool bFrameworkInitialized = false;
|
||||
|
||||
/** Map of GameplayTag → bool for session-scoped flags. */
|
||||
UPROPERTY()
|
||||
TMap<FGameplayTag, bool> SessionFlags;
|
||||
|
||||
/** Maps service GameplayTags to subsystem classes. Populated during Init. */
|
||||
UPROPERTY()
|
||||
TMap<FGameplayTag, TSubclassOf<UGameInstanceSubsystem>> ServiceRegistry;
|
||||
|
||||
// ========================================================================
|
||||
// Internal Methods
|
||||
// ========================================================================
|
||||
|
||||
/** Platform-specific initialization routing. */
|
||||
void InitPlatformServices();
|
||||
|
||||
/** Validates the tag registry and logs results. */
|
||||
void ValidateFrameworkTags();
|
||||
|
||||
/** Builds the ServiceRegistry map of GameplayTag → SubsystemClass. */
|
||||
void RegisterServices();
|
||||
};
|
||||
127
Source/Framework/Public/Core/GM_CoreGameMode.h
Normal file
127
Source/Framework/Public/Core/GM_CoreGameMode.h
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — GM_CoreGameMode (05)
|
||||
// Core Game Mode. Server-authoritative session rules, player spawning, chapter
|
||||
// transitions, death routing. In C++, extends the replicated GameMode base for
|
||||
// full networking support.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "GM_CoreGameMode.generated.h"
|
||||
|
||||
// Forward declarations
|
||||
class UGI_GameFramework;
|
||||
class AGS_CoreGameState;
|
||||
class APC_CoreController;
|
||||
class APS_CorePlayerState;
|
||||
|
||||
// Delegates
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnChapterTransition, FGameplayTag, NewChapter);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGameOverTriggered, FGameplayTag, EndingTag);
|
||||
|
||||
/**
|
||||
* GM_CoreGameMode — Core Game Mode.
|
||||
*
|
||||
* Sets the rules of the game session: which pawn, controller, player state,
|
||||
* HUD, and game state classes to use. Manages chapter transitions, win/loss/
|
||||
* death routing, and coordinates with the narrative system for story progression.
|
||||
*
|
||||
* Server-authoritative. Extends AGameModeBase for replication support.
|
||||
*/
|
||||
UCLASS()
|
||||
class FRAMEWORK_API AGM_CoreGameMode : public AGameModeBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AGM_CoreGameMode();
|
||||
|
||||
// ========================================================================
|
||||
// Default Classes (Set in Blueprint or Config)
|
||||
// ========================================================================
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Framework|Classes")
|
||||
TSubclassOf<APC_CoreController> PlayerControllerClass;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Framework|Classes")
|
||||
TSubclassOf<APS_CorePlayerState> PlayerStateClass;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Framework|Classes")
|
||||
TSubclassOf<AGS_CoreGameState> GameStateClass;
|
||||
|
||||
// ========================================================================
|
||||
// Chapter Management
|
||||
// ========================================================================
|
||||
|
||||
/** The currently active chapter GameplayTag. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Framework|Narrative")
|
||||
FGameplayTag CurrentChapterTag;
|
||||
|
||||
/**
|
||||
* Transitions the game to a new chapter.
|
||||
* Server-authoritative. Sets phase to Loading, opens the chapter level,
|
||||
* then restores InGame phase on load complete.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
|
||||
void TransitionToChapter(FGameplayTag ChapterTag);
|
||||
|
||||
// ========================================================================
|
||||
// Death Handling
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Handles player death. Called by BPC_DeathHandlingSystem.
|
||||
* Idempotent — safe to call multiple times.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Death")
|
||||
void HandlePlayerDead(AController* DeadController);
|
||||
|
||||
// ========================================================================
|
||||
// Ending / Game Over
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Triggers a specific ending condition.
|
||||
* Passes the ending tag to BPC_EndingAccumulator for accumulation logic.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
|
||||
void TriggerEnding(FGameplayTag EndingTag);
|
||||
|
||||
// ========================================================================
|
||||
// Pause Control
|
||||
// ========================================================================
|
||||
|
||||
/** Runtime flag — menu widgets check this before pausing. False during cutscenes/death. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Framework|State")
|
||||
bool bPauseAllowed = true;
|
||||
|
||||
// ========================================================================
|
||||
// Event Dispatchers
|
||||
// ========================================================================
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnChapterTransition OnChapterTransition;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnGameOverTriggered OnGameOverTriggered;
|
||||
|
||||
// ========================================================================
|
||||
// Overrides
|
||||
// ========================================================================
|
||||
|
||||
virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override;
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
protected:
|
||||
/** Cached reference to the framework GameInstance. */
|
||||
UPROPERTY()
|
||||
TObjectPtr<UGI_GameFramework> CachedFramework;
|
||||
|
||||
/** Server-side: performs the actual level transition for a chapter. */
|
||||
void ServerTransitionToChapter(FGameplayTag ChapterTag);
|
||||
|
||||
/** Called when the chapter level finishes loading. */
|
||||
void OnChapterLevelLoaded(FGameplayTag ChapterTag);
|
||||
};
|
||||
144
Source/Framework/Public/Core/GS_CoreGameState.h
Normal file
144
Source/Framework/Public/Core/GS_CoreGameState.h
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — GS_CoreGameState (06)
|
||||
// Shared session state. Fully replicated singleton visible to all players.
|
||||
// Tracks chapter, narrative phase, encounter status, and active objectives.
|
||||
// C++ gives us proper GetLifetimeReplicatedProps() and OnRep_ handlers.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/GameStateBase.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
#include "GS_CoreGameState.generated.h"
|
||||
|
||||
// Delegates
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnChapterChanged, FGameplayTag, NewChapter);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnNarrativePhaseChanged, FGameplayTag, NewPhase);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEncounterStateChanged, bool, bActive);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnObjectiveTagsChanged);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayTimeUpdated, float, ElapsedSeconds);
|
||||
|
||||
/**
|
||||
* GS_CoreGameState — Shared Session State.
|
||||
*
|
||||
* A replicated singleton data holder. All modification happens through
|
||||
* dedicated setter functions — never direct variable writes.
|
||||
*
|
||||
* In C++, replication is handled via GetLifetimeReplicatedProps() with
|
||||
* OnRep_ handlers that mirror broadcast dispatchers for both network
|
||||
* clients and local single-player.
|
||||
*/
|
||||
UCLASS()
|
||||
class FRAMEWORK_API AGS_CoreGameState : public AGameStateBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AGS_CoreGameState();
|
||||
|
||||
// ========================================================================
|
||||
// Replicated State
|
||||
// ========================================================================
|
||||
|
||||
/** Elapsed play time (accumulated only when GamePhase is InGame). */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ElapsedPlayTime, BlueprintReadOnly, Category = "Framework|State")
|
||||
float ElapsedPlayTime = 0.0f;
|
||||
|
||||
/** Current story chapter tag. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ActiveChapter, BlueprintReadOnly, Category = "Framework|Narrative")
|
||||
FGameplayTag ActiveChapterTag;
|
||||
|
||||
/** Sub-chapter narrative phase. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_NarrativePhase, BlueprintReadOnly, Category = "Framework|Narrative")
|
||||
FGameplayTag ActiveNarrativePhase;
|
||||
|
||||
/** Whether an AI encounter is currently active. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_EncounterActive, BlueprintReadOnly, Category = "Framework|Combat")
|
||||
bool bEncounterActive = false;
|
||||
|
||||
/** Array of active objective tags. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ObjectiveTags, BlueprintReadOnly, Category = "Framework|Narrative")
|
||||
TArray<FGameplayTag> ActiveObjectiveTags;
|
||||
|
||||
// ========================================================================
|
||||
// Setters (Server-Authoritative)
|
||||
// ========================================================================
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
|
||||
void SetChapter(FGameplayTag ChapterTag);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
|
||||
void SetNarrativePhase(FGameplayTag PhaseTag);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Combat")
|
||||
void SetEncounterActive(bool bActive);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
|
||||
void AddObjective(FGameplayTag ObjectiveTag);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
|
||||
void RemoveObjective(FGameplayTag ObjectiveTag);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
|
||||
void ClearAllObjectives();
|
||||
|
||||
// ========================================================================
|
||||
// Event Dispatchers
|
||||
// ========================================================================
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnPlayTimeUpdated OnElapsedPlayTimeUpdated;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnChapterChanged OnChapterChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnNarrativePhaseChanged OnNarrativePhaseChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnEncounterStateChanged OnEncounterActiveStateChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
|
||||
FOnObjectiveTagsChanged OnObjectiveTagsChanged;
|
||||
|
||||
// ========================================================================
|
||||
// Overrides
|
||||
// ========================================================================
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
virtual void BeginPlay() override;
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
protected:
|
||||
// ========================================================================
|
||||
// OnRep Handlers — Fire dispatchers for network clients AND local single-player
|
||||
// ========================================================================
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_ElapsedPlayTime();
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_ActiveChapter();
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_NarrativePhase();
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_EncounterActive();
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_ObjectiveTags();
|
||||
|
||||
// ========================================================================
|
||||
// Internal
|
||||
// ========================================================================
|
||||
|
||||
/** Cached GameInstance for phase checking during time accumulation. */
|
||||
UPROPERTY()
|
||||
TObjectPtr<class UGI_GameFramework> CachedFramework;
|
||||
|
||||
/** Throttle timer for play time updates (fires ~1/sec). */
|
||||
float TimeUpdateAccumulator = 0.0f;
|
||||
static constexpr float TimeUpdateInterval = 1.0f;
|
||||
};
|
||||
317
Source/Framework/Public/Core/I_InterfaceLibrary.h
Normal file
317
Source/Framework/Public/Core/I_InterfaceLibrary.h
Normal file
@@ -0,0 +1,317 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — Framework Interfaces (03)
|
||||
// All 9 Blueprint Interfaces defined in C++ for clean default values and type safety.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Interface.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "I_InterfaceLibrary.generated.h"
|
||||
|
||||
// ============================================================================
|
||||
// Forward Declarations
|
||||
// ============================================================================
|
||||
|
||||
class UDA_ItemData;
|
||||
class UDA_InteractionData;
|
||||
|
||||
// ============================================================================
|
||||
// I_Interactable — World objects the player can interact with
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType, meta = (CannotImplementInterfaceInBlueprint))
|
||||
class UInteractable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IInteractable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** Called when a player interacts with this object. Returns true if interaction succeeded. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool OnInteract(AActor* Interactor);
|
||||
|
||||
/** Called when crosshair/focus enters this object. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void OnFocusBegin(AActor* Interactor);
|
||||
|
||||
/** Called when crosshair/focus leaves this object. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void OnFocusEnd(AActor* Interactor);
|
||||
|
||||
/** Returns the interaction prompt text (e.g. "Open Door", "Pick Up"). */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
FText GetInteractionPrompt() const;
|
||||
|
||||
/** Returns whether interaction is currently possible. BlockReason explains why if false. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool CanInteract(AActor* Interactor, FText& OutBlockReason) const;
|
||||
|
||||
/** Returns the GameplayTag identifying the interaction type (e.g. Framework.Interaction.Type.Pickup). */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
FGameplayTag GetInteractionType() const;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_Inspectable — Objects that can be examined in 3D inspect mode
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class UInspectable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IInspectable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void StartInspect(AActor* Inspector);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void EndInspect(AActor* Inspector);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void RotateInspect(FRotator RotationDelta);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool GetInspectData(FVector& OutAnchorPoint, FRotator& OutDefaultRotation, float& OutZoomDistance) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool HasInspectInfo() const;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_Damageable — Anything that takes damage or can be healed
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class UDamageable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IDamageable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** Apply damage. Returns actual damage dealt after modifiers. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Combat")
|
||||
float TakeDamage(float DamageAmount, AActor* DamageCauser, FGameplayTag DamageType, FVector HitLocation, FVector HitDirection);
|
||||
|
||||
/** Heal by amount. Returns actual health restored. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Combat")
|
||||
float Heal(float HealAmount, AActor* Healer);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Combat")
|
||||
bool IsAlive() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Combat")
|
||||
float GetCurrentHealth() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Combat")
|
||||
float GetMaxHealth() const;
|
||||
|
||||
/** Called when health reaches zero. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Combat")
|
||||
void OnDeath(AActor* Killer, FGameplayTag DeathCause);
|
||||
|
||||
/** Returns multiplier for incoming damage (e.g. 1.5 = takes 50% more damage). */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Combat")
|
||||
float GetDamageModifier(FGameplayTag DamageType) const;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_Holdable — Physics objects the player can grab and manipulate
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class UHoldable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IHoldable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void OnPickup(AActor* Holder);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void OnDrop(AActor* Dropper);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
FTransform GetHoldTransform() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool IsHeld() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void OnReleasedFromHold();
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_Lockable — Objects that can be locked/unlocked with key items
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class ULockable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API ILockable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool TryLock(AActor* Locker);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool TryUnlock(AActor* Unlocker, FGameplayTag KeyTag);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool IsLocked() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
FGameplayTag GetRequiredKeyTag() const;
|
||||
|
||||
/** Broadcast when lock state changes (implementor fires via delegate). */
|
||||
virtual void OnLockStateChanged(bool bNewLocked) {}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_UsableItem — Items that can be used from inventory/quick-slots
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class UUsableItem : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IUsableItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Inventory")
|
||||
bool UseItem(AActor* User, AActor* Target);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Inventory")
|
||||
bool CanUseItem(AActor* User, AActor* Target) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Inventory")
|
||||
float GetUseDuration() const;
|
||||
|
||||
/** Called after UseItem completes (for animations, effects). */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Inventory")
|
||||
void OnItemUsed(AActor* User);
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_Persistable — Actors that save/load their state to disk
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class UPersistable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IPersistable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** Serialize state to a byte array for saving. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Save")
|
||||
TArray<uint8> OnSave();
|
||||
|
||||
/** Restore state from a previously saved byte array. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Save")
|
||||
void OnLoad(const TArray<uint8>& Data);
|
||||
|
||||
/** Returns the unique GameplayTag identifier for this persistable actor. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Save")
|
||||
FGameplayTag GetSaveTag() const;
|
||||
|
||||
/** Returns true if this actor has changed since last save. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Save")
|
||||
bool NeedsSave() const;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_Toggleable — Objects with binary on/off states
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class UToggleable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IToggleable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void Toggle(AActor* Toggler);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void SetState(bool bNewState, AActor* Setter);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
bool GetCurrentState() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
FText GetStateLabel() const;
|
||||
|
||||
/** Broadcast when state changes. */
|
||||
virtual void OnStateChanged(bool bNewState, AActor* Changer) {}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// I_Adjustable — Objects with continuous value range (dials, sliders)
|
||||
// ============================================================================
|
||||
|
||||
UINTERFACE(MinimalAPI, BlueprintType)
|
||||
class UAdjustable : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class FRAMEWORK_API IAdjustable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void Adjust(float Delta, AActor* Adjuster);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
void SetValue(float NewValue, AActor* Setter);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
float GetCurrentValue() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
float GetMinValue() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Framework|Interaction")
|
||||
float GetMaxValue() const;
|
||||
|
||||
/** Broadcast when value changes. */
|
||||
virtual void OnValueChanged(float NewValue, AActor* Changer) {}
|
||||
};
|
||||
Reference in New Issue
Block a user