Files
Naked-Desire/Source/NakedDesire/Global/SessionManagerSubsystem.h
T
2026-06-03 15:17:02 +03:00

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;
};