// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Abilities/GameplayAbilityTargetTypes.h" #include "Containers/Array.h" #include "Delegates/IDelegateInstance.h" #include "Engine/EngineTypes.h" #include "Engine/HitResult.h" #include "Equipment/LyraGameplayAbility_FromEquipment.h" #include "GameplayAbilitySpec.h" #include "Math/Transform.h" #include "Math/UnrealMathSSE.h" #include "Math/Vector.h" #include "UObject/UObjectGlobals.h" #include "LyraGameplayAbility_RangedWeapon.generated.h" class APawn; class ULyraRangedWeaponInstance; class UObject; struct FCollisionQueryParams; struct FFrame; struct FGameplayAbilityActorInfo; struct FGameplayEventData; struct FGameplayTag; struct FGameplayTagContainer; /** Defines where an ability starts its trace from and where it should face */ UENUM(BlueprintType) enum class ELyraAbilityTargetingSource : uint8 { // From the player's camera towards camera focus CameraTowardsFocus, // From the pawn's center, in the pawn's orientation PawnForward, // From the pawn's center, oriented towards camera focus PawnTowardsFocus, // From the weapon's muzzle or location, in the pawn's orientation WeaponForward, // From the weapon's muzzle or location, towards camera focus WeaponTowardsFocus, // Custom blueprint-specified source location Custom }; /** * ULyraGameplayAbility_RangedWeapon * * An ability granted by and associated with a ranged weapon instance */ UCLASS() class ULyraGameplayAbility_RangedWeapon : public ULyraGameplayAbility_FromEquipment { GENERATED_BODY() public: ULyraGameplayAbility_RangedWeapon(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); UFUNCTION(BlueprintCallable, Category="Lyra|Ability") ULyraRangedWeaponInstance* GetWeaponInstance() const; //~UGameplayAbility interface virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const override; virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override; virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override; //~End of UGameplayAbility interface protected: struct FRangedWeaponFiringInput { // Start of the trace FVector StartTrace; // End of the trace if aim were perfect FVector EndAim; // The direction of the trace if aim were perfect FVector AimDir; // The weapon instance / source of weapon data ULyraRangedWeaponInstance* WeaponData = nullptr; // Can we play bullet FX for hits during this trace bool bCanPlayBulletFX = false; FRangedWeaponFiringInput() : StartTrace(ForceInitToZero) , EndAim(ForceInitToZero) , AimDir(ForceInitToZero) { } }; protected: static int32 FindFirstPawnHitResult(const TArray& HitResults); // Does a single weapon trace, either sweeping or ray depending on if SweepRadius is above zero FHitResult WeaponTrace(const FVector& StartTrace, const FVector& EndTrace, float SweepRadius, bool bIsSimulated, OUT TArray& OutHitResults) const; // Wrapper around WeaponTrace to handle trying to do a ray trace before falling back to a sweep trace if there were no hits and SweepRadius is above zero FHitResult DoSingleBulletTrace(const FVector& StartTrace, const FVector& EndTrace, float SweepRadius, bool bIsSimulated, OUT TArray& OutHits) const; // Traces all of the bullets in a single cartridge void TraceBulletsInCartridge(const FRangedWeaponFiringInput& InputData, OUT TArray& OutHits); virtual void AddAdditionalTraceIgnoreActors(FCollisionQueryParams& TraceParams) const; // Determine the trace channel to use for the weapon trace(s) virtual ECollisionChannel DetermineTraceChannel(FCollisionQueryParams& TraceParams, bool bIsSimulated) const; void PerformLocalTargeting(OUT TArray& OutHits); FVector GetWeaponTargetingSourceLocation() const; FTransform GetTargetingTransform(APawn* SourcePawn, ELyraAbilityTargetingSource Source) const; void OnTargetDataReadyCallback(const FGameplayAbilityTargetDataHandle& InData, FGameplayTag ApplicationTag); UFUNCTION(BlueprintCallable) void StartRangedWeaponTargeting(); // Called when target data is ready UFUNCTION(BlueprintImplementableEvent) void OnRangedWeaponTargetDataReady(const FGameplayAbilityTargetDataHandle& TargetData); private: FDelegateHandle OnTargetDataReadyCallbackDelegateHandle; };