Indie · UE4 · AI Systems · Solo · 2022

Humanity Last Resort

Humanity Last Resort

A 3D city-building simulation in which you manage a resort to satisfy aggressive alien tourists — or risk the world's destruction. Real-time resource management, placement mechanics, and a Needs-driven AI system where every alien has a priority queue of desires. If satisfaction drops too low, the global mood collapses and it's game over.

UE4 C++ AI Needs System Object Pooling Subsystems Delegates
What I Built
  • AI Needs system — each alien carries a sorted Need list; TryGetTask() picks the most urgent unsatisfied need and queries the world for a matching facility.
  • AlienSubsystem — object-pooled world subsystem ticking the full alien state machine (Idle → TryGetTask → Arrived → DoTask → Leaving).
  • GlobalMood delegate — mood aggregated from all aliens; fires SpawnRateUpdate at thresholds 80/60/40 and GameOver below 30.
  • Placement & selection UI — drag-and-drop building placement with snap grids, contextual selection highlighting, and resource cost validation.
  • Resource management — dynamic supply/demand curves for 6 resource types; supervisored by Mohamed Hafez (Tech Director, Limbic Entertainment).

AI Needs — TryGetTask()

Needs are sorted by CurValue (lowest = most urgent). On repeated failure the alien's mood is decremented; once all tasks are exhausted the alien state flips to Leaving.

Alien.cpp — TryGetTask()
void AAlien::TryGetTask()
{
    // Sort needs ascending — lowest value is most urgent
    Needs.Sort([](const FNeed& A, const FNeed& B)
        { return A.CurValue < B.CurValue; });

    for (FNeed& Need : Needs)
    {
        if (Need.CurValue >= Need.SatisfiedThreshold) continue;

        AActor* Facility = AlienSubsystem->FindFacilityFor(Need.Type, GetActorLocation());
        if (Facility)
        {
            CurrentTask  = { Need.Type, Facility };
            AlienState   = EAlienState::MovingToTask;
            return;
        }
        // Facility not found — penalise mood
        --CurFailedTasks;
        ChangeMood(-BadMoodVal);
    }

    // No satisfiable need found — give up and leave
    AlienState = EAlienState::Leaving;
}
AlienSubsystem — GlobalMood Delegates

The subsystem aggregates mood from all active aliens and fires spawn-rate delegates at each threshold. Dropping below 30 triggers the lose condition.

AlienSubsystem.cpp — UpdateGlobalMood()
void UAlienSubsystem::UpdateGlobalMood()
{
    float Total = 0.f;
    for (AAlien* A : ActiveAliens) Total += A->GetMood();
    GlobalMood = ActiveAliens.Num() > 0
               ? Total / ActiveAliens.Num()
               : 100.f;

    // Fire delegates at mood thresholds
    if      (GlobalMood <= 30.f) OnGameOver.Broadcast();
    else if (GlobalMood <= 40.f) OnSpawnRateUpdate.Broadcast(ESpawnRate::Crisis);
    else if (GlobalMood <= 60.f) OnSpawnRateUpdate.Broadcast(ESpawnRate::Slow);
    else if (GlobalMood <= 80.f) OnSpawnRateUpdate.Broadcast(ESpawnRate::Normal);
    else                           OnSpawnRateUpdate.Broadcast(ESpawnRate::Fast);
}

void UAlienSubsystem::TickStateMachine(AAlien* A, float DT)
{
    switch (A->AlienState)
    {
    case EAlienState::Idle:
        A->TryGetTask(); break;
    case EAlienState::Arrived:
        A->DoTask(DT);   break;
    case EAlienState::Leaving:
        A->Leave();
        ActiveAliens.Remove(A);
        AlienPool.Return(A);   // back to object pool
        UpdateGlobalMood();     // re-evaluate after departure
        break;
    }
}
Release July 20, 2022 Engine Unreal Engine 4 Language C++ Category Simulation · Strategy Supervisor Mohamed Hafez — Limbic ↗ Play khaledelsayed.itch.io ↗
Connect