void UAblAbilityTaskRaycastValidator::Validate(const TWeakObjectPtr<UAblAbilityTaskValidatorContext>& Context, const TWeakObjectPtr<const UAblAbilityTask>& Task) const
{
	const UAblRayCastQueryTask* RaycastTask = CastChecked<const UAblRayCastQueryTask>(Task.Get());

	if (!RaycastTask->GetFireEvent() && !RaycastTask->GetCopyResultsToContext())
	{
		Context->AddWarning(LOCTEXT("AbilityValidatorRayCastNoOutput", "Raycast Task is set to not fire its event or copy its results to the context. This Task won't be able to do anything with its results."));
	}
}
void UAblAbilityLengthValidator::Validate(const TWeakObjectPtr<UAblAbilityTaskValidatorContext>& Context, const TWeakObjectPtr<const UAblAbilityTask>& Task) const
{
	const float AbilityLength = Context->GetAbility()->GetLength();
	const TArray<UAblAbilityTask*>& AllTasks = Context->GetAbility()->GetTasks();

	float LastTaskEndTime = 0.0f;
	for (const UAblAbilityTask* AbilityTask : AllTasks)
	{
		if (AbilityTask->GetEndTime() > AbilityLength)
		{
			FText WarningMessage = FText::Format(LOCTEXT("AbilityValidatorTaskTooLong", "Task {0} extends past the length of the ability. Is this intended?"), AbilityTask->GetTaskName());
			Context->AddWarning(WarningMessage);
		}

		LastTaskEndTime = FMath::Max(AbilityTask->GetEndTime(), LastTaskEndTime);
	}

	if (AbilityLength - LastTaskEndTime > KINDA_SMALL_NUMBER)
	{
		FText WarningMessage = FText::FormatOrdered(LOCTEXT("AbilityValidatorEmptySpace", "There is empty space in the timeline. The last task finishes at {0} but the ability has a length of {1}. Is this intended?"), LastTaskEndTime, AbilityLength);
		Context->AddWarning(WarningMessage);
	}
}