// Fill out your copyright notice in the Description page of Project Settings. #include "PresidentAIController.h" #include "EngineUtils.h" #include "Util.h" #define LogInfo(Msg) Util::log_info(TEXT("APresidentAIController"), Msg) #define LogError(Msg) Util::log_error(TEXT("APresidentAIController"), Msg) void APresidentAIController::BeginPlay() { Super::BeginPlay(); /* * Initialize random stream. */ random.Initialize(FMath::Rand()); } void APresidentAIController::Tick(float delta) { Super::Tick(delta); switch (current_state) { case state_t::init: { // Without this offset, the path finding to return to starting location will fail with // invalid. I'm too sleepy to dig further. const FVector offset(1.0, 1.0, 0); starting_location = GetPawn()->GetActorLocation() + offset; target_location = starting_location; marker_locations = get_markers(); // Update state. current_state = state_t::idle; } break; case state_t::idle: { const bool should_wait = random.GetFraction() > .5; const bool is_home = target_location == starting_location; if (should_wait && is_home) { current_state = state_t::waiting; } else { target_location = is_home ? get_random_mark() : starting_location; MoveToLocation(target_location); current_state = state_t::moving; } } break; case state_t::moving: if (move_completed) { move_completed = false; current_state = state_t::waiting; } break; case state_t::waiting: waiting_time += delta; if (waiting_time > wait_threshold) { waiting_time = 0; current_state = state_t::idle; } break; default: /* * Do nothing. */ break; } } void APresidentAIController::OnMoveCompleted(FAIRequestID request_id, const FPathFollowingResult& result) { move_completed = true; } /** * Helper function to load all the markers in the level. */ TArray APresidentAIController::get_markers() const { TArray locations; for (TActorIterator iterator(GetWorld()); iterator; ++iterator) { AActor* actor = *iterator; if (actor && actor != this) { UClass* actor_class = actor->GetClass(); if (actor_class == marker_class) { locations.Add(actor->GetActorLocation()); } } } if (locations.Num() == 0) { LogError("No markers"); } return locations; } /** * Helper function for returning world location of randomly selected mark. * * @return World location vector of mark. */ FVector APresidentAIController::get_random_mark() const { if (marker_locations.Num() == 0) { LogError("No markers"); return FVector(); } const int index = random.RandRange(0, marker_locations.Num() - 1); return marker_locations[index]; }