Setup player preview for equipment panel
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
// © 2025 Naked People Team. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/WorldSubsystem.h"
|
||||
#include "TimeOfDaySubsystem.generated.h"
|
||||
|
||||
class UGlobalSaveGameData;
|
||||
|
||||
/**
|
||||
* Day vs. night phase (GDD §10.1). Drives NPC density and embarrassment rate.
|
||||
* Day is 08:00–20:00; everything else is night.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EDayPhase : uint8
|
||||
{
|
||||
Day,
|
||||
Night
|
||||
};
|
||||
|
||||
/**
|
||||
* Why the 90-day campaign ended (GDD §3.3). Evicted is the rent-failure loss;
|
||||
* CampaignComplete fires when the player survives to day 90. The ending screen /
|
||||
* win-threshold logic (§21 open) lives in BP and reacts to OnCampaignEnded.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class ECampaignEndReason : uint8
|
||||
{
|
||||
Evicted,
|
||||
CampaignComplete
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHourChangedSignature, int32, Hour);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDayChangedSignature, int32, NewDay);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPhaseChangedSignature, EDayPhase, NewPhase);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCampaignEndedSignature, ECampaignEndReason, Reason);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPushTimeToSkySignature, const FTimecode&, Timecode);
|
||||
|
||||
/**
|
||||
* The single authoritative clock (GDD §2.4, §10.1). Owns time-of-day and the
|
||||
* calendar in C++ and pushes the current time to the UltraDynamicSky actor each
|
||||
* in-game minute via ANakedDesireGameMode::SetCurrentTime — inverting the old
|
||||
* BP-drives-time flow. Persists to UGlobalSaveGameData (MinuteOfDay / DaysPassed).
|
||||
*
|
||||
* The calendar rolls at 04:00 (DAY_ROLL_HOUR); the day phase flips at 08:00 / 20:00.
|
||||
* Weekly rent is charged every WEEK_LENGTH_DAYS-th roll; follower income deposits
|
||||
* each roll. Sleep / time-skips funnel through AdvanceClock so boundaries always fire.
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKEDDESIRE_API UTimeOfDaySubsystem : public UTickableWorldSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void OnWorldBeginPlay(UWorld& InWorld) override;
|
||||
|
||||
// FTickableGameObject
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
virtual TStatId GetStatId() const override;
|
||||
virtual bool IsTickable() const override { return bBegunPlay && !IsTemplate(); }
|
||||
|
||||
// --- Queries ---
|
||||
UFUNCTION(BlueprintPure, Category = "Time")
|
||||
int32 GetDay() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time")
|
||||
float GetMinuteOfDay() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time")
|
||||
int32 GetHour() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time")
|
||||
int32 GetMinute() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time")
|
||||
EDayPhase GetPhase() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time")
|
||||
bool IsDay() const { return GetPhase() == EDayPhase::Day; }
|
||||
|
||||
// --- Time control ---
|
||||
// Advance the clock by a number of in-game minutes, firing every boundary crossed.
|
||||
UFUNCTION(BlueprintCallable, Category = "Time")
|
||||
void SkipTime(float Minutes);
|
||||
|
||||
// Fast-forward to the next 08:00 (used by the §4.4 holding-cell cutscene).
|
||||
UFUNCTION(BlueprintCallable, Category = "Time")
|
||||
void SkipToNextMorning();
|
||||
|
||||
// §2.4 sleep: fast-forward 8 hours, restore energy, autosave. (The apartment bed
|
||||
// also routes outside-clothing loss through USessionLossResolver — see §4.4.)
|
||||
UFUNCTION(BlueprintCallable, Category = "Time")
|
||||
void Sleep();
|
||||
|
||||
// --- Pause (reason-keyed; the clock runs only while the reason set is empty).
|
||||
// Note §11.17: the holding-cell cutscene deliberately does NOT pause the clock. ---
|
||||
UFUNCTION(BlueprintCallable, Category = "Time")
|
||||
void PushPause(FName Reason);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Time")
|
||||
void PopPause(FName Reason);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time")
|
||||
bool IsPaused() const { return PauseReasons.Num() > 0; }
|
||||
|
||||
// --- Delegates ---
|
||||
UPROPERTY(BlueprintAssignable, Category = "Time")
|
||||
FOnHourChangedSignature OnHourChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Time")
|
||||
FOnDayChangedSignature OnDayChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Time")
|
||||
FOnPhaseChangedSignature OnPhaseChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Time")
|
||||
FOnCampaignEndedSignature OnCampaignEnded;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Time")
|
||||
FOnPushTimeToSkySignature OnPushTimeToSky;
|
||||
|
||||
private:
|
||||
void AdvanceClock(double DeltaMinutes);
|
||||
void HandleHourBoundary(int32 HourOfDay); // 0–23
|
||||
void SetPhase(EDayPhase NewPhase);
|
||||
void AdvanceCalendarDay();
|
||||
void ChargeWeeklyRent();
|
||||
void DepositDailyFollowerIncome();
|
||||
void PushTimeToSky();
|
||||
|
||||
static EDayPhase ComputePhase(float InMinuteOfDay);
|
||||
|
||||
UGlobalSaveGameData* GetSave() const;
|
||||
void RestorePlayerEnergy() const;
|
||||
void Autosave() const;
|
||||
|
||||
// Last whole in-game minute pushed to the sky, to throttle the push to ~1/min.
|
||||
int32 LastPushedMinute = -1;
|
||||
EDayPhase CurrentPhase = EDayPhase::Day;
|
||||
TSet<FName> PauseReasons;
|
||||
bool bBegunPlay = false;
|
||||
};
|
||||
Reference in New Issue
Block a user