Added session system
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
// © 2025 Naked People Team. All Rights Reserved.
|
||||
|
||||
|
||||
#include "SessionLossResolver.h"
|
||||
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "NakedDesire/Clothing/ClothingItemInstance.h"
|
||||
#include "NakedDesire/Interactables/ItemPickup.h"
|
||||
#include "NakedDesire/SaveGame/GlobalSaveGameData.h"
|
||||
#include "NakedDesire/SaveGame/SaveSubsystem.h"
|
||||
|
||||
void USessionLossResolver::OnWorldBeginPlay(UWorld& InWorld)
|
||||
{
|
||||
Super::OnWorldBeginPlay(InWorld);
|
||||
|
||||
if (USessionManagerSubsystem* SessionManager = InWorld.GetSubsystem<USessionManagerSubsystem>())
|
||||
{
|
||||
SessionManager->OnSessionEnd.AddDynamic(this, &USessionLossResolver::ResolveLoss);
|
||||
}
|
||||
}
|
||||
|
||||
void USessionLossResolver::ResolveLoss(ESessionLossCause Cause)
|
||||
{
|
||||
// §4.4 precedence: if a chase is in progress, the loss always resolves as
|
||||
// police capture — the chase wins regardless of what actually fired.
|
||||
if (const USessionManagerSubsystem* SessionManager = GetWorld()->GetSubsystem<USessionManagerSubsystem>())
|
||||
{
|
||||
if (SessionManager->IsPoliceChaseActive())
|
||||
{
|
||||
Cause = ESessionLossCause::PoliceCapture;
|
||||
}
|
||||
}
|
||||
|
||||
// §4.4: equipped clothing is never forcibly removed — the resolver simply never
|
||||
// touches equipped items.
|
||||
// TODO(§6.4): when bags exist, a bag placed in the world is lost with its
|
||||
// contents — mark its world record for deletion here.
|
||||
|
||||
bool bWentToHoldingCell = false;
|
||||
|
||||
switch (Cause)
|
||||
{
|
||||
case ESessionLossCause::SafeReturn:
|
||||
// Normal session end; nothing is lost. Autosave below.
|
||||
break;
|
||||
|
||||
case ESessionLossCause::EmbarrassmentMax:
|
||||
// Fade to apartment with no extra cost — no time skip, money, or rep hit.
|
||||
break;
|
||||
|
||||
case ESessionLossCause::EnergyZero:
|
||||
// Forced sleep cycle: everything left outside the apartment is guaranteed lost.
|
||||
LoseAllWorldClothing();
|
||||
break;
|
||||
|
||||
case ESessionLossCause::PoliceCapture:
|
||||
{
|
||||
UGlobalSaveGameData* Save = GetSave();
|
||||
if (Save && Save->Money >= PoliceCaptureMoneyPenalty)
|
||||
{
|
||||
// Can pay: deduct the penalty and go home.
|
||||
Save->Money -= PoliceCaptureMoneyPenalty;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't pay: a night in the holding cell settles the debt; no money owed.
|
||||
bWentToHoldingCell = true;
|
||||
}
|
||||
ClearWanted();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Autosave();
|
||||
|
||||
OnSessionLossResolved.Broadcast(Cause, bWentToHoldingCell);
|
||||
}
|
||||
|
||||
void USessionLossResolver::LoseAllWorldClothing()
|
||||
{
|
||||
UGlobalSaveGameData* Save = GetSave();
|
||||
|
||||
// Loose clothing in the world is represented by AItemPickup actors. Dropping only
|
||||
// happens outside, and the apartment stores items in the wardrobe (not as pickups),
|
||||
// so every pickup currently counts as "outside the apartment".
|
||||
// TODO: once an apartment volume query exists, spare pickups that sit inside it.
|
||||
TArray<AActor*> Pickups;
|
||||
UGameplayStatics::GetAllActorsOfClass(this, AItemPickup::StaticClass(), Pickups);
|
||||
for (AActor* Actor : Pickups)
|
||||
{
|
||||
AItemPickup* Pickup = Cast<AItemPickup>(Actor);
|
||||
if (!Pickup)
|
||||
continue;
|
||||
|
||||
if (Save)
|
||||
{
|
||||
if (UClothingItemInstance* Item = Pickup->GetItem())
|
||||
{
|
||||
Save->RemoveWorldItem(Item);
|
||||
}
|
||||
}
|
||||
Pickup->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void USessionLossResolver::ClearWanted()
|
||||
{
|
||||
// TODO(§7.7 / Phase 6): clear the `wanted` tag once the Wanted attribute exists.
|
||||
}
|
||||
|
||||
void USessionLossResolver::Autosave() const
|
||||
{
|
||||
if (const UGameInstance* GameInstance = GetWorld()->GetGameInstance())
|
||||
{
|
||||
if (USaveSubsystem* SaveSubsystem = GameInstance->GetSubsystem<USaveSubsystem>())
|
||||
{
|
||||
SaveSubsystem->SaveGame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UGlobalSaveGameData* USessionLossResolver::GetSave() const
|
||||
{
|
||||
if (const UGameInstance* GameInstance = GetWorld()->GetGameInstance())
|
||||
{
|
||||
if (USaveSubsystem* SaveSubsystem = GameInstance->GetSubsystem<USaveSubsystem>())
|
||||
{
|
||||
return SaveSubsystem->GetCurrentSave();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
Reference in New Issue
Block a user