bool UBTDecorator_IsAtLocation::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const { bool bHasReached = false; AAIController* AIOwner = OwnerComp.GetAIOwner(); UPathFollowingComponent* PathFollowingComponent = AIOwner ? AIOwner->GetPathFollowingComponent() : nullptr; if (PathFollowingComponent) { const UBlackboardComponent* MyBlackboard = OwnerComp.GetBlackboardComponent(); if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Object::StaticClass()) { UObject* KeyValue = MyBlackboard->GetValue<UBlackboardKeyType_Object>(BlackboardKey.GetSelectedKeyID()); AActor* TargetActor = Cast<AActor>(KeyValue); if (TargetActor) { bHasReached = PathFollowingComponent->HasReached(*TargetActor, AcceptableRadius, false, bUseNavAgentGoalLocation); } } else if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass()) { const FVector TargetLocation = MyBlackboard->GetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID()); if (FAISystem::IsValidLocation(TargetLocation)) { bHasReached = PathFollowingComponent->HasReached(TargetLocation, AcceptableRadius); } } } return bHasReached; }
bool FindNodeOwner(AActor* OwningActor, class UBTNode* Node, UBehaviorTreeComponent*& OwningComp, int32& OwningInstanceIdx) { bool bFound = false; APawn* OwningPawn = Cast<APawn>(OwningActor); if (OwningPawn && OwningPawn->Controller) { bFound = FindNodeOwner(OwningPawn->Controller, Node, OwningComp, OwningInstanceIdx); } if (OwningActor && !bFound) { TArray<UBehaviorTreeComponent*> Components; OwningActor->GetComponents(Components); for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++) { UBehaviorTreeComponent* BTComp = Components[ComponentIndex]; if (BTComp) { const int32 InstanceIdx = BTComp->FindInstanceContainingNode(Node); if (InstanceIdx != INDEX_NONE) { OwningComp = BTComp; OwningInstanceIdx = InstanceIdx; bFound = true; break; } } } } return bFound; }
EBTNodeResult::Type UBTTask_MoveToPlayer::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { AEnemyAI *CharPC = Cast<AEnemyAI>(OwnerComp.GetAIOwner()); ASacredHeartCharacter *Enemy = Cast<ASacredHeartCharacter>(OwnerComp.GetBlackboardComponent()->GetValue<UBlackboardKeyType_Object>(CharPC->EnemyKeyID)); if (Enemy) { int bpm = Enemy->heartRate; if (bpm > 100) { CharPC->GetCharacter()->GetCharacterMovement()->MaxWalkSpeed = 550; CharPC->MoveToActor(Enemy, 5.f, true, true, true, 0, true); return EBTNodeResult::Succeeded; } else { return EBTNodeResult::Failed; } } else { return EBTNodeResult::Failed; } }
EBTNodeResult::Type UMyBTTask_FindWayPoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { /* Check whether the AIController component exists to avoid errors */ ABotAI* MyController = Cast<ABotAI>(OwnerComp.GetAIOwner()); if (MyController == nullptr) { return EBTNodeResult::Failed; } /* Gets pointer to a waypoint */ AEnemyWayPoint* CurrentWaypoint = MyController->GetWaypoint(); AActor* NewWaypoint = nullptr; /* Get all Actors of type "EnemyWayPoint" in the level, and Iterate through them */ TArray<AActor*> AllWaypoints; UGameplayStatics::GetAllActorsOfClass(MyController, AEnemyWayPoint::StaticClass(), AllWaypoints); /* Select one random waypoint by index */ NewWaypoint = AllWaypoints[FMath::RandRange(0, AllWaypoints.Num() - 1)]; if (NewWaypoint) { /* Assign the retrieved waypoint to blackboard as the new move destination */ OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>(BlackboardKey.GetSelectedKeyID(), NewWaypoint); return EBTNodeResult::Succeeded; } return EBTNodeResult::Failed; }
bool UBTTask_BlueprintBase::IsTaskExecuting() const { UBehaviorTreeComponent* OwnerComp = Cast<UBehaviorTreeComponent>(GetOuter()); EBTTaskStatus::Type TaskStatus = OwnerComp->GetTaskStatus(this); return (TaskStatus == EBTTaskStatus::Active); }
void UBTService_BlueprintBase::OnCeaseRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { Super::OnCeaseRelevant(OwnerComp, NodeMemory); if (!OwnerComp.HasAnyFlags(RF_BeginDestroyed) && OwnerComp.GetOwner()) { // force dropping all pending latent actions associated with this blueprint // we can't have those resuming activity when node is/was aborted BlueprintNodeHelpers::AbortLatentActions(OwnerComp, *this); if (AIOwner != nullptr && ReceiveActivationImplementations & FBTNodeBPImplementationHelper::AISpecific) { ReceiveDeactivationAI(AIOwner, AIOwner->GetPawn()); } else if (ReceiveActivationImplementations & FBTNodeBPImplementationHelper::Generic) { ReceiveDeactivation(ActorOwner); } } else { UE_LOG(LogBehaviorTree, Warning, TEXT("OnCeaseRelevant called on Blueprint service %s with invalid owner. OwnerComponent: %s, OwnerComponent Owner: %s. %s") , *GetNameSafe(this), *OwnerComp.GetName(), *GetNameSafe(OwnerComp.GetOwner()) , OwnerComp.HasAnyFlags(RF_BeginDestroyed) ? TEXT("OwnerComponent has BeginDestroyed flag") : TEXT("") ); } }
EBTNodeResult::Type UChooseNextWaypoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { // Get the patrol route auto ControlledPawn = OwnerComp.GetAIOwner()->GetPawn(); auto PatrolRoute = ControlledPawn->FindComponentByClass<UPatrolRoute>(); if (!ensure(PatrolRoute)) { return EBTNodeResult::Failed; } // Warn about empty patrol routes auto PatrolPoints = PatrolRoute->GetPatrolPoints(); if (PatrolPoints.Num() == 0) { UE_LOG(LogTemp, Warning, TEXT("A guard is missing patrol points.")); return EBTNodeResult::Failed; } // Set the next waypoint auto BlackboardComp = OwnerComp.GetBlackboardComponent(); auto Index = BlackboardComp->GetValueAsInt(IndexKey.SelectedKeyName); BlackboardComp->SetValueAsObject(WaypointKey.SelectedKeyName, PatrolPoints[Index]); // Cycle the index auto NextIndex = (Index + 1) % PatrolPoints.Num(); BlackboardComp->SetValueAsInt(IndexKey.SelectedKeyName, NextIndex); // UE_LOG(LogTemp, Warning, TEXT("Waypoint index: %i"), Index); return EBTNodeResult::Succeeded; }
EBTNodeResult::Type UMyBTTask_ResetRoute::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { /* Check whether the AIController component exists to avoid errors */ ABotAI* MyController = Cast<ABotAI>(OwnerComp.GetAIOwner()); if (MyController == nullptr) { return EBTNodeResult::Failed; } //uint8 BBResetRoute = OwnerComp.GetBlackboardComponent()->GetKeyID("ResetRoute"); //uint8 BBResetRoute = OwnerComp.GetBlackboardComponent()->GetKeyID("ResetRoute"); uint8 BBResetRoute = OwnerComp.GetBlackboardComponent()->GetKeyID("ResetRoute"); OwnerComp.GetBlackboardComponent()->SetValueAsBool(BBResetRoute, true); // uint8 BBResetRoute = OwnerComp.GetBlackboardComponent()->GetKeyID("ResetRoute"); return EBTNodeResult::Succeeded; }
void UBTTask_BlueprintBase::SetFinishOnMessageWithId(FName MessageName, int32 RequestID) { UBehaviorTreeComponent* OwnerComp = Cast<UBehaviorTreeComponent>(GetOuter()); if (OwnerComp) { OwnerComp->RegisterMessageObserver(this, MessageName, RequestID); } }
void UBTDecorator_BlueprintBase::OnBlackboardChange(const UBlackboardComponent& Blackboard, FBlackboard::FKey ChangedKeyID) { UBehaviorTreeComponent* BehaviorComp = (UBehaviorTreeComponent*)Blackboard.GetBrainComponent(); if (BehaviorComp && GetShouldAbort(*BehaviorComp)) { BehaviorComp->RequestExecution(this); } }
void UBTDecorator_CompareBBEntries::OnBlackboardChange(const UBlackboardComponent& Blackboard, FBlackboard::FKey ChangedKeyID) { UBehaviorTreeComponent* BehaviorComp = static_cast<UBehaviorTreeComponent*>(Blackboard.GetBrainComponent()); if (BehaviorComp && (BlackboardKeyA.GetSelectedKeyID() == ChangedKeyID || BlackboardKeyB.GetSelectedKeyID() == ChangedKeyID)) { BehaviorComp->RequestExecution(this); } }
void UBMAgroCheck::TickNode(UBehaviorTreeComponent&OwnerComp, uint8* NodeMemory, float DeltaSeconds) { Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds); if (ThisTree == nullptr || ThisController == nullptr || ThisAICharacter == nullptr) { ThisTree = OwnerComp.GetCurrentTree(); ThisController = Cast<ABMAIController>(OwnerComp.GetAIOwner()); ThisAICharacter = Cast<ABMBossCharacter>(ThisController->GetPawn()); if (ThisTree == nullptr || ThisController == nullptr || ThisAICharacter == nullptr) { UE_LOG(LogTemp, Warning, TEXT("Warning Agro Service performed on invalid AI")); return; } } // Initialize a sweep params struct with trace complex set to true FCollisionQueryParams SphereSweepParams(FName(TEXT("AgroCheckSweep")), true, ThisAICharacter); FCollisionObjectQueryParams ObjectQuery(ECC_GameTraceChannel1); // Initialize Hit Result FHitResult HitOut(ForceInit); DrawDebugSphere(ThisAICharacter->GetWorld(), ThisAICharacter->GetActorLocation(), 1500, 12, FColor::Red, false, 4.0f); // Perform the sweep and check boolean return, we will only be checking for BMCharacter objects bool bResult = ThisAICharacter->GetWorld()->SweepSingleByObjectType(HitOut, ThisAICharacter->GetActorLocation(), ThisAICharacter->GetActorLocation() + FVector(0.0f, 0.0f, 10.0f), FQuat(), ObjectQuery, FCollisionShape::MakeSphere(1500), SphereSweepParams); if (bResult) { ThisController->GetBlackboard()->SetValueAsObject(TEXT("TargetToFollow"), HitOut.GetActor()); ThisController->GetBlackboard()->SetValueAsVector(TEXT("HomeLocation"), ThisAICharacter->GetActorLocation()); ThisController->GetBlackboard()->SetValueAsVector(TEXT("TargetLocation"), HitOut.GetActor()->GetActorLocation()); ThisController->TrackToTarget(); } else { ThisController->GetBlackboard()->SetValueAsObject(TEXT("TargetToFollow"), nullptr); ThisController->StopTrack(); } }
//----------------------------------------------------------------------// // 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); } }
EBTNodeResult::Type UBTTaskNode_ChooseNextSpell::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { Super::ExecuteTask(OwnerComp, NodeMemory); auto controller = Cast<ABaseAIController>(OwnerComp.GetAIOwner()); auto blackboard = OwnerComp.GetBlackboardComponent(); auto spellData = controller->GetNextSpell(); blackboard->SetValueAsObject("NextSpell", spellData); return EBTNodeResult::Type::Succeeded; }
FString FBehaviorTreeDebugger::DescribeInstance(UBehaviorTreeComponent& InstanceToDescribe) const { FString ActorDesc; if (InstanceToDescribe.GetOwner()) { AController* TestController = Cast<AController>(InstanceToDescribe.GetOwner()); ActorDesc = TestController ? TestController->GetName() : InstanceToDescribe.GetOwner()->GetActorLabel(); } return ActorDesc; }
bool UBTDecorator_TagCooldown::HasCooldownFinished(const UBehaviorTreeComponent& OwnerComp) const { const float TagCooldownEndTime = OwnerComp.GetTagCooldownEndTime(CooldownTag); if (TagCooldownEndTime == 0.f) { // special case, we don't have an end time yet for this cooldown tag return true; } const float TimePassed = (OwnerComp.GetWorld()->GetTimeSeconds() - TagCooldownEndTime); return TimePassed >= CooldownDuration; }
void UBTComposite_SimpleParallel::NotifyChildExecution(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32 ChildIdx, EBTNodeResult::Type& NodeResult) const { FBTParallelMemory* MyMemory = (FBTParallelMemory*)NodeMemory; if (ChildIdx == EBTParallelChild::MainTask) { MyMemory->MainTaskResult = NodeResult; if (NodeResult == EBTNodeResult::InProgress) { EBTTaskStatus::Type Status = OwnerComp.GetTaskStatus(Children[EBTParallelChild::MainTask].ChildTask); if (Status == EBTTaskStatus::Active) { // can't register if task is currently being aborted (latent abort returns in progress) MyMemory->bMainTaskIsActive = true; MyMemory->bForceBackgroundTree = false; OwnerComp.RegisterParallelTask(Children[EBTParallelChild::MainTask].ChildTask); RequestDelayedExecution(OwnerComp, EBTNodeResult::Succeeded); } } else if (MyMemory->bMainTaskIsActive) { MyMemory->bMainTaskIsActive = false; const int32 MyInstanceIdx = OwnerComp.FindInstanceContainingNode(this); OwnerComp.UnregisterParallelTask(Children[EBTParallelChild::MainTask].ChildTask, MyInstanceIdx); if (NodeResult != EBTNodeResult::Aborted && !MyMemory->bRepeatMainTask) { // check if subtree should be aborted when task finished with success/failed result if (FinishMode == EBTParallelMode::AbortBackground) { OwnerComp.RequestExecution((UBTCompositeNode*)this, MyInstanceIdx, Children[EBTParallelChild::MainTask].ChildTask, EBTParallelChild::MainTask, NodeResult); } } } else if (NodeResult == EBTNodeResult::Succeeded && FinishMode == EBTParallelMode::WaitForBackground) { // special case: if main task finished instantly, but composite is supposed to wait for background tree, // request single run of background tree anyway MyMemory->bForceBackgroundTree = true; RequestDelayedExecution(OwnerComp, EBTNodeResult::Succeeded); } } }
EBTNodeResult::Type URandomWander::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { UBlackboardComponent* Blackboard = OwnerComp.GetBlackboardComponent(); if (!GetWorld()) { return EBTNodeResult::Failed; } FVector NewWaypoint = FVector::ZeroVector; FVector CurrentPos = Blackboard->GetOwner()->GetActorLocation(); NewWaypoint.X = CurrentPos.X + FMath::FRandRange(-5000, 5000); NewWaypoint.Y = CurrentPos.Y + FMath::FRandRange(-5000, 5000); while (FVector::Dist(NewWaypoint, Blackboard->GetOwner()->GetActorLocation()) <= 2000.f && TraceFromPosition(OutResult, 100.f, ECollisionChannel::ECC_EngineTraceChannel1, NewWaypoint, OwnerComp) == false) { NewWaypoint.X = CurrentPos.X + FMath::FRandRange(-5000, 5000); NewWaypoint.Y = CurrentPos.Y + FMath::FRandRange(-5000, 5000); } if (!NewWaypoint.IsZero()) { Blackboard->SetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID(), NewWaypoint); return EBTNodeResult::Succeeded; } return EBTNodeResult::Failed; }
void UBTNode::InitializeInSubtree(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& NextInstancedIndex, EBTMemoryInit::Type InitType) const { if (bCreateNodeInstance) { // composite nodes can't be instanced! check(IsA(UBTCompositeNode::StaticClass()) == false); UBTNode* NodeInstance = OwnerComp.NodeInstances.IsValidIndex(NextInstancedIndex) ? OwnerComp.NodeInstances[NextInstancedIndex] : NULL; if (NodeInstance == NULL) { NodeInstance = NewObject<UBTNode>(&OwnerComp, GetClass(), GetFName(), RF_NoFlags, (UObject*)(this)); NodeInstance->InitializeNode(GetParentNode(), GetExecutionIndex(), GetMemoryOffset(), GetTreeDepth()); NodeInstance->bIsInstanced = true; OwnerComp.NodeInstances.Add(NodeInstance); } check(NodeInstance); NodeInstance->SetOwner(OwnerComp.GetOwner()); FBTInstancedNodeMemory* MyMemory = GetSpecialNodeMemory<FBTInstancedNodeMemory>(NodeMemory); MyMemory->NodeIdx = NextInstancedIndex; NodeInstance->OnInstanceCreated(OwnerComp); NextInstancedIndex++; } else { InitializeMemory(OwnerComp, NodeMemory, InitType); } }
EBTNodeResult::Type USetMaxWalkSpeed::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { Super::ExecuteTask(OwnerComp, NodeMemory); if (!GetWorld()) { return EBTNodeResult::Failed; } AActor* AnnaActor = OwnerComp.GetBlackboardComponent()->GetOwner(); if (AnnaActor) { ACharacter* AnnaCharacter = Cast<AController>(AnnaActor)->GetCharacter(); if (AnnaCharacter) { AnnaCharacter->GetCharacterMovement()->MaxWalkSpeed = DesiredMaxSpeed; EBTNodeResult::Succeeded; } } return EBTNodeResult::Failed; }
void UBTDecorator_BlueprintBase::OnBecomeRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { if (AIOwner != nullptr && ReceiveObserverActivatedImplementations & FBTNodeBPImplementationHelper::AISpecific) { ReceiveObserverActivatedAI(AIOwner, AIOwner->GetPawn()); } else if (ReceiveObserverActivatedImplementations & FBTNodeBPImplementationHelper::Generic) { ReceiveObserverActivated(ActorOwner); } if (GetNeedsTickForConditionChecking()) { // if set up as observer, and has a condition check, we want to check the condition every frame // highly inefficient, but hopefully people will use it only for prototyping. bNotifyTick = true; } UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent(); if (BlackboardComp) { for (int32 NameIndex = 0; NameIndex < ObservedKeyNames.Num(); NameIndex++) { const FBlackboard::FKey KeyID = BlackboardComp->GetKeyID(ObservedKeyNames[NameIndex]); if (KeyID != FBlackboard::InvalidKey) { BlackboardComp->RegisterObserver(KeyID, this, FOnBlackboardChange::CreateUObject(this, &UBTDecorator_BlueprintBase::OnBlackboardChange)); } } } }
EBTNodeResult::Type UATBTTask_MoveArea::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { UNavigationSystem* NavigationSystem = UNavigationSystem::GetCurrent(GetWorld()); AATCharacterAI* MyCharacter = Cast<AATCharacterAI>(OwnerComp.GetAIOwner()->GetPawn()); if (NavigationSystem != nullptr && MyCharacter != nullptr) { FNavLocation RandomPointIn; if (NavigationSystem->GetRandomPointInNavigableRadius(MyCharacter->GetActorLocation(), MyCharacter->AreaRadius, RandomPointIn)) { OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Vector>(GetSelectedBlackboardKey(), RandomPointIn.Location); return EBTNodeResult::Succeeded; } } return EBTNodeResult::Failed; }
void UBTDecorator_TimeLimit::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) { OwnerComp.RequestExecution(this); // make sure that next tick won't happen before execution request is processed SetNextTickTime(NodeMemory, 1000000.0f); }
EBTNodeResult::Type USetNextTargetPoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { Super::ExecuteTask(OwnerComp, NodeMemory); if (!GetWorld()) { return EBTNodeResult::Failed; } //Set the blackboard to make calling it easier in the future UBlackboardComponent* Blackboard = OwnerComp.GetBlackboardComponent(); //Get the ID of the key that we state in the editor uint8 TargetKeyID = Blackboard->GetKeyID(TargetName); //Get the AI so we can call a function on it UObject* SelfActor = Blackboard->GetValue<UBlackboardKeyType_Object>(TargetKeyID); //Cast it to the proper class AShadowAnnaCharacter* ShadowAnna = Cast<AShadowAnnaCharacter>(SelfActor); if (ShadowAnna) { //IF the cast works call the function //FVector NewTarget = ShadowAnna->SetNextTargetPoint(); //Blackboard->SetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID(), NewTarget); return EBTNodeResult::Succeeded; } return EBTNodeResult::Failed; }
// @note I know it's ugly to have "return" statements in many places inside a function, but the way // around was very awkward here bool UBTDecorator_CompareBBEntries::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const { // first of all require same type // @todo this could be checked statically (i.e. in editor, asset creation time)! if (BlackboardKeyA.SelectedKeyType != BlackboardKeyB.SelectedKeyType) { return false; } const UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent(); if (BlackboardComp) { //BlackboardComp->GetKeyType const EBlackboardCompare::Type Result = BlackboardComp->CompareKeyValues(BlackboardKeyA.SelectedKeyType, BlackboardKeyA.GetSelectedKeyID(), BlackboardKeyB.GetSelectedKeyID()); static_assert(int32(EBlackboardCompare::Equal) == int32(EBlackBoardEntryComparison::Equal) && int32(EBlackboardCompare::NotEqual) == int32(EBlackBoardEntryComparison::NotEqual), "These values need to be equal"); return int32(Operator) == int32(Result); } return false; }
void UBTTaskNode::ReceivedMessage(UBrainComponent* BrainComp, const FAIMessage& Message) { UBehaviorTreeComponent* OwnerComp = static_cast<UBehaviorTreeComponent*>(BrainComp); check(OwnerComp); const uint16 InstanceIdx = OwnerComp->FindInstanceContainingNode(this); if (OwnerComp->InstanceStack.IsValidIndex(InstanceIdx)) { uint8* NodeMemory = GetNodeMemory<uint8>(OwnerComp->InstanceStack[InstanceIdx]); OnMessage(*OwnerComp, NodeMemory, Message.MessageName, Message.RequestID, Message.Status == FAIMessage::Success); } else { UE_VLOG(OwnerComp->GetOwner(), LogBehaviorTree, Warning, TEXT("UBTTaskNode::ReceivedMessage called while %s node no longer in active BT") , *GetNodeName()); } }
void UBTDecorator_CompareBBEntries::OnCeaseRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent(); if (BlackboardComp) { BlackboardComp->UnregisterObserversFrom(this); } }
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) { 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; }
void UBTDecorator_CompareBBEntries::OnBecomeRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent(); if (BlackboardComp) { BlackboardComp->RegisterObserver(BlackboardKeyA.GetSelectedKeyID(), this, FOnBlackboardChange::CreateUObject(this, &UBTDecorator_CompareBBEntries::OnBlackboardChange)); BlackboardComp->RegisterObserver(BlackboardKeyB.GetSelectedKeyID(), this, FOnBlackboardChange::CreateUObject(this, &UBTDecorator_CompareBBEntries::OnBlackboardChange)); } }
EBTNodeResult::Type UEngageTask::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { UBehaviorTreeComponent* BTComp = &OwnerComp; const UBlackboardComponent* BlackboardComp = BTComp->GetBlackboardComponent(); AAgentController* Controller = Cast<AAgentController>(BTComp->GetAIOwner()); if (Controller == NULL) { return EBTNodeResult::Failed; } else { class AAgent* Agent = Controller->GetAgentOwner(); // If the agent's weapon has ammo in it if (Agent->GetCurrentWeapon()->CalculateAmmo() > 0) { // Ensure reload is set to false because it should have been reloaded at this stage Agent->EndReload(); // Shoot Agent->Fire(); } else { // Stop firing if firing Agent->StopFiring(); // Reload Agent->BeginReload(); } return EBTNodeResult::Succeeded; } return EBTNodeResult::Failed; }