// Fill out your copyright notice in the Description page of Project Settings. #include "EnemyAIController.h" #include "EngineUtils.h" #include "DrawDebugHelpers.h" #include "Util.h" #define LogInfo(Msg) Util::log_info(TEXT("AEnemyIController"), Msg) #define LogError(Msg) Util::log_error(TEXT("AEnemyIController"), Msg) void AEnemyAIController::Tick(float delta_time) { Super::Tick(delta_time); switch(current_state) { case state_t::init: president = get_president(); if (president) { current_state = state_t::wait; } break; case state_t::wait: waiting_time += delta_time; if (waiting_time > wait_threshold) { waiting_time = 0; current_state = state_t::target; } break; case state_t::target: if (!president) { current_state = state_t::init; } else { FVector target_location = president->get_location(); const ABasePawn* local_pawn = Cast(GetPawn()); if (local_pawn) { FVector current_location = local_pawn->get_location(); FVector between = target_location - current_location; between = FVector(between.X, between.Y, 0); between.Normalize(); FVector extended = (between * overshoot_multiplier) + target_location; MoveToLocation(extended); current_state = state_t::moving; } else { // This will be cleaned up shortly. current_state = state_t::dead; } } break; case state_t::moving: if (move_completed) { move_completed = false; current_state = state_t::wait; } break; default: /* * Do nothing. */ break; } } void AEnemyAIController::OnMoveCompleted(FAIRequestID request_id, const FPathFollowingResult& result) { move_completed = true; } /** * Helper function to find president in level. */ ABasePawn* AEnemyAIController::get_president() const { ABasePawn* found = nullptr; for (TActorIterator iterator(GetWorld()); iterator; ++iterator) { AActor* actor = *iterator; if (actor && actor != this) { UClass* actor_class = actor->GetClass(); if (actor_class == (*president_class)) { if (found) { LogError("Multiple presidents found!"); break; } found = Cast(actor); } } } if (!found) { // LogError("No president found!"); } return found; }