From defc5decf99f1e49584e11c0e9c986d773c0b79a Mon Sep 17 00:00:00 2001 From: koritsa Date: Fri, 22 May 2026 16:23:59 +0300 Subject: [PATCH] Added save subsystem --- .../Clothing/ClothingItemInstance.cpp | 3 -- Source/NakedDesire/Global/Constants.h | 2 +- .../Player/NakedDesireCharacter.cpp | 9 ---- .../SaveGame/GlobalSaveGameData.cpp | 54 ++++++++----------- .../NakedDesire/SaveGame/GlobalSaveGameData.h | 26 ++++++--- Source/NakedDesire/SaveGame/ItemSaveRecord.h | 24 +++++++++ Source/NakedDesire/SaveGame/SaveSubsystem.cpp | 37 +++++++++++++ Source/NakedDesire/SaveGame/SaveSubsystem.h | 35 ++++++++++++ 8 files changed, 137 insertions(+), 53 deletions(-) create mode 100644 Source/NakedDesire/SaveGame/ItemSaveRecord.h create mode 100644 Source/NakedDesire/SaveGame/SaveSubsystem.cpp create mode 100644 Source/NakedDesire/SaveGame/SaveSubsystem.h diff --git a/Source/NakedDesire/Clothing/ClothingItemInstance.cpp b/Source/NakedDesire/Clothing/ClothingItemInstance.cpp index e26fc6f7..1317952f 100644 --- a/Source/NakedDesire/Clothing/ClothingItemInstance.cpp +++ b/Source/NakedDesire/Clothing/ClothingItemInstance.cpp @@ -1,4 +1 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - #include "ClothingItemInstance.h" diff --git a/Source/NakedDesire/Global/Constants.h b/Source/NakedDesire/Global/Constants.h index 86c9ab4a..965ec1b5 100644 --- a/Source/NakedDesire/Global/Constants.h +++ b/Source/NakedDesire/Global/Constants.h @@ -2,7 +2,7 @@ #pragma once -#define SLOT_NAME "Slot2" +inline const FString DefaultSaveSlotName = TEXT("Slot1"); #define SLOT_PLAYER 0 #define IS_DEMO false #define STARTING_MONEY 1000 diff --git a/Source/NakedDesire/Player/NakedDesireCharacter.cpp b/Source/NakedDesire/Player/NakedDesireCharacter.cpp index 6e46f9d0..d25f0f27 100644 --- a/Source/NakedDesire/Player/NakedDesireCharacter.cpp +++ b/Source/NakedDesire/Player/NakedDesireCharacter.cpp @@ -152,21 +152,12 @@ void ANakedDesireCharacter::BeginPlay() StimuliSourceComponent->RegisterForSense(TSubclassOf()); StimuliSourceComponent->RegisterWithPerceptionSystem(); - // UGlobalSaveGameData* SaveGameData = UGlobalSaveGameData::LoadOrCreateSaveGame(DefaultPlayerClothing, DefaultWardrobeClothing); - - // if (SaveGameData) - // { - // Money = FMath::RoundToInt(SaveGameData->Money); - // } - SetupClothingSlots(); ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &ANakedDesireCharacter::OnClothingEquip); ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &ANakedDesireCharacter::OnClothingUnequip); UNakedDesireUserSettings::GetNakedDesireUserSettings()->OnSettingsChanged.AddUniqueDynamic(this, &ANakedDesireCharacter::OnSettingsChanged); - - // ClothingManager->HydrateClothing(SaveGameData); } UAISense_Sight::EVisibilityResult ANakedDesireCharacter::CanBeSeenFrom(const FCanBeSeenFromContext& Context, diff --git a/Source/NakedDesire/SaveGame/GlobalSaveGameData.cpp b/Source/NakedDesire/SaveGame/GlobalSaveGameData.cpp index df77a2a0..5d6dfd74 100644 --- a/Source/NakedDesire/SaveGame/GlobalSaveGameData.cpp +++ b/Source/NakedDesire/SaveGame/GlobalSaveGameData.cpp @@ -7,59 +7,47 @@ UGlobalSaveGameData* UGlobalSaveGameData::CreateNewSaveGame() { - UGlobalSaveGameData* NewSave = Cast( - UGameplayStatics::CreateSaveGameObject(UGlobalSaveGameData::StaticClass()) - ); + UGlobalSaveGameData* NewSave = Cast(UGameplayStatics::CreateSaveGameObject(StaticClass())); if (!NewSave) { return nullptr; } - // NewSave->Money = InMoney; - - // for (const UClothingItemData* Item : CurrentWardrobeClothing) - // { - // NewSave->WardrobeClothing.Add(Item->ToSaveData()); - // } - // - // for (const UClothingItemData* Item : CurrentPlayerClothing) - // { - // NewSave->PlayerClothing.Add(Item->ToSaveData()); - // } - return NewSave; } -UGlobalSaveGameData* UGlobalSaveGameData::LoadOrCreateSaveGame() +UGlobalSaveGameData* UGlobalSaveGameData::LoadOrCreateSaveGame(const FString& SlotName) { - if (UGameplayStatics::DoesSaveGameExist(SLOT_NAME, SLOT_PLAYER)) - { - return Cast( - UGameplayStatics::LoadGameFromSlot(SLOT_NAME, SLOT_PLAYER) - ); - } + if (UGlobalSaveGameData* ExistingSave = LoadGame(SlotName)) + return ExistingSave; - UGlobalSaveGameData* NewSave = nullptr; - // if (DefaultWardrobeClothing && DefaultPlayerClothing) - // { - // NewSave = CreateNewSaveGame(DefaultWardrobeClothing->ClothingItems, DefaultPlayerClothing->ClothingItems, STARTING_MONEY); - // } + UGlobalSaveGameData* NewSave = CreateNewSaveGame(); if (NewSave) { - UGameplayStatics::SaveGameToSlot(NewSave, SLOT_NAME, SLOT_PLAYER); + UGameplayStatics::SaveGameToSlot(NewSave, SlotName, SLOT_PLAYER); } return NewSave; } -bool UGlobalSaveGameData::SaveGame() +UGlobalSaveGameData* UGlobalSaveGameData::LoadGame(const FString& SlotName) { - // if (UGlobalSaveGameData* Save = CreateNewSaveGame(CurrentWardrobeClothing, CurrentPlayerClothing, (float)InMoney)) - // { - // return UGameplayStatics::SaveGameToSlot(Save, SLOT_NAME, SLOT_PLAYER); - // } + if (UGameplayStatics::DoesSaveGameExist(SlotName, SLOT_PLAYER)) + { + return Cast(UGameplayStatics::LoadGameFromSlot(SlotName, SLOT_PLAYER)); + } + + return nullptr; +} + +bool UGlobalSaveGameData::SaveGame(const FString& SlotName) +{ + if (UGlobalSaveGameData* Save = CreateNewSaveGame()) + { + return UGameplayStatics::SaveGameToSlot(Save, SlotName, SLOT_PLAYER); + } return false; } diff --git a/Source/NakedDesire/SaveGame/GlobalSaveGameData.h b/Source/NakedDesire/SaveGame/GlobalSaveGameData.h index 1ffa2603..2348b6dc 100644 --- a/Source/NakedDesire/SaveGame/GlobalSaveGameData.h +++ b/Source/NakedDesire/SaveGame/GlobalSaveGameData.h @@ -4,8 +4,10 @@ #include "CoreMinimal.h" #include "GameFramework/SaveGame.h" +#include "NakedDesire/Global/Constants.h" #include "GlobalSaveGameData.generated.h" +struct FItemSaveRecord; class UClothingList; UCLASS() @@ -14,17 +16,27 @@ class NAKEDDESIRE_API UGlobalSaveGameData : public USaveGame GENERATED_BODY() public: - UPROPERTY(BlueprintReadWrite, SaveGame) + static UGlobalSaveGameData* LoadOrCreateSaveGame(const FString& SlotName = DefaultSaveSlotName); + static UGlobalSaveGameData* LoadGame(const FString& SlotName = DefaultSaveSlotName); + static bool SaveGame(const FString& SlotName = DefaultSaveSlotName); + + UPROPERTY(SaveGame) bool HaveSeenTutorial = false; - UPROPERTY(BlueprintReadWrite, SaveGame) + UPROPERTY(SaveGame) float Money = 0; - - UFUNCTION(BlueprintCallable) - static UGlobalSaveGameData* LoadOrCreateSaveGame(); - UFUNCTION(BlueprintCallable) - static bool SaveGame(); + UPROPERTY(SaveGame) + TArray WardrobeItems; + + UPROPERTY(SaveGame) + TArray EquippedItems; + + UPROPERTY(SaceGame) + int32 DaysPassed = 0; + + UPROPERTY(SaveGame) + float HourOfDay = 0.0f; private: static UGlobalSaveGameData* CreateNewSaveGame(); diff --git a/Source/NakedDesire/SaveGame/ItemSaveRecord.h b/Source/NakedDesire/SaveGame/ItemSaveRecord.h new file mode 100644 index 00000000..e0bfcfd3 --- /dev/null +++ b/Source/NakedDesire/SaveGame/ItemSaveRecord.h @@ -0,0 +1,24 @@ +#pragma once + +#include "CoreMinimal.h" +#include "ItemSaveRecord.generated.h" + +class UClothingItem; + +USTRUCT() +struct NAKEDDESIRE_API FItemSaveRecord +{ + GENERATED_BODY() + + UPROPERTY(SaveGame) + FGuid InstanceId; + + UPROPERTY(SaveGame) + TSoftObjectPtr Definition; + + UPROPERTY(SaveGame) + float Condition = 1.0f; + + UPROPERTY(SaveGame) + FGuid ParentId; +}; diff --git a/Source/NakedDesire/SaveGame/SaveSubsystem.cpp b/Source/NakedDesire/SaveGame/SaveSubsystem.cpp new file mode 100644 index 00000000..8a368eff --- /dev/null +++ b/Source/NakedDesire/SaveGame/SaveSubsystem.cpp @@ -0,0 +1,37 @@ +#include "SaveSubsystem.h" +#include "GlobalSaveGameData.h" +#include "ItemSaveRecord.h" + +void USaveSubsystem::LoadGame(const FString& SlotName) +{ + UGlobalSaveGameData* Save = UGlobalSaveGameData::LoadGame(SlotName); +} + +bool USaveSubsystem::SaveGame(const FString& SlotName) +{ + return UGlobalSaveGameData::SaveGame(SlotName); +} + +void USaveSubsystem::AddItem(const FItemSaveRecord& Record) +{ + Items.Add(Record); +} + +void USaveSubsystem::RemoveItem(const FGuid& InstanceId) +{ + FItemSaveRecord* ItemSaveRecord = Items.FindByPredicate([InstanceId](FItemSaveRecord ItemSaveRecord) + { + return ItemSaveRecord.InstanceId == InstanceId; + }); + if (ItemSaveRecord) + { + Items.Remove(*ItemSaveRecord); + } +} + +void USaveSubsystem::Initialize(FSubsystemCollectionBase& Collection) +{ + Super::Initialize(Collection); + + LoadGame(); +} diff --git a/Source/NakedDesire/SaveGame/SaveSubsystem.h b/Source/NakedDesire/SaveGame/SaveSubsystem.h new file mode 100644 index 00000000..d8cf254c --- /dev/null +++ b/Source/NakedDesire/SaveGame/SaveSubsystem.h @@ -0,0 +1,35 @@ +#pragma once + +#include "CoreMinimal.h" +#include "NakedDesire/Global/Constants.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "SaveSubsystem.generated.h" + +class UGlobalSaveGameData; +struct FItemSaveRecord; + +UCLASS() +class NAKEDDESIRE_API USaveSubsystem : public UGameInstanceSubsystem +{ + GENERATED_BODY() + +public: + void LoadGame(const FString& SlotName = DefaultSaveSlotName); + bool SaveGame(const FString& SlotName = DefaultSaveSlotName); + + const TArray& GetItems() const { return Items; } + void AddItem(const FItemSaveRecord& Record); + void RemoveItem(const FGuid& InstanceId); + + virtual void Initialize(FSubsystemCollectionBase& Collection) override; + +private: + UPROPERTY() + FString ActiveSlotName = DefaultSaveSlotName; + + UPROPERTY() + TArray Items; + + UPROPERTY() + TObjectPtr CurrentSave; +};