EBTNodeResult::Type UBoolChange::ExecuteTask(UBehaviorTreeComponent & OwnerComp, uint8 * NodeMemory) { Super::ExecuteTask(OwnerComp, NodeMemory); if (!GetWorld()) { return EBTNodeResult::Failed; } if (!CurrentBanditController) { Controller = OwnerComp.GetAIOwner(); CurrentBanditController = Cast<ABanditController>(Controller); } if (CurrentBanditController) { OwnerComp.GetBlackboardComponent()->SetValueAsBool(TEXT("PlayerSpotted"), true); OwnerComp.GetBlackboardComponent()->SetValueAsBool(TEXT("PlayerNearby"), true); return EBTNodeResult::Succeeded; } return EBTNodeResult::Failed; }
EBTNodeResult::Type UBTTask_PlayAbility::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { FBTPlayAbilityTaskMemory* TaskMemory = reinterpret_cast<FBTPlayAbilityTaskMemory*>(NodeMemory); AAIController* const OwnerController = OwnerComp.GetAIOwner(); const UAblAbility* AbilityCDO = Cast<UAblAbility>(Ability.GetDefaultObject()); if (AbilityCDO && OwnerController) { if (APawn* Owner = OwnerController->GetPawn()) { if (UAblAbilityComponent* AbilityComponent = Owner->FindComponentByClass<UAblAbilityComponent>()) { if (!TaskMemory->bAbilityPlayed) { UAblAbilityContext* Context = UAblAbilityContext::MakeContext(AbilityCDO, AbilityComponent, Owner, nullptr); EAblAbilityStartResult Result = AbilityComponent->ActivateAbility(Context); if (Result == EAblAbilityStartResult::Success || Result == EAblAbilityStartResult::AsyncProcessing) { TaskMemory->bAbilityPlayed = true; if (MarkAsInProgressDuringExecution) { TaskMemory->AbilityComponent = AbilityComponent; return EBTNodeResult::InProgress; } else { return EBTNodeResult::Succeeded; } } else { return EBTNodeResult::Failed; } } } } } return EBTNodeResult::Failed; }
EBTNodeResult::Type UBTTask_FindPointNearWaypoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { AsbrAIController* aiController = Cast<AsbrAIController>(OwnerComp.GetAIOwner()); if (aiController == NULL) return EBTNodeResult::Failed; ATargetPoint* waypoint = aiController->GetWaypoint(); if (waypoint) { const float SearchRadius = 200.0f; const FVector SearchOrigin = waypoint->GetActorLocation(); const FVector Loc = UNavigationSystem::GetRandomPointInNavigableRadius(aiController, SearchOrigin, SearchRadius); if (Loc != FVector::ZeroVector) { OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID(), Loc); aiController->SetWaypointVisited(waypoint); // сообщаем что посетили waypoint (todo: надо учесть расстояние) return EBTNodeResult::Succeeded; } } return EBTNodeResult::Failed; }
EBTNodeResult::Type UShootAtEnemyTask::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { AMinionAIController* MinionController = Cast<AMinionAIController>(OwnerComp.GetAIOwner()); if (MinionController == NULL) { return EBTNodeResult::Failed; } AMinionCharacter* Minion = Cast<AMinionCharacter>(MinionController->GetPawn()); ABorderItem* Enemy = MinionController->GetEnemy(); if (CanAttack(Minion, Enemy)) { AttackEnemy(Minion, Enemy); return EBTNodeResult::InProgress; } else if (!Enemy) { return EBTNodeResult::Succeeded; } return EBTNodeResult::Failed; }
EBTNodeResult::Type UBTTask_MoveDirectlyToward::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { const UBlackboardComponent* MyBlackboard = OwnerComp.GetBlackboardComponent(); FBTMoveDirectlyTowardMemory* MyMemory = reinterpret_cast<FBTMoveDirectlyTowardMemory*>(NodeMemory); AAIController* MyController = OwnerComp.GetAIOwner(); EBTNodeResult::Type NodeResult = EBTNodeResult::Failed; if (MyController && MyBlackboard) { if (GET_AI_CONFIG_VAR(bEnableBTAITasks)) { UAITask_MoveTo* AIMoveTask = NewBTAITask<UAITask_MoveTo>(OwnerComp); if (AIMoveTask != nullptr) { bool bSetUp = false; if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Object::StaticClass()) { UObject* KeyValue = MyBlackboard->GetValue<UBlackboardKeyType_Object>(BlackboardKey.GetSelectedKeyID()); AActor* TargetActor = Cast<AActor>(KeyValue); if (TargetActor) { AIMoveTask->SetUp(MyController, FVector::ZeroVector, TargetActor, AcceptableRadius, /*bUsePathfinding=*/false, FAISystem::BoolToAIOption(bStopOnOverlap)); NodeResult = EBTNodeResult::InProgress; } else { UE_VLOG(MyController, LogBehaviorTree, Warning, TEXT("UBTTask_MoveDirectlyToward::ExecuteTask tried to go to actor while BB %s entry was empty"), *BlackboardKey.SelectedKeyName.ToString()); } } else if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass()) { const FVector TargetLocation = MyBlackboard->GetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID()); AIMoveTask->SetUp(MyController, TargetLocation, nullptr, AcceptableRadius, /*bUsePathfinding=*/false, FAISystem::BoolToAIOption(bStopOnOverlap)); NodeResult = EBTNodeResult::InProgress; } if (NodeResult == EBTNodeResult::InProgress) { AIMoveTask->ReadyForActivation(); } } } else { EPathFollowingRequestResult::Type RequestResult = EPathFollowingRequestResult::Failed; if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Object::StaticClass()) { UObject* KeyValue = MyBlackboard->GetValue<UBlackboardKeyType_Object>(BlackboardKey.GetSelectedKeyID()); AActor* TargetActor = Cast<AActor>(KeyValue); if (TargetActor) { RequestResult = bDisablePathUpdateOnGoalLocationChange ? MyController->MoveToLocation(TargetActor->GetActorLocation(), AcceptableRadius, bStopOnOverlap, /*bUsePathfinding=*/false, /*bProjectDestinationToNavigation=*/bProjectVectorGoalToNavigation, bAllowStrafe) : MyController->MoveToActor(TargetActor, AcceptableRadius, bStopOnOverlap, /*bUsePathfinding=*/false, bAllowStrafe); } } else if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass()) { const FVector TargetLocation = MyBlackboard->GetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID()); RequestResult = MyController->MoveToLocation(TargetLocation, AcceptableRadius, bStopOnOverlap, /*bUsePathfinding=*/false, /*bProjectDestinationToNavigation=*/bProjectVectorGoalToNavigation, bAllowStrafe); } if (RequestResult == EPathFollowingRequestResult::RequestSuccessful) { const FAIRequestID RequestID = MyController->GetCurrentMoveRequestID(); MyMemory->MoveRequestID = RequestID; WaitForMessage(OwnerComp, UBrainComponent::AIMessage_MoveFinished, RequestID); NodeResult = EBTNodeResult::InProgress; } else if (RequestResult == EPathFollowingRequestResult::AlreadyAtGoal) { NodeResult = EBTNodeResult::Succeeded; } } } return NodeResult; }
EBTNodeResult::Type UBTTask_Escape::ExecuteTask(UBehaviorTreeComponent& OwnedTree, uint8* Node) { AWolfAIController* Controller = Cast<AWolfAIController>(OwnedTree.GetAIOwner()); if (!Controller) { GLog->Log("Controller fail"); return EBTNodeResult::Failed; } FName SensedTargetKey = "SensedTarget"; AMyCharacter_FirstTry* Caveman = Cast<AMyCharacter_FirstTry>(OwnedTree.GetBlackboardComponent()->GetValueAsObject(SensedTargetKey)); if (Caveman) { TArray<FHitResult> HitResults; //Start and End Location of the capsule FVector StartLocation = Caveman->GetActorLocation(); FVector EndLocation = StartLocation; EndLocation.Z += Caveman->GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight() / 2; //Collision Channel ECollisionChannel ECC = ECollisionChannel::ECC_WorldDynamic; //Collision Shape FCollisionShape CollisionShape; //Making Collision in sphere CollisionShape.ShapeType = ECollisionShape::Sphere; CollisionShape.SetSphere(350); //Sweeping for possible escape nodes if (Caveman->GetWorld()->SweepMultiByChannel(HitResults, StartLocation, EndLocation, FQuat::FQuat(), ECC, CollisionShape)) { //DrawDebugSphere(Caveman->GetWorld(), ((EndLocation - StartLocation) / 2) + StartLocation, CollisionShape.GetSphereRadius(), 100, FColor::Green, true); TArray<AActor*> AllPathNodes; UGameplayStatics::GetAllActorsOfClass(Caveman->GetWorld(), APathNode::StaticClass(), AllPathNodes); APathNode* NextNode; NextNode = Cast<APathNode>(AllPathNodes[FMath::RandRange(0, AllPathNodes.Num() - 1)]); //Finding next possible node while (NextNode->bIsCurrentlyOccupied && AllPathNodes.Contains(NextNode)) { NextNode = Cast<APathNode>(AllPathNodes[FMath::RandRange(0, AllPathNodes.Num() - 1)]); GLog->Log("Fear success"); } //Occupy the node NextNode->bIsCurrentlyOccupied = true; //Set the new node in the blackboard OwnedTree.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>(BlackboardKey.GetSelectedKeyID(), NextNode); //OwnedTree.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>(Bl) GLog->Log("Success after while"); return EBTNodeResult::Succeeded; } } GLog->Log("General Fail"); return EBTNodeResult::Failed; }
EBTNodeResult::Type UBTTask_FlyTo::SchedulePathfindingRequest(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { if(!NavigationManager) NavigationManager = UDonNavigationHelper::DonNavigationManager(this); auto pawn = OwnerComp.GetAIOwner()->GetPawn(); auto myMemory = (FBT_FlyToTarget*)NodeMemory; auto blackboard = pawn ? pawn->GetController()->FindComponentByClass<UBlackboardComponent>() : NULL; // Validate internal state: if (!pawn || !myMemory || !blackboard || !NavigationManager) { UE_LOG(LogTemp, Log, TEXT("[DoN Navigation] BTTask_FlyTo has invalid data for AI Pawn or NodeMemory or NavigationManager. Unable to proceed.")); if(blackboard) HandleTaskFailure(blackboard); return EBTNodeResult::Failed; } // Validate blackboard key data: if(FlightLocationKey.SelectedKeyType != UBlackboardKeyType_Vector::StaticClass()) { UE_LOG(LogTemp, Log, TEXT("[DoN Navigation] Invalid FlightLocationKey. Expected Vector type, found %s"), *(FlightLocationKey.SelectedKeyType ? FlightLocationKey.SelectedKeyType->GetName() : FString("?"))); HandleTaskFailure(blackboard); return EBTNodeResult::Failed; } // Prepare input: myMemory->Reset(); myMemory->Metadata.ActiveInstanceIdx = OwnerComp.GetActiveInstanceIdx(); myMemory->Metadata.OwnerComp = &OwnerComp; myMemory->QueryParams = QueryParams; myMemory->QueryParams.CustomDelegatePayload = &myMemory->Metadata; myMemory->bIsANavigator = pawn->GetClass()->ImplementsInterface(UDonNavigator::StaticClass()); FVector flightDestination = blackboard->GetValueAsVector(FlightLocationKey.SelectedKeyName); // Bind result notification delegate: FDoNNavigationResultHandler resultHandler; resultHandler.BindDynamic(this, &UBTTask_FlyTo::Pathfinding_OnFinish); // Bind dynamic collision updates delegate: myMemory->DynamicCollisionListener.BindDynamic(this, &UBTTask_FlyTo::Pathfinding_OnDynamicCollisionAlert); // Schedule task: bool bTaskScheduled = NavigationManager->SchedulePathfindingTask(pawn, flightDestination, myMemory->QueryParams, DebugParams, resultHandler, myMemory->DynamicCollisionListener); if (bTaskScheduled) { if(myMemory->QueryResults.QueryStatus != EDonNavigationQueryStatus::Success) // for simple paths the scheduler may have already solved the path synchronously myMemory->QueryResults.QueryStatus = EDonNavigationQueryStatus::InProgress; return EBTNodeResult::InProgress; } else { HandleTaskFailure(blackboard); return EBTNodeResult::Failed; } }