77 lines
2.9 KiB
C++
77 lines
2.9 KiB
C++
// © 2025 Naked People Team. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Subsystems/GameInstanceSubsystem.h"
|
|
#include "InventorySubsystem.generated.h"
|
|
|
|
class UItemInstance;
|
|
class UClothingManager;
|
|
class UGlobalSaveGameData;
|
|
class UPhoneItemInstance;
|
|
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWardrobeChangedSignature);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPhoneChangedSignature, UPhoneItemInstance*, Phone);
|
|
|
|
/**
|
|
* Runtime owner of the off-body item store (the apartment wardrobe, GDD §6.5 / §10.4).
|
|
*
|
|
* Holds live UItemInstance objects mirrored from UGlobalSaveGameData::WardrobeItems and is
|
|
* the single entry point for moving items between the wardrobe and the body. Equipped items
|
|
* stay owned by the per-character UClothingManager (it remains the body-state authority and
|
|
* keeps writing the EquippedItems bucket); this subsystem orchestrates the wardrobe<->equipped
|
|
* transfer so the two save buckets can never drift. Mutations broadcast OnWardrobeChanged so
|
|
* the wardrobe UI can refresh without polling.
|
|
*/
|
|
UCLASS()
|
|
class NAKEDDESIRE_API UInventorySubsystem : public UGameInstanceSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UPROPERTY(BlueprintAssignable)
|
|
FOnWardrobeChangedSignature OnWardrobeChanged;
|
|
|
|
// Fires when the phone slot changes; broadcasts the newly-equipped phone, or nullptr when emptied.
|
|
UPROPERTY(BlueprintAssignable)
|
|
FOnPhoneChangedSignature OnPhoneChanged;
|
|
|
|
/** Live wardrobe instances (off-body, mirrored from the save). */
|
|
const TArray<TObjectPtr<UItemInstance>>& GetWardrobeItems();
|
|
|
|
/** The phone occupying the dedicated phone slot (§6.5 / §9.9), or nullptr if none is equipped. */
|
|
UPhoneItemInstance* GetEquippedPhone();
|
|
|
|
/** Bring an item into the wardrobe (purchase, world-return). */
|
|
void AddToWardrobe(UItemInstance* Item);
|
|
|
|
/** Remove an item from the wardrobe without equipping it (discard). */
|
|
void RemoveFromWardrobe(UItemInstance* Item);
|
|
|
|
/** Move a stored item onto the body; any displaced garment returns to the wardrobe. */
|
|
void EquipFromWardrobe(UItemInstance* Item);
|
|
|
|
/** Take an equipped garment off the body and store it back in the wardrobe. */
|
|
void UnequipToWardrobe(UItemInstance* Item);
|
|
|
|
private:
|
|
void EnsureHydrated();
|
|
void StoreItem(UItemInstance* Item); // live list + save bucket, no broadcast
|
|
void UnstoreItem(UItemInstance* Item); // live list + save bucket, no broadcast
|
|
|
|
void EquipPhone(UPhoneItemInstance* Phone); // hot-swaps the previous phone back to the wardrobe
|
|
void UnequipPhone(UPhoneItemInstance* Phone); // stores the phone back in the wardrobe
|
|
|
|
UClothingManager* GetPlayerClothingManager() const;
|
|
UGlobalSaveGameData* GetSave() const;
|
|
|
|
UPROPERTY()
|
|
TArray<TObjectPtr<UItemInstance>> WardrobeItems;
|
|
|
|
UPROPERTY()
|
|
TObjectPtr<UPhoneItemInstance> EquippedPhone;
|
|
|
|
// The save the live list was built from; re-hydrate when this changes (e.g. load game).
|
|
TWeakObjectPtr<UGlobalSaveGameData> HydratedSave;
|
|
}; |