Compare commits

..

3 Commits

Author SHA1 Message Date
0526f25058 更新新手引导系统 2025-11-26 16:58:17 +08:00
a83eeacbc5 修复bug 2025-11-25 14:21:55 +08:00
1a5c391707 修复新手引导bug 2025-11-25 13:34:51 +08:00
49 changed files with 109 additions and 30 deletions

View File

@ -84,8 +84,8 @@ TSet<int32> UContainerInfo::GetOverlapOtherItem(FContainerItem Item)
if (Item.IsSlotUsing(FIntPoint(x, y)))
{
if (ContainerShape->IsSlotActive(Item.ContainerStartPos.X + x, Item.ContainerStartPos.Y + y) &&
SlotItems[FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y)] != -1
if (ContainerShape->IsSlotActive(Item.ContainerStartPos.X + x, Item.ContainerStartPos.Y + y) && SlotItems.Contains(FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y))
///SlotItems[FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y)] != -1
)
{
OverlapItems.Add(SlotItems[FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y)] );

View File

@ -5,12 +5,18 @@
#include "ProjectFish/Gameplay/Subsystem/GameInfoManager.h"
void UPlayerInfoSaveGame::BeginDestroy()
{
Super::BeginDestroy();
}
void UPlayerInfoSaveGame::SetShipContainerItems(TArray<FContainerItemSaveData> NewItems)
{
ShipContainerItems = NewItems;
if (GetWorld())
if (GetOuter())
{
GetWorld()->GetGameInstance()->GetSubsystem<UGameInfoManager>()->SaveGameInfo();
GetOuter()->GetWorld()->GetGameInstance()->GetSubsystem<UGameInfoManager>()->SaveGameInfo();
OnShipContainerUpdate.Broadcast();
}
}

View File

@ -18,6 +18,8 @@ class PROJECTFISH_API UPlayerInfoSaveGame : public USaveGame
{
GENERATED_BODY()
public:
virtual void BeginDestroy() override;
UPROPERTY(SaveGame, BlueprintReadWrite, meta = (ToolTip = "开启教程模式"))
bool TutorialMode = true;
@ -57,10 +59,11 @@ public:
UPROPERTY(SaveGame, BlueprintReadWrite, meta = (ToolTip = "被击败的鱼"))
TArray<int32> Fish_defeated_IDS;
protected:
public:
UPROPERTY(BlueprintAssignable, Category = "PlayerInfoSaveGame")
FOnShipContainerUpdate OnShipContainerUpdate;
protected:
UFUNCTION(BlueprintCallable, Category= "PlayerInfoSaveGame")
void SetShipContainerItems(TArray<FContainerItemSaveData> NewItems);
};

View File

@ -514,5 +514,8 @@ public:
//引导task
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tutorial Asset")
TSubclassOf<class UTutorialTask_Base> TutorialTaskClass;
UPROPERTY()
UTutorialTask_Base* TutorialTaskObject;
};

View File

@ -16,7 +16,7 @@ class PROJECTFISH_API UFishGameInstance : public UGameInstance
public:
/** GameInstace */
virtual void OnStart() override;
UFUNCTION(BlueprintImplementableEvent)
void InitTutorialSteps();
};

View File

@ -24,9 +24,10 @@ void UGameInfoManager::NewSaveGame()
void UGameInfoManager::SaveGameInfo()
{
if (!IsValid(PlayerInfo.Get()))
if (!IsValid(PlayerInfo))
{
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
}
// 保存任务数据
if (UQuestManager* QuestManager = GetGameInstance()->GetSubsystem<UQuestManager>())
@ -34,7 +35,7 @@ void UGameInfoManager::SaveGameInfo()
PlayerInfo->QuestSaveData = QuestManager->GetQuestSaveData();
}
if (UGameplayStatics::SaveGameToSlot(PlayerInfo.Get(), SaveGameSlotName, 0))
if (UGameplayStatics::SaveGameToSlot(PlayerInfo, SaveGameSlotName, 0))
{
UE_LOG(LogTemp, Warning, TEXT("存档保存成功"));
}
@ -49,7 +50,7 @@ bool UGameInfoManager::LoadGameInfo()
if (UGameplayStatics::DoesSaveGameExist(SaveGameSlotName, 0))
{
PlayerInfo = Cast<UPlayerInfoSaveGame>(UGameplayStatics::LoadGameFromSlot(SaveGameSlotName, 0));
PlayerInfo->Rename(nullptr, this);
// 加载任务数据
if (UQuestManager* QuestManager = GetGameInstance()->GetSubsystem<UQuestManager>())
{
@ -74,7 +75,8 @@ bool UGameInfoManager::LoadGameInfo()
void UGameInfoManager::CreateGameInfo(UContainerInfo* ShipContainer, UContainerInfo* PlayerContainer)
{
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
if (!IsValid(PlayerInfo))
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
PlayerInfo->ShipContainerItems = ShipContainer->GetSaveData();
PlayerInfo->ShipContainerShapeID = ShipContainer->ContainerShape->GetPrimaryAssetId();
@ -93,7 +95,7 @@ void UGameInfoManager::CreateGameInfoAndSave(UShapeAsset* ShipContainerShape, US
PlayerContainer->InitContainerByShape(PlayerContainerShape);
//创建要保存的额存档信息
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
PlayerInfo->ShipContainerItems = ShipContainer->GetSaveData();
PlayerInfo->ShipContainerShapeID = ShipContainer->ContainerShape->GetPrimaryAssetId();
@ -119,7 +121,7 @@ void UGameInfoManager::SetTutorialMode(bool bTutorialMode)
{
if (!IsValid(PlayerInfo))
{
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
}
PlayerInfo->TutorialMode = bTutorialMode;
}
@ -137,7 +139,7 @@ void UGameInfoManager::AddDefeatedFish(int32 FishID)
{
if (!IsValid(PlayerInfo))
{
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
}
PlayerInfo->Fish_defeated_IDS.Add(FishID);
SaveGameInfo();

View File

@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
#include "DialogueAsset.h"
#include "ProjectFish/Data/PlayerInfoSaveGame.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "GameInfoManager.generated.h"
@ -41,9 +42,11 @@ public:
UFUNCTION(BlueprintCallable)
void AddDefeatedFish(int32 FishID);
TObjectPtr<class UPlayerInfoSaveGame> GetPlayerInfo() {return PlayerInfo;}
protected:
UPROPERTY(BlueprintReadOnly)
TObjectPtr<class UPlayerInfoSaveGame> PlayerInfo;
UPROPERTY(BlueprintReadWrite)
class UPlayerInfoSaveGame* PlayerInfo;
static FString SaveGameSlotName;
};

View File

@ -32,6 +32,7 @@ void UTutorialManagerSubsystem::ApplyCurrentTutorialStep()
{
if (TutorialSteps.Num() > CurrentTutorialStep )
{
UE_LOG(LogTemp, Warning, TEXT("执行 CurrentTutorialStep = %d || name = %s "), CurrentTutorialStep, *GetCurrentTutorialStep().StepName.ToString() );
bTutorialing = true;
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
if (IsValid(CurrentStep.Dialogue))
@ -52,7 +53,7 @@ void UTutorialManagerSubsystem::ApplyCurrentTutorialStep()
}
if (IsValid(CurrentStep.TutorialTaskClass))
{
CreateTask();
}
}
else
@ -66,12 +67,18 @@ void UTutorialManagerSubsystem::CompleteTutorialStep()
{
if (bTutorialing)
{
if (TutorialTask)
if (TutorialTaskObject)
{
TutorialTask->ConditionalBeginDestroy();
TutorialTask = nullptr;
TutorialTaskObject->BeforTutorialComplete();
TutorialTaskObject->ConditionalBeginDestroy();
TutorialTaskObject = nullptr;
}
UE_LOG(LogTemp, Warning, TEXT("教程进行下一步 currentstep = %d"), CurrentTutorialStep);
if (TutorialWidget)
{
TutorialWidget->RemoveFromViewport();
TutorialWidget = nullptr;
}
UE_LOG(LogTemp, Warning, TEXT(" 教程进行下一步"));
OnStepComplete.Broadcast(CurrentTutorialStep);
CurrentTutorialStep++;
ApplyCurrentTutorialStep();
@ -138,7 +145,7 @@ void UTutorialManagerSubsystem::AccepAndFollowQuest()
void UTutorialManagerSubsystem::ShowTutorialUI()
{
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
UUserWidget* TutorialWidget = CreateWidget<UUserWidget>(GetWorld(), CurrentStep.TutorialUI);
TutorialWidget = CreateWidget<UUserWidget>(GetWorld(), CurrentStep.TutorialUI);
TutorialWidget->AddToViewport(99);
}
@ -161,6 +168,7 @@ void UTutorialManagerSubsystem::ControlUI()
void UTutorialManagerSubsystem::CreateTask()
{
TutorialTask = NewObject<UTutorialTask_Base>(this);
TutorialTask->Execute(GetWorld()->GetAuthGameMode());
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
TutorialTaskObject = NewObject<UTutorialTask_Base>(this, CurrentStep.TutorialTaskClass);
TutorialTaskObject->Execute(GetWorld()->GetAuthGameMode());
}

View File

@ -12,7 +12,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnStepComplete, int32, CompleteInde
/**
*
*/
UCLASS()
UCLASS(BlueprintType)
class PROJECTFISH_API UTutorialManagerSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
@ -48,10 +48,11 @@ protected:
void ControlUI();
//创建task
void CreateTask();
private:
protected:
FDelegateHandle LevelLoadedDelegateHandle;
UPROPERTY(BlueprintAssignable)
FOnStepComplete OnStepComplete;
UPROPERTY(BlueprintReadOnly)
bool bTutorialing;
TArray<FTutorialStep> TutorialSteps;
@ -59,7 +60,10 @@ private:
FString DialogueUIPath;
UPROPERTY()
class UDialogueWidget_Base* DialogueWidget;
UPROPERTY()
class UTutorialTask_Base* TutorialTask;
UUserWidget* TutorialWidget;
UPROPERTY()
class UTutorialTask_Base* TutorialTaskObject;
};

View File

@ -24,4 +24,5 @@ public:
UFUNCTION(BlueprintNativeEvent, Category= "TutorialTask")
void BeforTutorialComplete();
virtual void BeforTutorialComplete_Implementation();
};

View File

@ -3,13 +3,32 @@
#include "TutorialTask_CheckShipContainer.h"
#include "GameFramework/GameModeBase.h"
#include "ProjectFish/Gameplay/Subsystem/GameInfoManager.h"
#include "ProjectFish/Gameplay/Subsystem/TutorialManagerSubsystem.h"
void UTutorialTask_CheckShipContainer::Execute_Implementation(class AGameModeBase* GameMode)
{
Super::Execute_Implementation(GameMode);
if (GameMode)
{
GameMode->GetGameInstance()->GetSubsystem<UGameInfoManager>()->GetPlayerInfo()
->OnShipContainerUpdate.AddDynamic(this, &UTutorialTask_CheckShipContainer::OnShipContainerUpdate);
}
}
void UTutorialTask_CheckShipContainer::BeforTutorialComplete_Implementation()
{
Super::BeforTutorialComplete_Implementation();
}
void UTutorialTask_CheckShipContainer::OnShipContainerUpdate()
{
//只有3个物品时才完成当前的引导步骤
int CurrentItemCount = GetOuter()->GetWorld()->GetGameInstance()->GetSubsystem<UGameInfoManager>()->GetPlayerInfo()->ShipContainerItems.Num();
if (CurrentItemCount == ReqItemsCount)
{
Cast<UTutorialManagerSubsystem>(GetOuter())->CompleteTutorialStep();
}
}

View File

@ -13,7 +13,14 @@ UCLASS()
class PROJECTFISH_API UTutorialTask_CheckShipContainer : public UTutorialTask_Base
{
GENERATED_BODY()
virtual void Execute_Implementation(class AGameModeBase* GameMode) override;
virtual void BeforTutorialComplete_Implementation() override;
UFUNCTION()
void OnShipContainerUpdate();
protected:
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "TutorialTask_CheckShipContainer")
int32 ReqItemsCount;
};

View File

@ -8,6 +8,10 @@
void UTutorialTask_GamePause::Execute_Implementation(class AGameModeBase* GameMode)
{
Super::Execute_Implementation(GameMode);
// LevelLoadedDelegateHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(
// this,
// &UTutorialTask_GamePause::OnLevelLoaded
// );
UGameplayStatics::SetGamePaused(this, true);
}
@ -16,3 +20,18 @@ void UTutorialTask_GamePause::BeforTutorialComplete_Implementation()
Super::BeforTutorialComplete_Implementation();
UGameplayStatics::SetGamePaused(this, false);
}
void UTutorialTask_GamePause::OnLevelLoaded(UWorld* World)
{
// FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(LevelLoadedDelegateHandle);
// FTimerHandle LambdaTimerHandle;
// GetWorld()->GetTimerManager().SetTimer(
// LambdaTimerHandle,
// [this]()
// {
// UGameplayStatics::SetGamePaused(this, true);
// },
// 1.5f,
// false
// );
}

View File

@ -18,4 +18,8 @@ public:
virtual void Execute_Implementation(class AGameModeBase* GameMode) override;
virtual void BeforTutorialComplete_Implementation() override;
void OnLevelLoaded(UWorld* World);
private:
FDelegateHandle LevelLoadedDelegateHandle;
};

View File

@ -23,7 +23,7 @@ void USkillManager::Tick(float DeltaTime)
bool USkillManager::IsTickable() const
{
return !bGameEnd && IsValid(GameMode) && GameMode->GetBattleIsBegin();
return !bGameEnd && IsValid(GameMode) && GameMode->GetBattleIsBegin() && !GameMode->IsPaused();
}
TStatId USkillManager::GetStatId() const