96 lines
3.9 KiB
C
96 lines
3.9 KiB
C
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include "CoreMinimal.h"
|
||
|
#include "Subsystems/WorldSubsystem.h"
|
||
|
#include "GameplayTagContainer.h"
|
||
|
#include "GameplayAbilitySpec.h"
|
||
|
#include "LyraGamePhaseSubsystem.generated.h"
|
||
|
|
||
|
class ULyraGamePhaseAbility;
|
||
|
|
||
|
DECLARE_DYNAMIC_DELEGATE_OneParam(FLyraGamePhaseDynamicDelegate, const ULyraGamePhaseAbility*, Phase);
|
||
|
DECLARE_DELEGATE_OneParam(FLyraGamePhaseDelegate, const ULyraGamePhaseAbility* Phase);
|
||
|
|
||
|
DECLARE_DYNAMIC_DELEGATE_OneParam(FLyraGamePhaseTagDynamicDelegate, const FGameplayTag&, PhaseTag);
|
||
|
DECLARE_DELEGATE_OneParam(FLyraGamePhaseTagDelegate, const FGameplayTag& PhaseTag);
|
||
|
|
||
|
// Match rule for message receivers
|
||
|
UENUM(BlueprintType)
|
||
|
enum class EPhaseTagMatchType : uint8
|
||
|
{
|
||
|
// An exact match will only receive messages with exactly the same channel
|
||
|
// (e.g., registering for "A.B" will match a broadcast of A.B but not A.B.C)
|
||
|
ExactMatch,
|
||
|
|
||
|
// A partial match will receive any messages rooted in the same channel
|
||
|
// (e.g., registering for "A.B" will match a broadcast of A.B as well as A.B.C)
|
||
|
PartialMatch
|
||
|
};
|
||
|
|
||
|
|
||
|
/** */
|
||
|
UCLASS()
|
||
|
class ULyraGamePhaseSubsystem : public UWorldSubsystem
|
||
|
{
|
||
|
GENERATED_BODY()
|
||
|
|
||
|
public:
|
||
|
ULyraGamePhaseSubsystem();
|
||
|
|
||
|
virtual void PostInitialize() override;
|
||
|
|
||
|
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
|
||
|
|
||
|
void StartPhase(TSubclassOf<ULyraGamePhaseAbility> PhaseAbility, FLyraGamePhaseDelegate PhaseEndedCallback = FLyraGamePhaseDelegate());
|
||
|
|
||
|
//TODO Return a handle so folks can delete these. They will just grow until the world resets.
|
||
|
//TODO Should we just occasionally clean these observers up? It's not as if everyone will properly unhook them even if there is a handle.
|
||
|
void WhenPhaseStartsOrIsActive(FGameplayTag PhaseTag, EPhaseTagMatchType MatchType, const FLyraGamePhaseTagDelegate& WhenPhaseActive);
|
||
|
void WhenPhaseEnds(FGameplayTag PhaseTag, EPhaseTagMatchType MatchType, const FLyraGamePhaseTagDelegate& WhenPhaseEnd);
|
||
|
|
||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, BlueprintPure = false, meta = (AutoCreateRefTerm = "PhaseTag"))
|
||
|
bool IsPhaseActive(const FGameplayTag& PhaseTag) const;
|
||
|
|
||
|
protected:
|
||
|
virtual bool DoesSupportWorldType(const EWorldType::Type WorldType) const override;
|
||
|
|
||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Game Phase", meta = (DisplayName="Start Phase", AutoCreateRefTerm = "PhaseEnded"))
|
||
|
void K2_StartPhase(TSubclassOf<ULyraGamePhaseAbility> Phase, const FLyraGamePhaseDynamicDelegate& PhaseEnded);
|
||
|
|
||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Game Phase", meta = (DisplayName = "When Phase Starts or Is Active", AutoCreateRefTerm = "WhenPhaseActive"))
|
||
|
void K2_WhenPhaseStartsOrIsActive(FGameplayTag PhaseTag, EPhaseTagMatchType MatchType, FLyraGamePhaseTagDynamicDelegate WhenPhaseActive);
|
||
|
|
||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Game Phase", meta = (DisplayName = "When Phase Ends", AutoCreateRefTerm = "WhenPhaseEnd"))
|
||
|
void K2_WhenPhaseEnds(FGameplayTag PhaseTag, EPhaseTagMatchType MatchType, FLyraGamePhaseTagDynamicDelegate WhenPhaseEnd);
|
||
|
|
||
|
void OnBeginPhase(const ULyraGamePhaseAbility* PhaseAbility, const FGameplayAbilitySpecHandle PhaseAbilityHandle);
|
||
|
void OnEndPhase(const ULyraGamePhaseAbility* PhaseAbility, const FGameplayAbilitySpecHandle PhaseAbilityHandle);
|
||
|
|
||
|
private:
|
||
|
struct FLyraGamePhaseEntry
|
||
|
{
|
||
|
public:
|
||
|
FGameplayTag PhaseTag;
|
||
|
FLyraGamePhaseDelegate PhaseEndedCallback;
|
||
|
};
|
||
|
|
||
|
TMap<FGameplayAbilitySpecHandle, FLyraGamePhaseEntry> ActivePhaseMap;
|
||
|
|
||
|
struct FPhaseObserver
|
||
|
{
|
||
|
public:
|
||
|
bool IsMatch(const FGameplayTag& ComparePhaseTag) const;
|
||
|
|
||
|
FGameplayTag PhaseTag;
|
||
|
EPhaseTagMatchType MatchType = EPhaseTagMatchType::ExactMatch;
|
||
|
FLyraGamePhaseTagDelegate PhaseCallback;
|
||
|
};
|
||
|
|
||
|
TArray<FPhaseObserver> PhaseStartObservers;
|
||
|
TArray<FPhaseObserver> PhaseEndObservers;
|
||
|
|
||
|
friend class ULyraGamePhaseAbility;
|
||
|
};
|