87 lines
2.8 KiB
C++
87 lines
2.8 KiB
C++
// © 2025 Naked People Team. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Subsystems/WorldSubsystem.h"
|
|
#include "SessionManagerSubsystem.generated.h"
|
|
|
|
class UStatsManager;
|
|
class ULocationData;
|
|
|
|
/**
|
|
* Why a session ended (GDD §4.4). SafeReturn is a non-loss end (player walked
|
|
* home); the other three are the session-loss conditions from §3.3. The actual
|
|
* "what gets lost" handling lives in USessionLossResolver (DEV-100), which also
|
|
* applies police-chase precedence via bPoliceChaseActive.
|
|
*/
|
|
UENUM(BlueprintType)
|
|
enum class ESessionLossCause : uint8
|
|
{
|
|
SafeReturn,
|
|
EmbarrassmentMax,
|
|
EnergyZero,
|
|
PoliceCapture
|
|
};
|
|
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSessionStartSignature);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSessionEndSignature, ESessionLossCause, Cause);
|
|
|
|
/**
|
|
* Owns the "going outside" session state (GDD §4). A session starts when the
|
|
* player leaves the apartment and ends when they return safely or hit a loss
|
|
* condition (embarrassment max / energy zero / police capture). The apartment
|
|
* ALocationTrigger drives start / end; embarrassment-max and energy-zero are
|
|
* detected by subscribing to UStatsManager. This replaces the EndGameEmbarrassed
|
|
* Blueprint event on ANakedDesireGameMode.
|
|
*
|
|
* The apartment threshold is detected via ULocationSubsystem: a session starts when the player leaves
|
|
* a location tagged Location.Apartment and ends (SafeReturn) when they re-enter one. There is no
|
|
* per-trigger apartment flag — the apartment is just a tagged location.
|
|
*/
|
|
UCLASS()
|
|
class NAKEDDESIRE_API USessionManagerSubsystem : public UWorldSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
virtual void OnWorldBeginPlay(UWorld& InWorld) override;
|
|
|
|
UFUNCTION(BlueprintPure, Category = "Session")
|
|
bool IsSessionActive() const { return bSessionActive; }
|
|
|
|
// Set by the police AI pipeline (Phase 6). Read by USessionLossResolver for
|
|
// the §4.4 loss precedence rule: a loss fired mid-chase resolves as capture.
|
|
UFUNCTION(BlueprintCallable, Category = "Session")
|
|
void SetPoliceChaseActive(bool bActive) { bPoliceChaseActive = bActive; }
|
|
|
|
UFUNCTION(BlueprintPure, Category = "Session")
|
|
bool IsPoliceChaseActive() const { return bPoliceChaseActive; }
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Session")
|
|
FOnSessionStartSignature OnSessionStart;
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Session")
|
|
FOnSessionEndSignature OnSessionEnd;
|
|
|
|
private:
|
|
void StartSession();
|
|
void EndSession(ESessionLossCause Cause);
|
|
|
|
void BindToPlayerStats();
|
|
|
|
UFUNCTION()
|
|
void HandleLocationEntered(ULocationData* Location);
|
|
|
|
UFUNCTION()
|
|
void HandleLocationExited(ULocationData* Location);
|
|
|
|
UFUNCTION()
|
|
void HandleEmbarrassmentUpdate(float CurrentValue, float MaxValue);
|
|
|
|
UFUNCTION()
|
|
void HandleEnergyUpdate(float CurrentValue, float MaxValue);
|
|
|
|
bool bSessionActive = false;
|
|
bool bPoliceChaseActive = false;
|
|
}; |