TArray<FActiveGameplayEffectHandle> FGameplayAbilityTargetData::ApplyGameplayEffectSpec(FGameplayEffectSpec& InSpec, FPredictionKey PredictionKey) { TArray<FActiveGameplayEffectHandle> AppliedHandles; if (!ensure(InSpec.GetContext().IsValid() && InSpec.GetContext().GetInstigatorAbilitySystemComponent())) { return AppliedHandles; } TArray<TWeakObjectPtr<AActor> > Actors = GetActors(); AppliedHandles.Reserve(Actors.Num()); for (TWeakObjectPtr<AActor> TargetActor : Actors) { UAbilitySystemComponent* TargetComponent = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor.Get()); if (TargetComponent) { // We have to make a new effect spec and context here, because otherwise the targeting info gets accumulated and things take damage multiple times FGameplayEffectSpec SpecToApply(InSpec); FGameplayEffectContextHandle EffectContext = SpecToApply.GetContext().Duplicate(); SpecToApply.SetContext(EffectContext); AddTargetDataToContext(EffectContext, false); AppliedHandles.Add(EffectContext.GetInstigatorAbilitySystemComponent()->ApplyGameplayEffectSpecToTarget(SpecToApply, TargetComponent, PredictionKey)); } } return AppliedHandles; }
FGameplayEffectContextHandle UGameplayAbility::GetEffectContext(const FGameplayAbilityActorInfo *ActorInfo) const { check(ActorInfo); FGameplayEffectContextHandle Context = FGameplayEffectContextHandle(UAbilitySystemGlobals::Get().AllocGameplayEffectContext()); // By default use the owner and avatar as the instigator and causer Context.AddInstigator(ActorInfo->OwnerActor.Get(), ActorInfo->AvatarActor.Get()); return Context; }
FVector UAbilitySystemBlueprintLibrary::EffectContextGetOrigin(FGameplayEffectContextHandle EffectContext) { if (EffectContext.HasOrigin()) { return EffectContext.GetOrigin(); } return FVector::ZeroVector; }
FHitResult UAbilitySystemBlueprintLibrary::EffectContextGetHitResult(FGameplayEffectContextHandle EffectContext) { if (EffectContext.GetHitResult()) { return *EffectContext.GetHitResult(); } return FHitResult(); }
void FGameplayCueHandler::GameplayCueActivated(const FGameplayTagContainer& GameplayCueTags, float NormalizedMagnitude, const FGameplayEffectContextHandle& EffectContext) { check(Owner); bool InstigatorLocal = EffectContext.IsLocallyControlled(); bool TargetLocal = OwnerIsLocallyControlled(); for (auto TagIt = GameplayCueTags.CreateConstIterator(); TagIt; ++TagIt) { if (FGameplayCueViewInfo* View = GetBestMatchingView(EGameplayCueEvent::OnActive, *TagIt, InstigatorLocal, TargetLocal)) { View->SpawnViewEffects(Owner, NULL, EffectContext); } FName MatchedTag; UFunction *Func = UAbilitySystemGlobals::Get().GetGameplayCueFunction(*TagIt, Owner->GetClass(), MatchedTag); if (Func) { FGameplayCueParameters Params; Params.NormalizedMagnitude = NormalizedMagnitude; Params.EffectContext = EffectContext; IGameplayCueInterface::DispatchBlueprintCustomHandler(Owner, Func, EGameplayCueEvent::OnActive, Params); } } }
void FGameplayAbilityTargetData::AddTargetDataToContext(FGameplayEffectContextHandle& Context, bool bIncludeActorArray) const { if (bIncludeActorArray && (GetActors().Num() > 0)) { Context.AddActors(GetActors()); } if (HasHitResult() && !Context.GetHitResult()) { Context.AddHitResult(*GetHitResult()); } if (HasOrigin()) { Context.AddOrigin(GetOrigin().GetLocation()); } }
void FGameplayCueHandler::GameplayCueExecuted(const FGameplayTagContainer& GameplayCueTags, float NormalizedMagnitude, const FGameplayEffectContextHandle& EffectContext) { check(Owner); bool InstigatorLocal = EffectContext.IsLocallyControlled(); bool TargetLocal = OwnerIsLocallyControlled(); for (auto TagIt = GameplayCueTags.CreateConstIterator(); TagIt; ++TagIt) { if (FGameplayCueViewInfo* View = GetBestMatchingView(EGameplayCueEvent::Executed, *TagIt, InstigatorLocal, TargetLocal)) { View->SpawnViewEffects(Owner, NULL, EffectContext); } } }
void FGameplayCueHandler::GameplayCueAdded(const FGameplayTagContainer& GameplayCueTags, float NormalizedMagnitude, const FGameplayEffectContextHandle& EffectContext) { check(Owner); bool InstigatorLocal = EffectContext.IsLocallyControlled(); bool TargetLocal = OwnerIsLocallyControlled(); for (auto TagIt = GameplayCueTags.CreateConstIterator(); TagIt; ++TagIt) { TArray<TSharedPtr<FGameplayCueViewEffects> > &Effects = SpawnedViewEffects.FindOrAdd(*TagIt); // Clear old effects if they existed? This will vary case to case. Removing old effects is the easiest approach ClearEffects(Effects); check(Effects.Num() == 0); if (FGameplayCueViewInfo * View = GetBestMatchingView(EGameplayCueEvent::WhileActive, *TagIt, InstigatorLocal, TargetLocal)) { TSharedPtr<FGameplayCueViewEffects> SpawnedEffects = View->SpawnViewEffects(Owner, &SpawnedObjects, EffectContext); Effects.Add(SpawnedEffects); } } }
bool UAbilitySystemBlueprintLibrary::EffectContextHasHitResult(FGameplayEffectContextHandle EffectContext) { return EffectContext.GetHitResult() != NULL; }
bool UAbilitySystemBlueprintLibrary::EffectContextIsInstigatorLocallyControlled(FGameplayEffectContextHandle EffectContext) { return EffectContext.IsLocallyControlled(); }
void UAbilitySystemBlueprintLibrary::EffectContextSetOrigin(FGameplayEffectContextHandle EffectContext, FVector Origin) { EffectContext.AddOrigin(Origin); }
void UAbilitySystemBlueprintLibrary::EffectContextAddHitResult(FGameplayEffectContextHandle EffectContext, FHitResult HitResult, bool bReset) { EffectContext.AddHitResult(HitResult, bReset); }
bool UAbilitySystemBlueprintLibrary::EffectContextIsValid(FGameplayEffectContextHandle EffectContext) { return EffectContext.IsValid(); }
TSharedPtr<FGameplayCueViewEffects> FGameplayCueViewInfo::SpawnViewEffects(AActor *Owner, TArray<UObject*> *SpawnedObjects, const FGameplayEffectContextHandle& EffectContext) const { check(Owner); TSharedPtr<FGameplayCueViewEffects> SpawnedEffects = TSharedPtr<FGameplayCueViewEffects>(new FGameplayCueViewEffects()); if (Sound) { SpawnedEffects->AudioComponent = UGameplayStatics::PlaySoundAttached(Sound, Owner->GetRootComponent()); if (SpawnedObjects) { SpawnedObjects->Add(SpawnedEffects->AudioComponent.Get()); } } if (ParticleSystem) { if (EffectContext.GetHitResult()) { const FHitResult &HitResult = *EffectContext.GetHitResult(); if (AttachParticleSystem) { SpawnedEffects->ParticleSystemComponent = UGameplayStatics::SpawnEmitterAttached(ParticleSystem, Owner->GetRootComponent(), NAME_None, HitResult.Location, HitResult.Normal.Rotation(), EAttachLocation::KeepWorldPosition); } else { bool AutoDestroy = SpawnedObjects == nullptr; SpawnedEffects->ParticleSystemComponent = UGameplayStatics::SpawnEmitterAtLocation(Owner->GetWorld(), ParticleSystem, HitResult.Location, HitResult.Normal.Rotation(), AutoDestroy); } } else { if (AttachParticleSystem) { SpawnedEffects->ParticleSystemComponent = UGameplayStatics::SpawnEmitterAttached(ParticleSystem, Owner->GetRootComponent()); } else { bool AutoDestroy = SpawnedObjects == nullptr; SpawnedEffects->ParticleSystemComponent = UGameplayStatics::SpawnEmitterAtLocation(Owner->GetWorld(), ParticleSystem, Owner->GetActorLocation(), Owner->GetActorRotation(), AutoDestroy); } } if (SpawnedObjects) { SpawnedObjects->Add(SpawnedEffects->ParticleSystemComponent.Get()); } else if (SpawnedEffects->ParticleSystemComponent.IsValid()) { for (int32 EmitterIndx = 0; EmitterIndx < SpawnedEffects->ParticleSystemComponent->EmitterInstances.Num(); EmitterIndx++) { if (SpawnedEffects->ParticleSystemComponent->EmitterInstances[EmitterIndx] && SpawnedEffects->ParticleSystemComponent->EmitterInstances[EmitterIndx]->CurrentLODLevel && SpawnedEffects->ParticleSystemComponent->EmitterInstances[EmitterIndx]->CurrentLODLevel->RequiredModule && SpawnedEffects->ParticleSystemComponent->EmitterInstances[EmitterIndx]->CurrentLODLevel->RequiredModule->EmitterLoops == 0) { ABILITY_LOG(Warning, TEXT("%s - particle system has a looping emitter. This should not be used in a executed GameplayCue!"), *SpawnedEffects->ParticleSystemComponent->GetName()); break; } } } } if (ActorClass) { FVector Location = Owner->GetActorLocation(); FRotator Rotation = Owner->GetActorRotation(); SpawnedEffects->SpawnedActor = Cast<AGameplayCueActor>(Owner->GetWorld()->SpawnActor(ActorClass, &Location, &Rotation)); if (SpawnedObjects) { SpawnedObjects->Add(SpawnedEffects->SpawnedActor.Get()); } } return SpawnedEffects; }