130 lines
2.8 KiB
C++
Executable File
130 lines
2.8 KiB
C++
Executable File
// 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<FVector> APresidentAIController::get_markers() const
|
|
{
|
|
TArray<FVector> locations;
|
|
for (TActorIterator<AActor> 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];
|
|
}
|
|
|