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());
	}
}