:(
This commit is contained in:
51
Source/Aura/Private/AbilitySystem/AuraProjectileSpell.cpp
Normal file
51
Source/Aura/Private/AbilitySystem/AuraProjectileSpell.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
|
||||
#include "AbilitySystem/AuraProjectileSpell.h"
|
||||
|
||||
#include "AbilitySystemBlueprintLibrary.h"
|
||||
#include "AbilitySystemComponent.h"
|
||||
#include "Actor/AuraProjectile.h"
|
||||
#include "Interact/CombatInterface.h"
|
||||
|
||||
void UAuraProjectileSpell::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
|
||||
const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo,
|
||||
const FGameplayEventData* TriggerEventData)
|
||||
{
|
||||
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UAuraProjectileSpell::SpawnProjectile(const FVector ProjectileTargetLocation)
|
||||
{
|
||||
const bool bIsServer = GetAvatarActorFromActorInfo()->HasAuthority();
|
||||
if (bIsServer) return;
|
||||
|
||||
ICombatInterface* CombatInterface = Cast<ICombatInterface>(GetAvatarActorFromActorInfo());
|
||||
if (CombatInterface)
|
||||
{
|
||||
const FVector SocketLocation = CombatInterface->GetCombatSocketLocation();
|
||||
FRotator Rotation = (ProjectileTargetLocation - SocketLocation).Rotation();
|
||||
Rotation.Pitch = 0.0f;
|
||||
|
||||
FTransform SpawnTransform;
|
||||
SpawnTransform.SetLocation(SocketLocation);
|
||||
SpawnTransform.SetRotation(Rotation.Quaternion());
|
||||
|
||||
AAuraProjectile* Projectile = GetWorld()->SpawnActorDeferred<AAuraProjectile>(
|
||||
ProjectileClass,
|
||||
SpawnTransform,
|
||||
GetOwningActorFromActorInfo(),
|
||||
Cast<APawn>(CurrentActorInfo->AvatarActor), //Changed to allow GetInstigator() to work accurately in Projectile. Allowing ignoring the player character.
|
||||
ESpawnActorCollisionHandlingMethod::AlwaysSpawn);
|
||||
|
||||
const UAbilitySystemComponent* SourceASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetAvatarActorFromActorInfo());
|
||||
const FGameplayEffectSpecHandle SpecHandle = SourceASC->MakeOutgoingSpec(DamageEffectClass, GetAbilityLevel(), SourceASC->MakeEffectContext());
|
||||
Projectile->DamageEffectSpecHandle = SpecHandle;
|
||||
|
||||
UE_LOG(LogTemp,Warning,TEXT("Projectile - SourceASC %s - DamageEffectClass %s"), *SourceASC->GetName(), *DamageEffectClass->GetName());
|
||||
Projectile->FinishSpawning(SpawnTransform);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
|
||||
#include "AbilitySystem/GameplayAbility/AuraGameplayAbility.h"
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
|
||||
#include "AbilitySystem/Tasks/TargetDataUnderMouse.h"
|
||||
|
||||
#include "AbilitySystemComponent.h"
|
||||
|
||||
UTargetDataUnderMouse* UTargetDataUnderMouse::CreateTargetDataUnderMouse(UGameplayAbility* OwningAbility)
|
||||
{
|
||||
UTargetDataUnderMouse* MyObj = NewAbilityTask<UTargetDataUnderMouse>(OwningAbility);
|
||||
return MyObj;
|
||||
}
|
||||
|
||||
void UTargetDataUnderMouse::Activate()
|
||||
{
|
||||
const bool bIsLocallyControlled = Ability->GetCurrentActorInfo()->IsLocallyControlled();
|
||||
if (bIsLocallyControlled)
|
||||
{
|
||||
SendMouseCursorData();
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: We are on the server, so listen for target data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UTargetDataUnderMouse::SendMouseCursorData()
|
||||
{
|
||||
FScopedPredictionWindow ScopedPrediction(AbilitySystemComponent.Get());
|
||||
|
||||
APlayerController* PC = Ability->GetCurrentActorInfo()->PlayerController.Get();
|
||||
FHitResult CursorHit;
|
||||
PC->GetHitResultUnderCursor(ECC_Visibility, false, CursorHit);
|
||||
|
||||
FGameplayAbilityTargetDataHandle DataHandle;
|
||||
FGameplayAbilityTargetData_SingleTargetHit* Data = new FGameplayAbilityTargetData_SingleTargetHit();
|
||||
Data->HitResult = CursorHit;
|
||||
DataHandle.Add(Data);
|
||||
|
||||
AbilitySystemComponent->ServerSetReplicatedTargetData(
|
||||
GetAbilitySpecHandle(),
|
||||
GetActivationPredictionKey(),
|
||||
DataHandle, FGameplayTag(),
|
||||
AbilitySystemComponent->ScopedPredictionKey
|
||||
);
|
||||
|
||||
if (ShouldBroadcastAbilityTaskDelegates())
|
||||
{
|
||||
ValidData.Broadcast(DataHandle);
|
||||
}
|
||||
|
||||
}
|
||||
75
Source/Aura/Private/Actor/AuraProjectile.cpp
Normal file
75
Source/Aura/Private/Actor/AuraProjectile.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
#include "Actor/AuraProjectile.h"
|
||||
|
||||
#include "AbilitySystemBlueprintLibrary.h"
|
||||
#include "AbilitySystemComponent.h"
|
||||
#include "NiagaraFunctionLibrary.h"
|
||||
#include "Aura/Aura.h"
|
||||
#include "Components/AudioComponent.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "GameFramework/ProjectileMovementComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
AAuraProjectile::AAuraProjectile()
|
||||
{
|
||||
bReplicates = true;
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
Sphere = CreateDefaultSubobject<USphereComponent>("Sphere");
|
||||
SetRootComponent(Sphere);
|
||||
Sphere->SetCollisionObjectType(ECC_PROJECTILE);
|
||||
Sphere->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
Sphere->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
Sphere->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Overlap);
|
||||
Sphere->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Overlap);
|
||||
Sphere->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
|
||||
|
||||
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>("ProjectileMovement");
|
||||
ProjectileMovement->InitialSpeed = 550.f;
|
||||
ProjectileMovement->MaxSpeed = 550.f;
|
||||
ProjectileMovement->ProjectileGravityScale = 0.f;
|
||||
}
|
||||
|
||||
void AAuraProjectile::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
SetLifeSpan(LifeSpan);
|
||||
Sphere->OnComponentBeginOverlap.AddDynamic(this, &AAuraProjectile::OnSphereOverlap);
|
||||
LoopingSoundComponent = UGameplayStatics::SpawnSoundAttached(LoopingSound, GetRootComponent());
|
||||
}
|
||||
|
||||
void AAuraProjectile::Destroyed()
|
||||
{
|
||||
if (!bHit && !HasAuthority())
|
||||
{
|
||||
UGameplayStatics::PlaySoundAtLocation(GetWorld(), ImpactSound, GetActorLocation());
|
||||
UNiagaraFunctionLibrary::SpawnSystemAtLocation(this, ImpactEffect, GetActorLocation());
|
||||
LoopingSoundComponent->Stop();
|
||||
}
|
||||
Super::Destroyed();
|
||||
}
|
||||
|
||||
void AAuraProjectile::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent,
|
||||
AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp,
|
||||
int32 OtherBodyIndex,
|
||||
bool bFromSweep,
|
||||
const FHitResult& SweepResult)
|
||||
{
|
||||
if (OtherActor == GetInstigator()) return; //So that the projectile will not collide with the owning actor.
|
||||
UGameplayStatics::PlaySoundAtLocation(GetWorld(), ImpactSound, GetActorLocation());
|
||||
UNiagaraFunctionLibrary::SpawnSystemAtLocation(this, ImpactEffect, GetActorLocation());
|
||||
LoopingSoundComponent->Stop();
|
||||
|
||||
if (HasAuthority())
|
||||
{
|
||||
if (UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(OtherActor))
|
||||
{
|
||||
TargetASC->ApplyGameplayEffectSpecToSelf(*DamageEffectSpecHandle.Data.Get());
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
else { bHit = true; }
|
||||
|
||||
}
|
||||
|
||||
5
Source/Aura/Private/Input/AuraInputComponent.cpp
Normal file
5
Source/Aura/Private/Input/AuraInputComponent.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
|
||||
#include "Input/AuraInputComponent.h"
|
||||
|
||||
24
Source/Aura/Private/Input/AuraInputConfig.cpp
Normal file
24
Source/Aura/Private/Input/AuraInputConfig.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
|
||||
#include "Input/AuraInputConfig.h"
|
||||
|
||||
#include "InputAction.h"
|
||||
|
||||
const UInputAction* UAuraInputConfig::FindAbilityInputActionForTag(const FGameplayTag& InputTag,
|
||||
bool bLogNotFound) const
|
||||
{
|
||||
for (const FAuraInputAction& Action : AbilityInputActions)
|
||||
{
|
||||
if (Action.InputAction && Action.InputTag == InputTag)
|
||||
{
|
||||
return Action.InputAction;
|
||||
}
|
||||
}
|
||||
|
||||
if (bLogNotFound)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("Can't find AbilityInputAction for InputTag [%s], on InputConfig [%s]"), *InputTag.ToString(), *GetName());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
30
Source/Aura/Public/AbilitySystem/AuraProjectileSpell.h
Normal file
30
Source/Aura/Public/AbilitySystem/AuraProjectileSpell.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AbilitySystem/GameplayAbility/AuraGameplayAbility.h"
|
||||
#include "AuraProjectileSpell.generated.h"
|
||||
|
||||
class AAuraProjectile;
|
||||
class UGameplayEffect;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AURA_API UAuraProjectileSpell : public UAuraGameplayAbility
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
private:
|
||||
protected:
|
||||
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Projectile")
|
||||
void SpawnProjectile(const FVector ProjectileTargetLocation);
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||
TSubclassOf<AAuraProjectile> ProjectileClass;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TSubclassOf<UGameplayEffect> DamageEffectClass;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Abilities/GameplayAbility.h"
|
||||
#include "AuraGameplayAbility.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AURA_API UAuraGameplayAbility : public UGameplayAbility
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
FGameplayTag StartupInputTag;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Abilities/Tasks/AbilityTask.h"
|
||||
#include "TargetDataUnderMouse.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMouseTargetDataSignature, const FGameplayAbilityTargetDataHandle&, DataHandle);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AURA_API UTargetDataUnderMouse : public UAbilityTask
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Ability|Tasks", meta = (DisplayName = "TargetDataUnderMouse", HidePin = "OwningAbility", DefaultToSelf = "OwningAbility", BlueprintInternalUseOnly = true))
|
||||
static UTargetDataUnderMouse* CreateTargetDataUnderMouse(UGameplayAbility* OwningAbility);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FMouseTargetDataSignature ValidData;
|
||||
|
||||
private:
|
||||
virtual void Activate() override;
|
||||
|
||||
void SendMouseCursorData();
|
||||
};
|
||||
54
Source/Aura/Public/Actor/AuraProjectile.h
Normal file
54
Source/Aura/Public/Actor/AuraProjectile.h
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "GameplayEffectTypes.h"
|
||||
#include "AuraProjectile.generated.h"
|
||||
|
||||
class UNiagaraSystem;
|
||||
class USphereComponent;
|
||||
class UProjectileMovementComponent;
|
||||
|
||||
UCLASS()
|
||||
class AURA_API AAuraProjectile : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AAuraProjectile();
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
TObjectPtr<UProjectileMovementComponent> ProjectileMovement;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, meta = (ExposeOnSpawn = true))
|
||||
FGameplayEffectSpecHandle DamageEffectSpecHandle;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void Destroyed() override;
|
||||
|
||||
UFUNCTION()
|
||||
void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
|
||||
private:
|
||||
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
float LifeSpan = 15.f;
|
||||
|
||||
bool bHit = false;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
TObjectPtr<USphereComponent> Sphere;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TObjectPtr<UNiagaraSystem> ImpactEffect;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TObjectPtr<USoundBase> ImpactSound;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TObjectPtr<USoundBase> LoopingSound;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<UAudioComponent> LoopingSoundComponent;
|
||||
};
|
||||
47
Source/Aura/Public/Input/AuraInputComponent.h
Normal file
47
Source/Aura/Public/Input/AuraInputComponent.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AuraInputConfig.h"
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "AuraInputComponent.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AURA_API UAuraInputComponent : public UEnhancedInputComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
template<class UserClass, typename PressedFuncType, typename ReleasedFuncType, typename HeldFuncType>
|
||||
void BindAbilityActions(const UAuraInputConfig* InputConfig, UserClass* Object, PressedFuncType PressedFunc, ReleasedFuncType ReleasedFunc, HeldFuncType HeldFunc);
|
||||
};
|
||||
|
||||
template <class UserClass, typename PressedFuncType, typename ReleasedFuncType, typename HeldFuncType>
|
||||
void UAuraInputComponent::BindAbilityActions(const UAuraInputConfig* InputConfig, UserClass* Object,
|
||||
PressedFuncType PressedFunc, ReleasedFuncType ReleasedFunc, HeldFuncType HeldFunc)
|
||||
{
|
||||
check(InputConfig);
|
||||
|
||||
for (const FAuraInputAction& Action : InputConfig->AbilityInputActions)
|
||||
{
|
||||
if (Action.InputAction && Action.InputTag.IsValid())
|
||||
{
|
||||
if (PressedFunc)
|
||||
{
|
||||
BindAction(Action.InputAction, ETriggerEvent::Started, Object, PressedFunc, Action.InputTag);
|
||||
}
|
||||
if (ReleasedFunc)
|
||||
{
|
||||
BindAction(Action.InputAction, ETriggerEvent::Completed, Object, ReleasedFunc, Action.InputTag);
|
||||
}
|
||||
if (HeldFunc)
|
||||
{
|
||||
BindAction(Action.InputAction, ETriggerEvent::Triggered, Object, HeldFunc, Action.InputTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Source/Aura/Public/Input/AuraInputConfig.h
Normal file
37
Source/Aura/Public/Input/AuraInputConfig.h
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright Echo Devgroup
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "AuraInputConfig.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FAuraInputAction
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
const class UInputAction* InputAction = nullptr;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
FGameplayTag InputTag = FGameplayTag();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AURA_API UAuraInputConfig : public UDataAsset
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
const UInputAction* FindAbilityInputActionForTag(const FGameplayTag& InputTag, bool bLogNotFound = false) const;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TArray<FAuraInputAction> AbilityInputActions;
|
||||
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user