void UGameplayTasksComponent::AddTaskToPriorityQueue(UGameplayTask& NewTask)
{
	const bool bStartOnTopOfSamePriority = (NewTask.GetResourceOverlapPolicy() == ETaskResourceOverlapPolicy::StartOnTop);
	int32 InsertionPoint = INDEX_NONE;
	
	for (int32 Idx = 0; Idx < TaskPriorityQueue.Num(); ++Idx)
	{
		if (TaskPriorityQueue[Idx] == nullptr)
		{
			continue;
		}

		if ((bStartOnTopOfSamePriority && TaskPriorityQueue[Idx]->GetPriority() <= NewTask.GetPriority())
			|| (!bStartOnTopOfSamePriority && TaskPriorityQueue[Idx]->GetPriority() < NewTask.GetPriority()))
		{
			TaskPriorityQueue.Insert(&NewTask, Idx);
			InsertionPoint = Idx;
			break;
		}
	}
	
	if (InsertionPoint == INDEX_NONE)
	{
		TaskPriorityQueue.Add(&NewTask);
	}
}
void UGameplayTasksComponent::OnGameplayTaskActivated(UGameplayTask& Task)
{
	// process events after finishing all operations
	FEventLock ScopeEventLock(this);

	if (Task.IsTickingTask())
	{
		check(TickingTasks.Contains(&Task) == false);
		TickingTasks.Add(&Task);

		// If this is our first ticking task, set this component as active so it begins ticking
		if (TickingTasks.Num() == 1)
		{
			UpdateShouldTick();
		}
	}
	if (Task.IsSimulatedTask())
	{
		check(SimulatedTasks.Contains(&Task) == false);
		SimulatedTasks.Add(&Task);
	}

	IGameplayTaskOwnerInterface* TaskOwner = Task.GetTaskOwner();
	if (!Task.IsOwnedByTasksComponent() && TaskOwner)
	{
		TaskOwner->OnGameplayTaskActivated(Task);
	}
}
//----------------------------------------------------------------------//
// Priority and resources handling
//----------------------------------------------------------------------//
void UGameplayTasksComponent::AddTaskReadyForActivation(UGameplayTask& NewTask)
{
	UE_VLOG(this, LogGameplayTasks, Log, TEXT("AddTaskReadyForActivation %s"), *NewTask.GetName());

	ensure(NewTask.RequiresPriorityOrResourceManagement() == true);
	
	TaskEvents.Add(FGameplayTaskEventData(EGameplayTaskEvent::Add, NewTask));
	// trigger the actual processing only if it was the first event added to the list
	if (TaskEvents.Num() == 1 && CanProcessEvents())
	{
		ProcessTaskEvents();
	}
}
static FString DescribeTaskHelper(const UGameplayTask& TaskOb)
{
	const UObject* OwnerOb = Cast<const UObject>(TaskOb.GetTaskOwner());
	return FString::Printf(TEXT("\n  {white}%s%s {%s}%s:%d {white}Owner:{yellow}%s {white}Res:{yellow}%s"),
		*TaskOb.GetName(),
		TaskOb.GetInstanceName() != NAME_None ? *FString::Printf(TEXT(" {yellow}[%s]"), *TaskOb.GetInstanceName().ToString()) : TEXT(""),
		TaskOb.IsActive() ? TEXT("green") : TEXT("orange"),
		*TaskOb.GetTaskStateName(), TaskOb.GetPriority(),
		*GetNameSafe(OwnerOb),
		TaskOb.GetRequiredResources().IsEmpty() ? TEXT("None") : *TaskOb.GetRequiredResources().GetDebugDescription());
}
void UGameplayTasksComponent::EndAllResourceConsumingTasksOwnedBy(const IGameplayTaskOwnerInterface& TaskOwner)// , bool bNotifyOwner)
{
	{
		FEventLock ScopeEventLock(this);

		// can't reuse FindAllTasksOwnedBy here, it's important to remove from queue immediately
		for (int32 Idx = TaskPriorityQueue.Num() - 1; Idx >= 0; Idx--)
		{
			if (TaskPriorityQueue[Idx] && TaskPriorityQueue[Idx]->GetTaskOwner() == &TaskOwner)
			{
				UGameplayTask* Task = TaskPriorityQueue[Idx];
				TaskPriorityQueue[Idx] = nullptr;
				Task->TaskOwnerEnded();
			}
		}
	}

	UpdateTaskActivations();
}
void UGameplayTasksComponent::RemoveResourceConsumingTask(UGameplayTask& Task)
{
	UE_VLOG(this, LogGameplayTasks, Log, TEXT("RemoveResourceConsumingTask %s"), *Task.GetName());

	TaskEvents.Add(FGameplayTaskEventData(EGameplayTaskEvent::Remove, Task));
	// trigger the actual processing only if it was the first event added to the list
	if (TaskEvents.Num() == 1 && CanProcessEvents())
	{
		ProcessTaskEvents();
	}
}
void AAIController::UnclaimTaskResource(TSubclassOf<UGameplayTaskResource> ResourceClass)
{
    if (CachedGameplayTasksComponent)
    {
        const uint8 ResourceID = UGameplayTaskResource::GetResourceID(ResourceClass);
        if (ScriptClaimedResources.HasID(ResourceID) == true)
        {
            ScriptClaimedResources.RemoveID(ResourceID);

            UE_VLOG(this, LogGameplayTasks, Log, TEXT("UnclaimTaskResource %s"), *GetNameSafe(*ResourceClass));

            UGameplayTask* ResourceTask = CachedGameplayTasksComponent->FindResourceConsumingTaskByName(ResourceClass->GetFName());
            if (ResourceTask)
            {
                ResourceTask->EndTask();
            }
            UE_CVLOG(ResourceTask == nullptr, this, LogGameplayTasks, Warning, TEXT("UnclaimTaskResource failed to find UGameplayTask_ClaimResource instance"));
        }
    }
}
Esempio n. 8
0
//----------------------------------------------------------------------//
// UBTTaskNode IGameplayTaskOwnerInterface
//----------------------------------------------------------------------//
void UBTTaskNode::OnTaskDeactivated(UGameplayTask& Task)
{
	ensure(Task.GetTaskOwner() == this);
	UBehaviorTreeComponent* BTComp = GetBTComponentForTask(Task);
	if (BTComp)
	{
		// this is a super-default behavior. Specific task will surely like to 
		// handle this themselves, finishing with specific result
		const EBTTaskStatus::Type Status = BTComp->GetTaskStatus(this);
		FinishLatentTask(*BTComp, Status == EBTTaskStatus::Aborting ? EBTNodeResult::Aborted : EBTNodeResult::Succeeded);
	}
}
void UGameplayTask::OnGameplayTaskDeactivated(UGameplayTask& Task)
{
    // cleanup after deactivation
    if (&Task == ChildTask)
    {
        UE_VLOG(GetGameplayTasksComponent(), LogGameplayTasks, Verbose, TEXT("%s> Child task deactivated: %s (state: %s)"), *GetName(), *Task.GetName(), *Task.GetTaskStateName());
        if (Task.IsFinished())
        {
            ChildTask = nullptr;
        }
    }
}
EGameplayTaskRunResult UGameplayTasksComponent::RunGameplayTask(IGameplayTaskOwnerInterface& TaskOwner, UGameplayTask& Task, uint8 Priority, FGameplayResourceSet AdditionalRequiredResources, FGameplayResourceSet AdditionalClaimedResources)
{
	const FText NoneText = FText::FromString(TEXT("None"));

	if (Task.GetState() == EGameplayTaskState::Paused || Task.GetState() == EGameplayTaskState::Active)
	{
		// return as success if already running for the same owner, failure otherwise 
		return Task.GetTaskOwner() == &TaskOwner
			? (Task.GetState() == EGameplayTaskState::Paused ? EGameplayTaskRunResult::Success_Paused : EGameplayTaskRunResult::Success_Active)
			: EGameplayTaskRunResult::Error;
	}

	// this is a valid situation if the task has been created via "Construct Object" mechanics
	if (Task.GetState() == EGameplayTaskState::Uninitialized)
	{
		Task.InitTask(TaskOwner, Priority);
	}

	Task.AddRequiredResourceSet(AdditionalRequiredResources);
	Task.AddClaimedResourceSet(AdditionalClaimedResources);
	Task.ReadyForActivation();

	switch (Task.GetState())
	{
	case EGameplayTaskState::AwaitingActivation:
	case EGameplayTaskState::Paused:
		return EGameplayTaskRunResult::Success_Paused;
		break;
	case EGameplayTaskState::Active:
		return EGameplayTaskRunResult::Success_Active;
		break;
	case EGameplayTaskState::Finished:
		return EGameplayTaskRunResult::Success_Active;
		break;
	}

	return EGameplayTaskRunResult::Error;
}
void UGameplayTasksComponent::OnGameplayTaskDeactivated(UGameplayTask& Task)
{
	// process events after finishing all operations
	FEventLock ScopeEventLock(this);
	const bool bIsFinished = (Task.GetState() == EGameplayTaskState::Finished);

	if (Task.GetChildTask() && bIsFinished)
	{
		if (Task.HasOwnerFinished())
		{
			Task.GetChildTask()->TaskOwnerEnded();
		}
		else
		{
			Task.GetChildTask()->EndTask();
		}
	}

	if (Task.IsTickingTask())
	{
		// If we are removing our last ticking task, set this component as inactive so it stops ticking
		TickingTasks.RemoveSingleSwap(&Task);
	}

	if (Task.IsSimulatedTask())
	{
		SimulatedTasks.RemoveSingleSwap(&Task);
	}

	// Resource-using task
	if (Task.RequiresPriorityOrResourceManagement() && bIsFinished)
	{
		OnTaskEnded(Task);
	}

	IGameplayTaskOwnerInterface* TaskOwner = Task.GetTaskOwner();
	if (!Task.IsOwnedByTasksComponent() && !Task.HasOwnerFinished() && TaskOwner)
	{
		TaskOwner->OnGameplayTaskDeactivated(Task);
	}

	UpdateShouldTick();
}
void UGameplayTasksComponent::RemoveTaskFromPriorityQueue(UGameplayTask& Task)
{	
	const int32 RemovedTaskIndex = TaskPriorityQueue.Find(&Task);
	if (RemovedTaskIndex != INDEX_NONE)
	{
		TaskPriorityQueue.RemoveAt(RemovedTaskIndex, 1, /*bAllowShrinking=*/false);
	}
	else
	{
		// take a note and ignore
		UE_VLOG(this, LogGameplayTasks, Verbose, TEXT("RemoveTaskFromPriorityQueue for %s called, but it's not in the queue. Might have been already removed"), *Task.GetName());
	}
}
void UGameplayTasksComponent::OnTaskEnded(UGameplayTask& Task)
{
	ensure(Task.RequiresPriorityOrResourceManagement() == true);
	RemoveResourceConsumingTask(Task);
}
void UGameplayTask::OnGameplayTaskInitialized(UGameplayTask& Task)
{
    UE_VLOG(GetGameplayTasksComponent(), LogGameplayTasks, Verbose, TEXT("%s> Child task initialized: %s"), *GetName(), *Task.GetName());

    // only one child task is allowed
    if (ChildTask)
    {
        UE_VLOG(GetGameplayTasksComponent(), LogGameplayTasks, Verbose, TEXT(">> terminating previous child task: %s"), *ChildTask->GetName());
        ChildTask->EndTask();
    }

    ChildTask = &Task;
}