// Copyright Echo Devgroup #include "AbilitySystem/AuraProjectileSpell.h" #include "AbilitySystemBlueprintLibrary.h" #include "AbilitySystemComponent.h" #include "AuraGameplayTags.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(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( ProjectileClass, SpawnTransform, GetOwningActorFromActorInfo(), Cast(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()); const FAuraGameplayTags GameplayTags = FAuraGameplayTags::Get(); UAbilitySystemBlueprintLibrary::AssignTagSetByCallerMagnitude(SpecHandle, GameplayTags.Damage, Damage); Projectile->DamageEffectSpecHandle = SpecHandle; Projectile->FinishSpawning(SpawnTransform); } }