Fix ability input system and more
parent
66995bc486
commit
021f30632a
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright
|
||||
|
||||
|
||||
#include "AbilitySystem/Abilities/VRGameplayAbility.h"
|
||||
|
||||
#include "AbilitySystemComponent.h"
|
||||
|
||||
UVRGameplayAbility::UVRGameplayAbility()
|
||||
{
|
||||
ActivationPolicy = EVRAbilityActivationPolicy::OnInputTriggered;
|
||||
}
|
||||
|
||||
void UVRGameplayAbility::OnGiveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec)
|
||||
{
|
||||
Super::OnGiveAbility(ActorInfo, Spec);
|
||||
|
||||
if (ActivationPolicy == EVRAbilityActivationPolicy::OnGiven)
|
||||
{
|
||||
if (ActorInfo && !Spec.IsActive())
|
||||
{
|
||||
ActorInfo->AbilitySystemComponent->TryActivateAbility(Spec.Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UVRGameplayAbility::EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled)
|
||||
{
|
||||
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
|
||||
|
||||
if (ActivationPolicy == EVRAbilityActivationPolicy::OnGiven)
|
||||
{
|
||||
if (ActorInfo)
|
||||
{
|
||||
ActorInfo->AbilitySystemComponent->ClearAbility(Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,3 +2,167 @@
|
|||
|
||||
|
||||
#include "AbilitySystem/VRAbilitySystemComponent.h"
|
||||
|
||||
#include "Logging.h"
|
||||
#include "AbilitySystem/Abilities/VRGameplayAbility.h"
|
||||
#include "AbilitySystem/StartupData/VRStartupAbilitySystemData.h"
|
||||
|
||||
UVRAbilitySystemComponent::UVRAbilitySystemComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
void UVRAbilitySystemComponent::ApplyStartupData()
|
||||
{
|
||||
if (StartupData)
|
||||
{
|
||||
StartupData->GiveToAbilitySystemComponent(this, DefaultStartingAbilityLevel);
|
||||
}
|
||||
|
||||
UE_LOG(VRGAS_Log, Error, TEXT("UVRAbilitySystemComponent::ApplyStartupData - No Startup Data found!"))
|
||||
}
|
||||
|
||||
void UVRAbilitySystemComponent::InputTagPressed(FGameplayTag& InTag)
|
||||
{
|
||||
if (!InTag.IsValid()) return;
|
||||
|
||||
FScopedAbilityListLock ActiveScopeLoc(*this);
|
||||
for (FGameplayAbilitySpec& AbilitySpec : GetActivatableAbilities())
|
||||
{
|
||||
if (AbilitySpec.Ability && AbilitySpec.DynamicAbilityTags.HasTagExact(InTag))
|
||||
{
|
||||
InputPressedSpecHandles.AddUnique(AbilitySpec.Handle);
|
||||
InputHeldSpecHandles.AddUnique(AbilitySpec.Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UVRAbilitySystemComponent::InputTagReleased(FGameplayTag& InTag)
|
||||
{
|
||||
if (!InTag.IsValid()) return;
|
||||
|
||||
FScopedAbilityListLock ActiveScopeLoc(*this);
|
||||
for (FGameplayAbilitySpec& AbilitySpec : GetActivatableAbilities())
|
||||
{
|
||||
if (AbilitySpec.Ability && (AbilitySpec.DynamicAbilityTags.HasTagExact(InTag)))
|
||||
{
|
||||
InputReleasedSpecHandles.AddUnique(AbilitySpec.Handle);
|
||||
InputHeldSpecHandles.Remove(AbilitySpec.Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We're doing the Lyra approach
|
||||
void UVRAbilitySystemComponent::ProcessAbilityInput(float DeltaTime, bool bGamePaused)
|
||||
{
|
||||
// TODO: Add tag that blocks all abilities
|
||||
|
||||
TArray<FGameplayAbilitySpecHandle> AbilitiesToActivate;
|
||||
|
||||
// Handle held abilities
|
||||
for (const FGameplayAbilitySpecHandle& AbilitySpecHandle : InputHeldSpecHandles)
|
||||
{
|
||||
if (const FGameplayAbilitySpec* AbilitySpec = FindAbilitySpecFromHandle(AbilitySpecHandle))
|
||||
{
|
||||
if (AbilitySpec->Ability && !AbilitySpec->IsActive())
|
||||
{
|
||||
const UVRGameplayAbility* AbilityCDO = CastChecked<UVRGameplayAbility>(AbilitySpec->Ability);
|
||||
|
||||
if (AbilityCDO->GetActivationPolicy() == EVRAbilityActivationPolicy::OnInputHeld)
|
||||
{
|
||||
AbilitiesToActivate.AddUnique(AbilitySpec->Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const FGameplayAbilitySpecHandle& AbilitySpecHandle : InputPressedSpecHandles)
|
||||
{
|
||||
if (FGameplayAbilitySpec* AbilitySpec = FindAbilitySpecFromHandle(AbilitySpecHandle))
|
||||
{
|
||||
if (AbilitySpec->Ability)
|
||||
{
|
||||
AbilitySpec->InputPressed;
|
||||
|
||||
if (AbilitySpec->IsActive())
|
||||
{
|
||||
AbilitySpecInputPressed(*AbilitySpec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ReSharper disable once CppTooWideScopeInitStatement
|
||||
const UVRGameplayAbility* AbilityCDO = CastChecked<UVRGameplayAbility>(AbilitySpec->Ability);
|
||||
|
||||
if (AbilityCDO->GetActivationPolicy() == EVRAbilityActivationPolicy::OnInputTriggered)
|
||||
{
|
||||
AbilitiesToActivate.AddUnique(AbilitySpec->Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Activate all abilities to be activated
|
||||
for (const FGameplayAbilitySpecHandle& AbilitySpecHandle : AbilitiesToActivate)
|
||||
{
|
||||
TryActivateAbility(AbilitySpecHandle);
|
||||
}
|
||||
|
||||
// Handle released ability inputs
|
||||
for (FGameplayAbilitySpecHandle& AbilitySpecHandle : InputReleasedSpecHandles)
|
||||
{
|
||||
if (FGameplayAbilitySpec* AbilitySpec = FindAbilitySpecFromHandle(AbilitySpecHandle))
|
||||
{
|
||||
if (AbilitySpec->Ability)
|
||||
{
|
||||
AbilitySpec->InputPressed = false;
|
||||
|
||||
if (AbilitySpec->IsActive())
|
||||
{
|
||||
AbilitySpecInputReleased(*AbilitySpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear cached ability handles, as in Lyra
|
||||
InputPressedSpecHandles.Empty();
|
||||
InputReleasedSpecHandles.Empty();
|
||||
}
|
||||
|
||||
void UVRAbilitySystemComponent::ClearAbilityInput()
|
||||
{
|
||||
InputPressedSpecHandles.Empty();
|
||||
InputReleasedSpecHandles.Empty();
|
||||
InputHeldSpecHandles.Empty();
|
||||
}
|
||||
|
||||
void UVRAbilitySystemComponent::AbilitySpecInputPressed(FGameplayAbilitySpec& Spec)
|
||||
{
|
||||
Super::AbilitySpecInputPressed(Spec);
|
||||
|
||||
// Do like Lyra
|
||||
if (Spec.IsActive())
|
||||
{
|
||||
// Invoke the InputPressed event.
|
||||
// This is not replicated here.
|
||||
// If someone is listening, they may replicate the InputPressed event to the server.
|
||||
InvokeReplicatedEvent(EAbilityGenericReplicatedEvent::InputPressed, Spec.Handle, Spec.ActivationInfo.GetActivationPredictionKey());
|
||||
}
|
||||
}
|
||||
|
||||
void UVRAbilitySystemComponent::AbilitySpecInputReleased(FGameplayAbilitySpec& Spec)
|
||||
{
|
||||
Super::AbilitySpecInputReleased(Spec);
|
||||
|
||||
if (Spec.IsActive())
|
||||
{
|
||||
// Invoke the InputReleased event.
|
||||
// This is not replicated here.
|
||||
// If someone is listening, they may replicate the InputReleased event to the server.
|
||||
InvokeReplicatedEvent(EAbilityGenericReplicatedEvent::InputReleased, Spec.Handle, Spec.ActivationInfo.GetActivationPredictionKey());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,3 +2,98 @@
|
|||
|
||||
|
||||
#include "Player/VRPlayerController.h"
|
||||
|
||||
#include "AbilitySystemGlobals.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
#include "Logging.h"
|
||||
#include "AbilitySystem/VRAbilitySystemComponent.h"
|
||||
#include "Input/VRInputComponent.h"
|
||||
|
||||
AVRPlayerController::AVRPlayerController()
|
||||
{
|
||||
bReplicates = true;
|
||||
}
|
||||
|
||||
void AVRPlayerController::PostProcessInput(const float DeltaTime, const bool bGamePaused)
|
||||
{
|
||||
if (UVRAbilitySystemComponent* VRAbilitySystemComponent = GetVRAbilitySystemComponent())
|
||||
{
|
||||
VRAbilitySystemComponent->ProcessAbilityInput(DeltaTime, bGamePaused);
|
||||
}
|
||||
|
||||
Super::PostProcessInput(DeltaTime, bGamePaused);
|
||||
}
|
||||
|
||||
void AVRPlayerController::SetupInputComponent()
|
||||
{
|
||||
Super::SetupInputComponent();
|
||||
|
||||
UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
|
||||
// We could check the subsystem instead of doing an if statement
|
||||
// check(Subsystem);
|
||||
|
||||
if (InputMappingContext)
|
||||
{
|
||||
Subsystem->AddMappingContext(InputMappingContext, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(VRGAS_Log, Error, TEXT("AVRPlayerController::SetupInputComponent - Input Mapping Context not found!"))
|
||||
}
|
||||
|
||||
if (UVRInputComponent* VRInputComponent = Cast<UVRInputComponent>(InputComponent))
|
||||
{
|
||||
VRInputComponent->BindAbilityActions(InputConfig, this,
|
||||
&ThisClass::Input_AbilityTagPressed, &ThisClass::Input_AbilityTagReleased);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(VRGAS_Log, Error, TEXT("AVRPlayerController::SetupInputComponent - Input Component is not of VRGAS type!"))
|
||||
}
|
||||
}
|
||||
|
||||
void AVRPlayerController::OnPossess(APawn* InPawn)
|
||||
{
|
||||
Super::OnPossess(InPawn);
|
||||
|
||||
CachedAbilitySystemComponent = Cast<UVRAbilitySystemComponent>(
|
||||
UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetPawn()));
|
||||
}
|
||||
|
||||
UAbilitySystemComponent* AVRPlayerController::GetAbilitySystemComponent()
|
||||
{
|
||||
if (!CachedAbilitySystemComponent.IsValid())
|
||||
{
|
||||
CachedAbilitySystemComponent = Cast<UVRAbilitySystemComponent>(
|
||||
UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetPawn()));
|
||||
|
||||
if (!CachedAbilitySystemComponent.IsValid()) return nullptr;
|
||||
}
|
||||
|
||||
return CachedAbilitySystemComponent.Get();
|
||||
}
|
||||
|
||||
UVRAbilitySystemComponent* AVRPlayerController::GetVRAbilitySystemComponent()
|
||||
{
|
||||
return Cast<UVRAbilitySystemComponent>(GetAbilitySystemComponent());
|
||||
}
|
||||
|
||||
void AVRPlayerController::Input_AbilityTagPressed(FGameplayTag InTag)
|
||||
{
|
||||
if (!GetVRAbilitySystemComponent())
|
||||
{
|
||||
UE_LOG(VRGAS_Log, Error, TEXT("AVRPlayerController::Input_AbilityTagPressed - No Vagabond Rose ASC present!"))
|
||||
}
|
||||
|
||||
GetVRAbilitySystemComponent()->InputTagPressed(InTag);
|
||||
}
|
||||
|
||||
void AVRPlayerController::Input_AbilityTagReleased(FGameplayTag InTag)
|
||||
{
|
||||
if (!GetVRAbilitySystemComponent())
|
||||
{
|
||||
UE_LOG(VRGAS_Log, Error, TEXT("AVRPlayerController::Input_AbilityTagReleased - No Vagabond Rose ASC present!"))
|
||||
}
|
||||
|
||||
GetVRAbilitySystemComponent()->InputTagReleased(InTag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
bool FVRAbilitySet::IsValid() const
|
||||
{
|
||||
return AbilityClass;
|
||||
return AbilityClass != nullptr;
|
||||
}
|
||||
|
||||
bool FVRAbilitySet::IsValidInput() const
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Abilities/GameplayAbility.h"
|
||||
#include "VRGameplayAbility.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVRAbilityActivationPolicy : uint8
|
||||
{
|
||||
OnInputTriggered,
|
||||
OnInputHeld,
|
||||
OnGiven
|
||||
};
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class VRGAS_API UVRGameplayAbility : public UGameplayAbility
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UVRGameplayAbility();
|
||||
|
||||
EVRAbilityActivationPolicy GetActivationPolicy() const { return ActivationPolicy; }
|
||||
|
||||
protected:
|
||||
//~ Begin UGameplayAbility Interface
|
||||
virtual void OnGiveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec) override;
|
||||
virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override;
|
||||
//~ End UGameplayAbility Interface
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Activation")
|
||||
EVRAbilityActivationPolicy ActivationPolicy;
|
||||
|
||||
};
|
||||
|
|
@ -6,9 +6,10 @@
|
|||
#include "AbilitySystemComponent.h"
|
||||
#include "VRAbilitySystemComponent.generated.h"
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE_OneParam(FEffectAssetTags, const FGameplayTagContainer& /*AssetTags*/);
|
||||
DECLARE_MULTICAST_DELEGATE(FAbilitiesGiven);
|
||||
// DECLARE_MULTICAST_DELEGATE_OneParam(FEffectAssetTags, const FGameplayTagContainer& /*AssetTags*/);
|
||||
// DECLARE_MULTICAST_DELEGATE(FAbilitiesGiven);
|
||||
|
||||
class UVRStartupAbilitySystemData;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -18,13 +19,50 @@ class VRGAS_API UVRAbilitySystemComponent : public UAbilitySystemComponent
|
|||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
void AbilityActorInfoSet();
|
||||
|
||||
FEffectAssetTags EffectAssetTags;
|
||||
FAbilitiesGiven OnAbilitiesGiven;
|
||||
UVRAbilitySystemComponent(const FObjectInitializer& ObjectInitializer);
|
||||
// void AbilityActorInfoSet();
|
||||
|
||||
// FEffectAssetTags EffectAssetTags;
|
||||
// FAbilitiesGiven OnAbilitiesGiven;
|
||||
#pragma region PublicStartup
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Startup Data")
|
||||
bool bStartupAbilitiesGiven = false;
|
||||
|
||||
// Add startup abilities
|
||||
virtual void ApplyStartupData();
|
||||
#pragma endregion
|
||||
|
||||
// Add startup abilities
|
||||
|
||||
#pragma region PublicInput
|
||||
// Handle pressed input
|
||||
virtual void InputTagPressed(FGameplayTag& InTag);
|
||||
// Handle released input
|
||||
virtual void InputTagReleased(FGameplayTag& InTag);
|
||||
|
||||
void ProcessAbilityInput(float DeltaTime, bool bGamePaused);
|
||||
void ClearAbilityInput();
|
||||
#pragma endregion
|
||||
|
||||
protected:
|
||||
#pragma region ProtectedInput
|
||||
virtual void AbilitySpecInputPressed(FGameplayAbilitySpec& Spec) override;
|
||||
virtual void AbilitySpecInputReleased(FGameplayAbilitySpec& Spec) override;
|
||||
|
||||
// Handles to abilities that had their input pressed this frame.
|
||||
TArray<FGameplayAbilitySpecHandle> InputPressedSpecHandles;
|
||||
|
||||
// Handles to abilities that had their input released this frame.
|
||||
TArray<FGameplayAbilitySpecHandle> InputReleasedSpecHandles;
|
||||
|
||||
// Handles to abilities that have their input held.
|
||||
TArray<FGameplayAbilitySpecHandle> InputHeldSpecHandles;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ProtectedStartup
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Startup Data")
|
||||
TObjectPtr<UVRStartupAbilitySystemData> StartupData;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Startup Data", meta = (ClampMin = 1))
|
||||
int DefaultStartingAbilityLevel = 1;
|
||||
#pragma endregion
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class VRGAS_API UVRInputComponent : public UEnhancedInputComponent
|
|||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
template <class UserClass, typename FuncType>
|
||||
void BindNativeActions(const UVRInputConfig* InputConfig, const FGameplayTag& InputTag, ETriggerEvent TriggerEvent,
|
||||
UserClass* Object,FuncType Func, bool bLogNotFound = true);
|
||||
|
|
@ -25,7 +26,7 @@ template <class UserClass, typename FuncType>
|
|||
void UVRInputComponent::BindNativeActions(const UVRInputConfig* InputConfig, const FGameplayTag& InputTag, ETriggerEvent TriggerEvent,
|
||||
UserClass* Object,FuncType Func, const bool bLogNotFound)
|
||||
{
|
||||
check(InputConfig)
|
||||
check(InputConfig);
|
||||
if (UInputAction* Action = InputConfig->FindNativeInputActionForTag(InputTag, bLogNotFound))
|
||||
{
|
||||
BindAction(Action, TriggerEvent, Object, Func);
|
||||
|
|
@ -33,9 +34,9 @@ void UVRInputComponent::BindNativeActions(const UVRInputConfig* InputConfig, con
|
|||
}
|
||||
|
||||
template <class UserClass, typename PressedFuncType, typename ReleasedFuncType>
|
||||
void UVRInputComponent::BindAbilityActions(const UVRInputConfig* InputConfig, UserClass* Object, PressedFuncType PressedFunc, ReleasedFuncType ReleasedFunc);
|
||||
void UVRInputComponent::BindAbilityActions(const UVRInputConfig* InputConfig, UserClass* Object, PressedFuncType PressedFunc, ReleasedFuncType ReleasedFunc)
|
||||
{
|
||||
check(InputConfig)
|
||||
check(InputConfig);
|
||||
for (const FVRTagInputBinding& Binding : InputConfig->AbilityInputActions)
|
||||
{
|
||||
if (Binding.IsValid())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include "GameFramework/PlayerController.h"
|
||||
#include "VRPlayerController.generated.h"
|
||||
|
||||
class UVRAbilitySystemComponent;
|
||||
struct FGameplayTag;
|
||||
class UVRInputConfig;
|
||||
class UInputMappingContext;
|
||||
class UAbilitySystemComponent;
|
||||
|
|
@ -21,6 +23,10 @@ class VRGAS_API AVRPlayerController : public APlayerController
|
|||
public:
|
||||
AVRPlayerController();
|
||||
|
||||
//~ Begin APlayerController Interface
|
||||
virtual void PostProcessInput(const float DeltaTime, const bool bGamePaused) override;
|
||||
//~ End APlayerContoller Interface
|
||||
|
||||
protected:
|
||||
// TODO: Implement controller
|
||||
virtual void SetupInputComponent() override;
|
||||
|
|
@ -40,5 +46,11 @@ protected:
|
|||
|
||||
UFUNCTION(BlueprintPure, Category = "Ability System", meta = (HideSelfPin))
|
||||
UAbilitySystemComponent* GetAbilitySystemComponent();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Ability System", meta = (HideSelfPin))
|
||||
UVRAbilitySystemComponent* GetVRAbilitySystemComponent();
|
||||
|
||||
void Input_AbilityTagPressed(FGameplayTag InTag);
|
||||
void Input_AbilityTagReleased(FGameplayTag InTag);
|
||||
#pragma endregion
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "VRGASTypes.generated.h"
|
||||
|
||||
class UGameplayAbility;
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ struct FVRAbilitySet
|
|||
TSubclassOf<UGameplayAbility> AbilityClass;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
uint32 AbilityLevel = 1.f;
|
||||
int AbilityLevel = 1;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue