void UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(AActor* Actor, FGameplayTag EventTag, FGameplayEventData Payload) { if (Actor && !Actor->IsPendingKill()) { IAbilitySystemInterface* AbilitySystemInterface = Cast<IAbilitySystemInterface>(Actor); if (AbilitySystemInterface != NULL) { UAbilitySystemComponent* AbilitySystemComponent = AbilitySystemInterface->GetAbilitySystemComponent(); if (AbilitySystemComponent != NULL) { FScopedPredictionWindow NewScopedWindow(AbilitySystemComponent, true); AbilitySystemComponent->HandleGameplayEvent(EventTag, &Payload); } } } }
void FAggregator::BroadcastOnDirty() { // If we are batching on Dirty calls (and we actually have dependents registered with us) then early out. if (FScopedAggregatorOnDirtyBatch::GlobalBatchCount > 0 && (Dependents.Num() > 0 || OnDirty.IsBound())) { FScopedAggregatorOnDirtyBatch::DirtyAggregators.Add(this); return; } if (IsBroadcastingDirty) { // Apologies for the vague warning but its very hard from this spot to call out what data has caused this. If this frequently happens we should improve this. ABILITY_LOG(Warning, TEXT("FAggregator detected cyclic attribute dependencies. We are skipping a recursive dirty call. Its possible the resulting attribute values are not what you expect!")); return; } TGuardValue<bool> Guard(IsBroadcastingDirty, true); OnDirty.Broadcast(this); TArray<FActiveGameplayEffectHandle> ValidDependents; for (FActiveGameplayEffectHandle Handle : Dependents) { UAbilitySystemComponent* ASC = Handle.GetOwningAbilitySystemComponent(); if (ASC) { ASC->OnMagnitudeDependencyChange(Handle, this); ValidDependents.Add(Handle); } } Dependents = ValidDependents; }
void UAbilityTask_WaitGameplayEffectRemoved::Activate() { if (Handle.IsValid() == false) { InvalidHandle.Broadcast(); EndTask(); return;; } UAbilitySystemComponent* EffectOwningAbilitySystemComponent = Handle.GetOwningAbilitySystemComponent(); if (EffectOwningAbilitySystemComponent) { FOnActiveGameplayEffectRemoved* DelPtr = EffectOwningAbilitySystemComponent->OnGameplayEffectRemovedDelegate(Handle); if (DelPtr) { OnGameplayEffectRemovedDelegateHandle = DelPtr->AddUObject(this, &UAbilityTask_WaitGameplayEffectRemoved::OnGameplayEffectRemoved); Registered = true; } } if (!Registered) { // GameplayEffect was already removed, treat this as a warning? Could be cases of immunity or chained gameplay rules that would instant remove something OnGameplayEffectRemoved(); } }
void FGameplayAbilitiesModule::GetActiveAbilitiesDebugDataForActor(AActor* Actor, FString& AbilityString, bool& bIsUsingAbilities) { UAbilitySystemComponent* AbilityComp = Actor->FindComponentByClass<UAbilitySystemComponent>(); bIsUsingAbilities = (AbilityComp != nullptr); int32 NumActive = 0; if (AbilityComp) { AbilityString = TEXT(""); for (const FGameplayAbilitySpec& AbilitySpec : AbilityComp->GetActivatableAbilities()) { if (AbilitySpec.Ability && AbilitySpec.IsActive()) { if (NumActive) { AbilityString += TEXT(", "); } UClass* AbilityClass = AbilitySpec.Ability->GetClass(); FString AbClassName = GetNameSafe(AbilityClass); AbClassName.RemoveFromEnd(TEXT("_c")); AbilityString += AbClassName; NumActive++; } } } if (NumActive == 0) { AbilityString = TEXT("None"); } }
void AGameplayAbilityTargetActor::BindToConfirmCancelInputs() { check(OwningAbility); UAbilitySystemComponent* ASC = OwningAbility->GetCurrentActorInfo()->AbilitySystemComponent.Get(); if (ASC) { const FGameplayAbilityActorInfo* Info = OwningAbility->GetCurrentActorInfo(); if (Info->IsLocallyControlled()) { // We have to wait for the callback from the AbilitySystemComponent. Which will always be instigated locally ASC->GenericLocalConfirmCallbacks.AddDynamic(this, &AGameplayAbilityTargetActor::ConfirmTargeting); // Tell me if the confirm input is pressed ASC->GenericLocalCancelCallbacks.AddDynamic(this, &AGameplayAbilityTargetActor::CancelTargeting); // Tell me if the cancel input is pressed } else { FGameplayAbilitySpecHandle Handle = OwningAbility->GetCurrentAbilitySpecHandle(); FPredictionKey PredKey = OwningAbility->GetCurrentActivationInfo().GetActivationPredictionKey(); GenericConfirmHandle = ASC->AbilityReplicatedEventDelegate(EAbilityGenericReplicatedEvent::GenericConfirm, Handle, PredKey ).AddUObject(this, &AGameplayAbilityTargetActor::ConfirmTargeting); GenericCancelHandle = ASC->AbilityReplicatedEventDelegate(EAbilityGenericReplicatedEvent::GenericCancel, Handle, PredKey ).AddUObject(this, &AGameplayAbilityTargetActor::CancelTargeting); if (ASC->CallReplicatedEventDelegateIfSet(EAbilityGenericReplicatedEvent::GenericConfirm, Handle, PredKey)) { return; } if (ASC->CallReplicatedEventDelegateIfSet(EAbilityGenericReplicatedEvent::GenericCancel, Handle, PredKey)) { return; } } } }
/** Outside code is saying 'stop everything and just forget about it' */ void AGameplayAbilityTargetActor::CancelTargeting() { UAbilitySystemComponent* ASC = OwningAbility->GetCurrentActorInfo()->AbilitySystemComponent.Get(); ASC->AbilityReplicatedEventDelegate(EAbilityGenericReplicatedEvent::GenericCancel, OwningAbility->GetCurrentAbilitySpecHandle(), OwningAbility->GetCurrentActivationInfo().GetActivationPredictionKey() ).Remove(GenericCancelHandle); CanceledDelegate.Broadcast(FGameplayAbilityTargetDataHandle()); Destroy(); }
int32 UAbilitySystemBlueprintLibrary::GetActiveGameplayEffectStackCount(FActiveGameplayEffectHandle ActiveHandle) { UAbilitySystemComponent* ASC = ActiveHandle.GetOwningAbilitySystemComponent(); if (ASC) { return ASC->GetCurrentStackCount(ActiveHandle); } return 0; }
FString UAbilitySystemBlueprintLibrary::GetActiveGameplayEffectDebugString(FActiveGameplayEffectHandle ActiveHandle) { FString Str; UAbilitySystemComponent* ASC = ActiveHandle.GetOwningAbilitySystemComponent(); if (ASC) { Str = ASC->GetActiveGEDebugString(ActiveHandle); } return Str; }
int32 UAbilitySystemBlueprintLibrary::GetActiveGameplayEffectStackLimitCount(FActiveGameplayEffectHandle ActiveHandle) { UAbilitySystemComponent* ASC = ActiveHandle.GetOwningAbilitySystemComponent(); if (ASC) { const UGameplayEffect* ActiveGE = ASC->GetGameplayEffectDefForHandle(ActiveHandle); if (ActiveGE) { return ActiveGE->StackLimitCount; } } return 0; }
void UAbilityTask_WaitGameplayEffectStackChange::OnDestroy(bool AbilityIsEnding) { UAbilitySystemComponent* EffectOwningAbilitySystemComponent = Handle.GetOwningAbilitySystemComponent(); if (EffectOwningAbilitySystemComponent && OnGameplayEffectStackChangeDelegateHandle.IsValid()) { FOnActiveGameplayEffectRemoved* DelPtr = EffectOwningAbilitySystemComponent->OnGameplayEffectRemovedDelegate(Handle); if (DelPtr) { DelPtr->Remove(OnGameplayEffectStackChangeDelegateHandle); } } Super::OnDestroy(AbilityIsEnding); }
void AGameplayAbilityTargetActor::ConfirmTargeting() { UAbilitySystemComponent* ASC = OwningAbility->GetCurrentActorInfo()->AbilitySystemComponent.Get(); ASC->AbilityReplicatedEventDelegate(EAbilityGenericReplicatedEvent::GenericConfirm, OwningAbility->GetCurrentAbilitySpecHandle(), OwningAbility->GetCurrentActivationInfo().GetActivationPredictionKey() ).Remove(GenericConfirmHandle); if (IsConfirmTargetingAllowed()) { ConfirmTargetingAndContinue(); if (bDestroyOnConfirmation) { Destroy(); } } }
void UAbilityTask_WaitGameplayTagRemoved::Activate() { UAbilitySystemComponent* ASC = GetTargetASC(); if (ASC && ASC->HasMatchingGameplayTag(Tag) == false) { Removed.Broadcast(); if(OnlyTriggerOnce) { EndTask(); return; } } Super::Activate(); }
/** Outside code is saying 'stop everything and just forget about it' */ void AGameplayAbilityTargetActor::CancelTargeting() { const FGameplayAbilityActorInfo* ActorInfo = (OwningAbility ? OwningAbility->GetCurrentActorInfo() : nullptr); UAbilitySystemComponent* ASC = (ActorInfo ? ActorInfo->AbilitySystemComponent.Get() : nullptr); if (ASC) { ASC->AbilityReplicatedEventDelegate(EAbilityGenericReplicatedEvent::GenericCancel, OwningAbility->GetCurrentAbilitySpecHandle(), OwningAbility->GetCurrentActivationInfo().GetActivationPredictionKey() ).Remove(GenericCancelHandle); } else { ABILITY_LOG(Warning, TEXT("AGameplayAbilityTargetActor::CancelTargeting called with null ASC! Actor %s"), *GetName()); } CanceledDelegate.Broadcast(FGameplayAbilityTargetDataHandle()); Destroy(); }
// TODO: polymorphic payload void UGameplayAbility::SendGameplayEvent(FGameplayTag EventTag, FGameplayEventData Payload) { if (NetExecutionPolicy == EGameplayAbilityNetExecutionPolicy::Predictive) { Payload.PredictionKey = CurrentActivationInfo.GetPredictionKeyForNewAction(); } AActor *OwnerActor = Cast<AActor>(GetOuter()); if (OwnerActor) { UAbilitySystemComponent* AbilitySystemComponent = OwnerActor->FindComponentByClass<UAbilitySystemComponent>(); if (ensure(AbilitySystemComponent)) { AbilitySystemComponent->HandleGameplayEvent(EventTag, &Payload); } } }
void UGameplayAbility::PreActivate(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, FOnGameplayAbilityEnded* OnGameplayAbilityEndedDelegate) { UAbilitySystemComponent* Comp = ActorInfo->AbilitySystemComponent.Get(); bIsActive = true; Comp->CancelAbilities(&CancelAbilitiesWithTag, nullptr, this); Comp->BlockAbilitiesWithTags(BlockAbilitiesWithTag); if (OnGameplayAbilityEndedDelegate) { OnGameplayAbilityEnded = *OnGameplayAbilityEndedDelegate; } Comp->NotifyAbilityActivated(Handle, this); }
void UAbilityTask_WaitGameplayEffectStackChange::Activate() { if (Handle.IsValid() == false) { InvalidHandle.Broadcast(Handle, 0, 0); EndTask(); return;; } UAbilitySystemComponent* EffectOwningAbilitySystemComponent = Handle.GetOwningAbilitySystemComponent(); if (EffectOwningAbilitySystemComponent) { FOnActiveGameplayEffectStackChange* DelPtr = EffectOwningAbilitySystemComponent->OnGameplayEffectStackChangeDelegate(Handle); if (DelPtr) { OnGameplayEffectStackChangeDelegateHandle = DelPtr->AddUObject(this, &UAbilityTask_WaitGameplayEffectStackChange::OnGameplayEffectStackChange); Registered = true; } } }
void AGameplayAbilityTargetActor::ConfirmTargeting() { const FGameplayAbilityActorInfo* ActorInfo = (OwningAbility ? OwningAbility->GetCurrentActorInfo() : nullptr); UAbilitySystemComponent* ASC = (ActorInfo ? ActorInfo->AbilitySystemComponent.Get() : nullptr); if (ASC) { ASC->AbilityReplicatedEventDelegate(EAbilityGenericReplicatedEvent::GenericConfirm, OwningAbility->GetCurrentAbilitySpecHandle(), OwningAbility->GetCurrentActivationInfo().GetActivationPredictionKey() ).Remove(GenericConfirmHandle); } else { ABILITY_LOG(Warning, TEXT("AGameplayAbilityTargetActor::ConfirmTargeting called with null Ability/ASC! Actor %s"), *GetName()); } if (IsConfirmTargetingAllowed()) { ConfirmTargetingAndContinue(); if (bDestroyOnConfirmation) { Destroy(); } } }
void UGameplayEffectExtension_LifestealTest::PostGameplayEffectExecute(const FGameplayModifierEvaluatedData &SelfData, const FGameplayEffectModCallbackData &Data) const { IGameplayTagsModule& GameplayTagsModule = IGameplayTagsModule::Get(); float DamageDone = Data.EvaluatedData.Magnitude; float LifestealPCT = SelfData.Magnitude; float HealthToRestore = -DamageDone * LifestealPCT; if (HealthToRestore > 0.f) { UAbilitySystemComponent *Source = Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent(); UGameplayEffect * LocalHealthRestore = HealthRestoreGameplayEffect; if (!LocalHealthRestore) { UProperty *HealthProperty = FindFieldChecked<UProperty>(UAbilitySystemTestAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED(UAbilitySystemTestAttributeSet, Health)); // Since this is a test class and we don't want to tie it any actual content assets, just construct a GameplayEffect here. LocalHealthRestore = NewObject<UGameplayEffect>(GetTransientPackage(), FName(TEXT("LifestealHealthRestore"))); LocalHealthRestore->Modifiers.SetNum(1); LocalHealthRestore->Modifiers[0].Magnitude.SetValue(HealthToRestore); LocalHealthRestore->Modifiers[0].ModifierOp = EGameplayModOp::Additive; LocalHealthRestore->Modifiers[0].Attribute.SetUProperty(HealthProperty); LocalHealthRestore->DurationPolicy = EGameplayEffectDurationType::Instant; LocalHealthRestore->Period.Value = UGameplayEffect::NO_PERIOD; } if (SelfData.Handle.IsValid()) { // We are coming from an active gameplay effect check(SelfData.Handle.IsValid()); } // Apply a GameplayEffect to restore health // We make the GameplayEffect's level = the health restored. This is one approach. We could also // try a basic restore 1 health item but apply a 2nd GE to modify that - but that seems like too many levels of indirection Source->ApplyGameplayEffectToSelf(LocalHealthRestore, HealthToRestore, Source->MakeEffectContext()); } }