61 lines
1.9 KiB
C++
61 lines
1.9 KiB
C++
// © 2025 Naked People Team. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "NPCType.h"
|
|
#include "Subsystems/WorldSubsystem.h"
|
|
#include "NakedDesire/Global/TimeOfDaySubsystem.h"
|
|
#include "NPCDirectorSubsystem.generated.h"
|
|
|
|
class ANPC;
|
|
class APawn;
|
|
class UNPCDirectorConfig;
|
|
|
|
/**
|
|
* The GDD §17.1 NPCManager: single authority for the crowd around the player (§10.2, §19).
|
|
* A WorldSubsystem (like UMissionSubsystem / UTimeOfDaySubsystem) — it needs world access plus the
|
|
* day/night phase to drive density.
|
|
*
|
|
* Keeps a pool of NPC actors prewarmed from UNPCDirectorConfig::SpawnTable and, on a light timer,
|
|
* reconciles the live population: recycles NPCs past the despawn radius and activates pooled ones at
|
|
* NavMesh points in the spawn ring until the phase-appropriate target count is met. Mesh-agnostic —
|
|
* it never touches what an NPC looks like, only how many exist and where. Supersedes the BP spawner.
|
|
*/
|
|
UCLASS()
|
|
class NAKEDDESIRE_API UNPCDirectorSubsystem : public UWorldSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
virtual void OnWorldBeginPlay(UWorld& InWorld) override;
|
|
virtual void Deinitialize() override;
|
|
|
|
private:
|
|
UFUNCTION()
|
|
void HandlePhaseChanged(EDayPhase NewPhase);
|
|
|
|
void PrewarmPool();
|
|
void UpdatePopulation(); // timer-driven reconcile
|
|
int32 CurrentTargetCount() const;
|
|
|
|
ANPC* TakeFromPool();
|
|
void ReturnToPool(ANPC* NPC);
|
|
ENPCType PickWeightedClass() const;
|
|
bool FindSpawnPoint(const FVector& Around, FVector& OutLocation) const;
|
|
TSubclassOf<ANPC> GetRandomNPCClass(TArray<TSubclassOf<ANPC>> InNPCClasses);
|
|
|
|
APawn* GetPlayerPawn() const;
|
|
UNPCDirectorConfig* GetConfig() const;
|
|
|
|
// Inactive (hidden) NPCs ready to activate.
|
|
UPROPERTY()
|
|
TArray<TObjectPtr<ANPC>> Pool;
|
|
|
|
// Currently live NPCs around the player.
|
|
UPROPERTY()
|
|
TArray<TObjectPtr<ANPC>> Active;
|
|
|
|
FTimerHandle UpdateTimerHandle;
|
|
EDayPhase CachedPhase = EDayPhase::Day;
|
|
}; |