63 lines
2.5 KiB
C++
63 lines
2.5 KiB
C++
// © 2025 Naked People Team. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Subsystems/WorldSubsystem.h"
|
|
#include "SessionManagerSubsystem.h"
|
|
#include "SessionLossResolver.generated.h"
|
|
|
|
/**
|
|
* Broadcast once a loss has been resolved transactionally. The presentation layer
|
|
* (fade / cutscene / teleport) and the time skip live in Blueprint / the future
|
|
* time subsystem and react to this, switching on FinalCause:
|
|
* - EmbarrassmentMax → fade to apartment. No time skip.
|
|
* - EnergyZero → trudge-home cutscene, then advance one sleep cycle.
|
|
* - PoliceCapture (!cell) → fade to apartment.
|
|
* - PoliceCapture (cell) → holding-cell cutscene, then fast-forward to next morning.
|
|
* - SafeReturn → no special presentation.
|
|
* The C++ side has already applied money / item / wanted changes by the time this fires.
|
|
*/
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSessionLossResolvedSignature, ESessionLossCause, FinalCause, bool, bWentToHoldingCell);
|
|
|
|
/**
|
|
* The single, deterministic owner of "what gets lost" on session end (GDD §4.4).
|
|
* Subscribes to USessionManagerSubsystem::OnSessionEnd and routes every cause
|
|
* through ResolveLoss. Per the architecture rule, no loss-handling logic should
|
|
* live anywhere else.
|
|
*/
|
|
UCLASS()
|
|
class NAKEDDESIRE_API USessionLossResolver : public UWorldSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
virtual void OnWorldBeginPlay(UWorld& InWorld) override;
|
|
|
|
// Single entry point for all §4.4 outcomes. Bound to OnSessionEnd; also callable
|
|
// directly (e.g. from a debug command) to exercise a path.
|
|
UFUNCTION(BlueprintCallable, Category = "Session")
|
|
void ResolveLoss(ESessionLossCause Cause);
|
|
|
|
// Voluntary sleep at the apartment bed (§4.4 step 2). Not a session-loss cause — the
|
|
// session already ended on entering the apartment — but any clothing left outside is
|
|
// still guaranteed lost. Lives here so ALL "what gets lost" logic stays in one place.
|
|
UFUNCTION(BlueprintCallable, Category = "Session")
|
|
void ResolveSleepLoss();
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Session")
|
|
FOnSessionLossResolvedSignature OnSessionLossResolved;
|
|
|
|
private:
|
|
// EnergyZero / sleep: every clothing item left outside the apartment is guaranteed lost.
|
|
void LoseAllWorldClothing();
|
|
|
|
// §7.7: cleared on police capture. No-op until the Wanted attribute exists (Phase 6).
|
|
void ClearWanted();
|
|
|
|
void Autosave() const;
|
|
class UGlobalSaveGameData* GetSave() const;
|
|
|
|
// §21 tuning placeholder — the police-capture money penalty.
|
|
float PoliceCaptureMoneyPenalty = 200.0f;
|
|
}; |