Compare commits
No commits in common. "f33feaf558a4e5c28b45ac558d08c0875eaaeedf" and "f3911b4d06adebc9137ca2a663092fbc9c7d85f2" have entirely different histories.
f33feaf558
...
f3911b4d06
Binary file not shown.
Binary file not shown.
@ -1,5 +0,0 @@
|
||||
|
||||
|
||||
[/Script/Dialogue.DialogueSettings]
|
||||
DialogueWidth=125.000000
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
[/Script/EngineSettings.GameMapsSettings]
|
||||
GameDefaultMap=/Game/TopDown/Maps/TopDownMap.TopDownMap
|
||||
EditorStartupMap=/Game/Maps/Home.Home
|
||||
EditorStartupMap=/Game/ART/Map/fishing.fishing
|
||||
GlobalDefaultGameMode="/Script/ProjectFish.ProjectFishGameMode"
|
||||
GameInstanceClass=/Game/Gameplay/BP_FishGameInstance.BP_FishGameInstance_C
|
||||
|
||||
[/Script/Engine.RendererSettings]
|
||||
r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,619 +0,0 @@
|
||||
# 新手引导系统设计(简化版)
|
||||
|
||||
## 一、核心思路
|
||||
|
||||
**一句话概括**:用一个 `TutorialManager` 管理引导流程,通过 Widget 的 `Tag` 控制显示/隐藏/高亮。
|
||||
|
||||
---
|
||||
|
||||
## 二、只需要3个东西
|
||||
|
||||
### 1. TutorialManager(一个管理类)
|
||||
|
||||
```cpp
|
||||
// TutorialManager.h
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "TutorialManager.generated.h"
|
||||
|
||||
// 简单的步骤配置
|
||||
USTRUCT(BlueprintType)
|
||||
struct FTutorialStep
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// 步骤ID
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 StepID = 0;
|
||||
|
||||
// 可见的Widget标签(其他都隐藏)
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<FName> VisibleWidgetTags;
|
||||
|
||||
// 高亮的Widget标签
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<FName> HighlightWidgetTags;
|
||||
|
||||
// 提示文本(可选)
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText HintText;
|
||||
|
||||
// 对话资产(可选)
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
class UDialogueAsset* DialogueAsset;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class PROJECTFISH_API UTutorialManager : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// 开始引导
|
||||
UFUNCTION(BlueprintCallable, Category = "Tutorial")
|
||||
void StartTutorial();
|
||||
|
||||
// 进入下一步
|
||||
UFUNCTION(BlueprintCallable, Category = "Tutorial")
|
||||
void NextStep();
|
||||
|
||||
// 完成引导
|
||||
UFUNCTION(BlueprintCallable, Category = "Tutorial")
|
||||
void FinishTutorial();
|
||||
|
||||
// 是否在引导中
|
||||
UFUNCTION(BlueprintPure, Category = "Tutorial")
|
||||
bool IsInTutorial() const { return bInTutorial; }
|
||||
|
||||
// 获取当前步骤
|
||||
UFUNCTION(BlueprintPure, Category = "Tutorial")
|
||||
int32 GetCurrentStep() const { return CurrentStepIndex; }
|
||||
|
||||
// 检查Widget是否应该显示
|
||||
UFUNCTION(BlueprintPure, Category = "Tutorial")
|
||||
bool ShouldShowWidget(FName WidgetTag) const;
|
||||
|
||||
// 检查Widget是否应该高亮
|
||||
UFUNCTION(BlueprintPure, Category = "Tutorial")
|
||||
bool ShouldHighlightWidget(FName WidgetTag) const;
|
||||
|
||||
// 隐藏遮罩层
|
||||
UFUNCTION(BlueprintCallable, Category = "Tutorial")
|
||||
void ShowMask(bool bShow);
|
||||
|
||||
protected:
|
||||
// 引导步骤配置(在编辑器中配置)
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Tutorial")
|
||||
TArray<FTutorialStep> TutorialSteps;
|
||||
|
||||
UPROPERTY()
|
||||
bool bInTutorial = false;
|
||||
|
||||
UPROPERTY()
|
||||
int32 CurrentStepIndex = -1;
|
||||
|
||||
private:
|
||||
void ApplyCurrentStep();
|
||||
void BroadcastStepChanged();
|
||||
};
|
||||
```
|
||||
|
||||
```cpp
|
||||
// TutorialManager.cpp
|
||||
#include "TutorialManager.h"
|
||||
|
||||
void UTutorialManager::StartTutorial()
|
||||
{
|
||||
bInTutorial = true;
|
||||
CurrentStepIndex = 0;
|
||||
ApplyCurrentStep();
|
||||
}
|
||||
|
||||
void UTutorialManager::NextStep()
|
||||
{
|
||||
if (!bInTutorial) return;
|
||||
|
||||
CurrentStepIndex++;
|
||||
if (CurrentStepIndex >= TutorialSteps.Num())
|
||||
{
|
||||
FinishTutorial();
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyCurrentStep();
|
||||
}
|
||||
|
||||
void UTutorialManager::FinishTutorial()
|
||||
{
|
||||
bInTutorial = false;
|
||||
CurrentStepIndex = -1;
|
||||
|
||||
// 保存到存档
|
||||
// GameInfoManager->SetTutorialCompleted(true);
|
||||
|
||||
ShowMask(false);
|
||||
}
|
||||
|
||||
bool UTutorialManager::ShouldShowWidget(FName WidgetTag) const
|
||||
{
|
||||
if (!bInTutorial) return true; // 正常模式全显示
|
||||
|
||||
if (!TutorialSteps.IsValidIndex(CurrentStepIndex))
|
||||
return true;
|
||||
|
||||
const FTutorialStep& Step = TutorialSteps[CurrentStepIndex];
|
||||
|
||||
// 如果没有配置,默认显示
|
||||
if (Step.VisibleWidgetTags.Num() == 0)
|
||||
return true;
|
||||
|
||||
// 白名单模式:只显示列表中的
|
||||
return Step.VisibleWidgetTags.Contains(WidgetTag);
|
||||
}
|
||||
|
||||
bool UTutorialManager::ShouldHighlightWidget(FName WidgetTag) const
|
||||
{
|
||||
if (!bInTutorial) return false;
|
||||
|
||||
if (!TutorialSteps.IsValidIndex(CurrentStepIndex))
|
||||
return false;
|
||||
|
||||
const FTutorialStep& Step = TutorialSteps[CurrentStepIndex];
|
||||
return Step.HighlightWidgetTags.Contains(WidgetTag);
|
||||
}
|
||||
|
||||
void UTutorialManager::ApplyCurrentStep()
|
||||
{
|
||||
BroadcastStepChanged();
|
||||
|
||||
if (!TutorialSteps.IsValidIndex(CurrentStepIndex))
|
||||
return;
|
||||
|
||||
const FTutorialStep& Step = TutorialSteps[CurrentStepIndex];
|
||||
|
||||
// 如果有对话,播放对话
|
||||
if (Step.DialogueAsset)
|
||||
{
|
||||
// 调用对话系统播放
|
||||
// DialogueSystem->PlayDialogue(Step.DialogueAsset);
|
||||
}
|
||||
|
||||
// 显示遮罩
|
||||
ShowMask(true);
|
||||
}
|
||||
|
||||
void UTutorialManager::BroadcastStepChanged()
|
||||
{
|
||||
// 通知所有UI刷新
|
||||
// 可以用事件委托或直接遍历所有Widget
|
||||
}
|
||||
|
||||
void UTutorialManager::ShowMask(bool bShow)
|
||||
{
|
||||
// 创建/显示/隐藏遮罩Widget
|
||||
// 遮罩Widget是一个全屏的半透明黑色背景
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Widget上设置Tag
|
||||
|
||||
在UMG编辑器中,给每个需要控制的Widget设置Tag:
|
||||
|
||||
```
|
||||
HomeUI:
|
||||
├─ Btn_Sail (Tag: "Btn_Sail")
|
||||
├─ Btn_Market (Tag: "Btn_Market")
|
||||
├─ Btn_Shop (Tag: "Btn_Shop")
|
||||
└─ Btn_Backpack (Tag: "Btn_Backpack")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Widget蓝图中检查是否显示
|
||||
|
||||
在每个Widget的蓝图中,添加简单逻辑:
|
||||
|
||||
```
|
||||
Event Construct:
|
||||
├─ Get TutorialManager
|
||||
├─ Bind to OnStepChanged Event
|
||||
└─ Call UpdateVisibility()
|
||||
|
||||
UpdateVisibility():
|
||||
├─ For each child widget:
|
||||
│ ├─ Get widget tag
|
||||
│ ├─ TutorialManager->ShouldShowWidget(tag)
|
||||
│ └─ Set Visibility (Visible / Collapsed)
|
||||
└─ Update Highlight state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、15步引导配置(简单表格)
|
||||
|
||||
在 `TutorialManager` 的 `TutorialSteps` 数组中配置:
|
||||
|
||||
| 步骤 | VisibleWidgetTags | HighlightWidgetTags | 说明 |
|
||||
|------|-------------------|---------------------|------|
|
||||
| 0 | [] | [] | 初始对话(DialogueAsset配置) |
|
||||
| 1 | [Btn_Sail] | [Btn_Sail] | 只显示出航按钮并高亮 |
|
||||
| 2 | [MapNode_0] | [MapNode_0] | 地图只显示一个节点 |
|
||||
| 3 | [] | [] | 进入Loading |
|
||||
| 4 | [MovementHint] | [] | 显示移动提示 |
|
||||
| 5 | [FishingHint] | [] | 显示钓鱼提示 |
|
||||
| 6 | [BattleUI] | [] | 战斗界面(隐藏背包/返航) |
|
||||
| ... | ... | ... | ... |
|
||||
|
||||
**配置方式**:在编辑器的 `Project Settings -> Tutorial Manager` 中直接填表格。
|
||||
|
||||
---
|
||||
|
||||
## 四、UI改造(最简单的方式)
|
||||
|
||||
### 方式1:蓝图中直接判断(推荐)
|
||||
|
||||
在每个Widget的蓝图中:
|
||||
|
||||
```blueprint
|
||||
Event Construct:
|
||||
├─ GetGameInstance
|
||||
├─ GetSubsystem(TutorialManager)
|
||||
├─ Bind Event: OnStepChanged -> UpdateVisibility
|
||||
└─ Call UpdateVisibility
|
||||
|
||||
Function UpdateVisibility:
|
||||
├─ If TutorialManager->IsInTutorial():
|
||||
│ ├─ Set Btn_Sail Visibility: ShouldShowWidget("Btn_Sail")
|
||||
│ ├─ Set Btn_Market Visibility: ShouldShowWidget("Btn_Market")
|
||||
│ └─ ...
|
||||
└─ Else: Show All
|
||||
```
|
||||
|
||||
### 方式2:C++中统一处理
|
||||
|
||||
创建一个简单的基类:
|
||||
|
||||
```cpp
|
||||
// TutorialWidget.h
|
||||
#pragma once
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "TutorialWidget.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UTutorialWidget : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void NativeConstruct() override;
|
||||
|
||||
protected:
|
||||
// 在子类中填写:Widget名 -> Tag的映射
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Tutorial")
|
||||
TMap<FName, UWidget*> WidgetTagMap;
|
||||
|
||||
UFUNCTION()
|
||||
void UpdateVisibility();
|
||||
|
||||
private:
|
||||
UPROPERTY()
|
||||
class UTutorialManager* TutorialManager;
|
||||
};
|
||||
```
|
||||
|
||||
```cpp
|
||||
// TutorialWidget.cpp
|
||||
#include "TutorialWidget.h"
|
||||
#include "TutorialManager.h"
|
||||
|
||||
void UTutorialWidget::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
TutorialManager = GetGameInstance()->GetSubsystem<UTutorialManager>();
|
||||
if (TutorialManager)
|
||||
{
|
||||
// 绑定步骤改变事件
|
||||
// TutorialManager->OnStepChanged.AddDynamic(this, &UTutorialWidget::UpdateVisibility);
|
||||
}
|
||||
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
void UTutorialWidget::UpdateVisibility()
|
||||
{
|
||||
if (!TutorialManager || !TutorialManager->IsInTutorial())
|
||||
{
|
||||
// 正常模式:全部显示
|
||||
for (auto& Pair : WidgetTagMap)
|
||||
{
|
||||
if (Pair.Value)
|
||||
Pair.Value->SetVisibility(ESlateVisibility::Visible);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 引导模式:根据Tag判断
|
||||
for (auto& Pair : WidgetTagMap)
|
||||
{
|
||||
if (!Pair.Value) continue;
|
||||
|
||||
bool bShouldShow = TutorialManager->ShouldShowWidget(Pair.Key);
|
||||
Pair.Value->SetVisibility(bShouldShow ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
|
||||
|
||||
// 高亮效果
|
||||
bool bShouldHighlight = TutorialManager->ShouldHighlightWidget(Pair.Key);
|
||||
if (bShouldHighlight)
|
||||
{
|
||||
// 添加高亮动画或材质效果
|
||||
// PlayAnimation(HighlightAnim);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
然后让 HomeUI 继承这个基类,在构造函数中填写映射:
|
||||
|
||||
```cpp
|
||||
// HomeUIWidget.cpp
|
||||
void UHomeUIWidget::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
// 填写映射
|
||||
WidgetTagMap.Add(TEXT("Btn_Sail"), Btn_Sail);
|
||||
WidgetTagMap.Add(TEXT("Btn_Market"), Btn_Market);
|
||||
WidgetTagMap.Add(TEXT("Btn_Shop"), Btn_Shop);
|
||||
WidgetTagMap.Add(TEXT("Btn_Backpack"), Btn_Backpack);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、特殊情况处理
|
||||
|
||||
### 1. 战斗特殊配置
|
||||
|
||||
不需要新的配置类,直接在战斗开始时检查:
|
||||
|
||||
```cpp
|
||||
// AProjectFishGameMode.cpp
|
||||
void AProjectFishGameMode::StartBattle()
|
||||
{
|
||||
UTutorialManager* Tutorial = GetGameInstance()->GetSubsystem<UTutorialManager>();
|
||||
|
||||
if (Tutorial && Tutorial->IsInTutorial())
|
||||
{
|
||||
int32 Step = Tutorial->GetCurrentStep();
|
||||
|
||||
// 第一场战斗(步骤6)
|
||||
if (Step == 6)
|
||||
{
|
||||
// 使用特定的鱼配置
|
||||
CurrentFish = LoadObject<UFishInfoConfigAsset>(..., TEXT("Tutorial_Fish_01"));
|
||||
|
||||
// 强制掉落
|
||||
bForceDropItem = true;
|
||||
ForcedDropItems.Add(TEXT("Item_Bass"));
|
||||
}
|
||||
// 第二场战斗(步骤9)
|
||||
else if (Step == 9)
|
||||
{
|
||||
CurrentFish = LoadObject<UFishInfoConfigAsset>(..., TEXT("Tutorial_Fish_02"));
|
||||
ForcedDropItems.Add(TEXT("Item_Bass"));
|
||||
ForcedDropItems.Add(TEXT("Item_MagicBook"));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 地图单节点
|
||||
|
||||
```cpp
|
||||
// FishingMapSubSystem.cpp
|
||||
void UFishingMapSubSystem::GenerateMap()
|
||||
{
|
||||
UTutorialManager* Tutorial = GetGameInstance()->GetSubsystem<UTutorialManager>();
|
||||
|
||||
if (Tutorial && Tutorial->IsInTutorial() && Tutorial->GetCurrentStep() == 2)
|
||||
{
|
||||
// 只生成1个节点
|
||||
AllNodes.Empty();
|
||||
UFishingMapNode* Node = NewObject<UFishingMapNode>();
|
||||
Node->NodeType = EMapNodeType::Battle;
|
||||
AllNodes.Add(Node);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常生成
|
||||
GenerateMapWithConfig(DefaultMapConfig);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 强制拾取奖励
|
||||
|
||||
```cpp
|
||||
// RewardWidget.cpp
|
||||
void URewardWidget::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
UTutorialManager* Tutorial = GetGameInstance()->GetSubsystem<UTutorialManager>();
|
||||
|
||||
if (Tutorial && Tutorial->IsInTutorial())
|
||||
{
|
||||
int32 Step = Tutorial->GetCurrentStep();
|
||||
if (Step == 7 || Step == 10) // 两场战斗后
|
||||
{
|
||||
// 隐藏关闭按钮,直到拾取完毕
|
||||
Btn_Close->SetVisibility(ESlateVisibility::Collapsed);
|
||||
bMustCollectAll = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void URewardWidget::OnAllItemsCollected()
|
||||
{
|
||||
if (bMustCollectAll)
|
||||
{
|
||||
Btn_Close->SetVisibility(ESlateVisibility::Visible);
|
||||
// 显示提示:"点击关闭继续"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、遮罩和高亮效果(简单实现)
|
||||
|
||||
### 遮罩Widget(WBP_TutorialMask)
|
||||
|
||||
创建一个简单的UMG:
|
||||
```
|
||||
Canvas Panel (全屏)
|
||||
└─ Image (黑色,透明度0.7)
|
||||
```
|
||||
|
||||
在 TutorialManager 中显示/隐藏它。
|
||||
|
||||
### 高亮效果(3种简单方案)
|
||||
|
||||
**方案1:边框发光**
|
||||
```cpp
|
||||
// 给按钮添加一个Border,设置发光颜色
|
||||
Btn_Sail->SetBorderBrush(HighlightBrush);
|
||||
```
|
||||
|
||||
**方案2:缩放动画**
|
||||
```
|
||||
创建UMG动画:
|
||||
0.0s -> Scale 1.0
|
||||
0.5s -> Scale 1.1
|
||||
1.0s -> Scale 1.0
|
||||
循环播放
|
||||
```
|
||||
|
||||
**方案3:后处理材质**
|
||||
给高亮Widget添加后处理效果(最炫酷,但稍复杂)。
|
||||
|
||||
---
|
||||
|
||||
## 七、完整流程示例
|
||||
|
||||
### 配置TutorialSteps(在编辑器中)
|
||||
|
||||
```cpp
|
||||
TutorialSteps[0]:
|
||||
StepID: 0
|
||||
DialogueAsset: DA_Tutorial_Intro
|
||||
VisibleWidgetTags: []
|
||||
HintText: ""
|
||||
|
||||
TutorialSteps[1]:
|
||||
StepID: 1
|
||||
VisibleWidgetTags: [Btn_Sail]
|
||||
HighlightWidgetTags: [Btn_Sail]
|
||||
HintText: "点击【出航】按钮"
|
||||
|
||||
TutorialSteps[2]:
|
||||
StepID: 2
|
||||
VisibleWidgetTags: [MapNode_0]
|
||||
HighlightWidgetTags: [MapNode_0]
|
||||
HintText: "选择一个地点"
|
||||
|
||||
// ... 继续配置到步骤15
|
||||
```
|
||||
|
||||
### 调用流程
|
||||
|
||||
```cpp
|
||||
// 游戏启动时
|
||||
void AMyGameInstance::Init()
|
||||
{
|
||||
Super::Init();
|
||||
|
||||
UTutorialManager* Tutorial = GetSubsystem<UTutorialManager>();
|
||||
|
||||
// 检查存档
|
||||
bool bCompletedTutorial = GameInfoManager->HasCompletedTutorial();
|
||||
if (!bCompletedTutorial)
|
||||
{
|
||||
Tutorial->StartTutorial();
|
||||
}
|
||||
}
|
||||
|
||||
// 出航按钮点击时
|
||||
void UHomeUIWidget::OnSailButtonClicked()
|
||||
{
|
||||
UTutorialManager* Tutorial = GetGameInstance()->GetSubsystem<UTutorialManager>();
|
||||
|
||||
if (Tutorial && Tutorial->IsInTutorial() && Tutorial->GetCurrentStep() == 1)
|
||||
{
|
||||
// 完成步骤1,进入步骤2
|
||||
Tutorial->NextStep();
|
||||
}
|
||||
|
||||
// 打开地图
|
||||
OpenMapUI();
|
||||
}
|
||||
|
||||
// 地图节点点击时
|
||||
void UMapWidget::OnNodeClicked()
|
||||
{
|
||||
UTutorialManager* Tutorial = GetGameInstance()->GetSubsystem<UTutorialManager>();
|
||||
|
||||
if (Tutorial && Tutorial->IsInTutorial() && Tutorial->GetCurrentStep() == 2)
|
||||
{
|
||||
Tutorial->NextStep();
|
||||
}
|
||||
|
||||
// 进入战斗
|
||||
StartBattle();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、总结
|
||||
|
||||
### 只需要做3件事:
|
||||
|
||||
1. **创建 TutorialManager**(1个类,~200行代码)
|
||||
2. **给UI Widget设置Tag**(在UMG编辑器中操作)
|
||||
3. **配置TutorialSteps表格**(在编辑器中填数据)
|
||||
|
||||
### 改造工作量:
|
||||
|
||||
- ✅ 新增代码:2个文件(TutorialManager + TutorialWidget基类)
|
||||
- ✅ UI改造:继承基类或蓝图中加几行代码
|
||||
- ✅ 特殊逻辑:在现有代码中加if判断
|
||||
- ✅ 总代码量:<500行
|
||||
|
||||
### 优势:
|
||||
|
||||
- 🟢 **极简**:只有1个核心类
|
||||
- 🟢 **直观**:配置就是一个表格
|
||||
- 🟢 **灵活**:可蓝图可C++
|
||||
- 🟢 **低侵入**:不破坏现有结构
|
||||
|
||||
---
|
||||
|
||||
## 九、文件结构
|
||||
|
||||
```
|
||||
Source/ProjectFish/Tutorial/
|
||||
├── TutorialManager.h # 管理类(核心)
|
||||
├── TutorialManager.cpp
|
||||
├── TutorialWidget.h # UI基类(可选)
|
||||
└── TutorialWidget.cpp
|
||||
|
||||
Content/UI/Tutorial/
|
||||
└── WBP_TutorialMask.uasset # 遮罩Widget
|
||||
```
|
||||
|
||||
就这么简单!🎉
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -67,7 +67,7 @@ FText UDialogueAsset::GetNextNodeText()
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDialogueComplete.Broadcast();
|
||||
UE_LOG(LogTemp, Warning, TEXT("DialogueNode has no output pin"));
|
||||
}
|
||||
return FText::FromString(TEXT(""));
|
||||
}
|
||||
|
||||
@ -93,7 +93,6 @@ public:
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNeedPlayeSelectDelegate, const TArray<FText>&, Options);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDialogueComplete);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -116,8 +115,6 @@ public:
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable, Category=Dialogue)
|
||||
FNeedPlayeSelectDelegate OnNeedPlayerSelect;
|
||||
UPROPERTY(BlueprintAssignable, Category=Dialogue)
|
||||
FOnDialogueComplete OnDialogueComplete;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Dialogue)
|
||||
TArray<UDialogueRuntimeNode*> NodeDatas;
|
||||
|
||||
@ -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.Contains(FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y))
|
||||
///SlotItems[FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y)] != -1
|
||||
if (ContainerShape->IsSlotActive(Item.ContainerStartPos.X + x, Item.ContainerStartPos.Y + y) &&
|
||||
SlotItems[FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y)] != -1
|
||||
)
|
||||
{
|
||||
OverlapItems.Add(SlotItems[FIntPoint(x + Item.ContainerStartPos.X, y + Item.ContainerStartPos.Y)] );
|
||||
|
||||
@ -2,21 +2,3 @@
|
||||
|
||||
|
||||
#include "PlayerInfoSaveGame.h"
|
||||
|
||||
#include "ProjectFish/Gameplay/Subsystem/GameInfoManager.h"
|
||||
|
||||
void UPlayerInfoSaveGame::BeginDestroy()
|
||||
{
|
||||
Super::BeginDestroy();
|
||||
}
|
||||
|
||||
void UPlayerInfoSaveGame::SetShipContainerItems(TArray<FContainerItemSaveData> NewItems)
|
||||
{
|
||||
ShipContainerItems = NewItems;
|
||||
|
||||
if (GetOuter())
|
||||
{
|
||||
GetOuter()->GetWorld()->GetGameInstance()->GetSubsystem<UGameInfoManager>()->SaveGameInfo();
|
||||
OnShipContainerUpdate.Broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
#include "ProjectFish/Quest/QuestTypes.h"
|
||||
#include "PlayerInfoSaveGame.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnShipContainerUpdate);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -18,11 +17,6 @@ class PROJECTFISH_API UPlayerInfoSaveGame : public USaveGame
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
virtual void BeginDestroy() override;
|
||||
UPROPERTY(SaveGame, BlueprintReadWrite, meta = (ToolTip = "开启教程模式"))
|
||||
bool TutorialMode = true;
|
||||
|
||||
UPROPERTY(SaveGame, BlueprintReadWrite, meta = (ToolTip = "船只资源"))
|
||||
FPrimaryAssetId ShipAssetID;
|
||||
|
||||
@ -34,7 +28,7 @@ public:
|
||||
FPrimaryAssetId ShipContainerShapeID;
|
||||
|
||||
// 船舱物品存档数据
|
||||
UPROPERTY(SaveGame, BlueprintReadOnly, meta = (ToolTip = "船舱物品数据"))
|
||||
UPROPERTY(SaveGame, BlueprintReadWrite, meta = (ToolTip = "船舱物品数据"))
|
||||
TArray<FContainerItemSaveData> ShipContainerItems;
|
||||
|
||||
UPROPERTY(SaveGame, BlueprintReadWrite, meta = (ToolTip = "仓库资源"))
|
||||
@ -58,12 +52,4 @@ public:
|
||||
//已战胜的鱼
|
||||
UPROPERTY(SaveGame, BlueprintReadWrite, meta = (ToolTip = "被击败的鱼"))
|
||||
TArray<int32> Fish_defeated_IDS;
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable, Category = "PlayerInfoSaveGame")
|
||||
FOnShipContainerUpdate OnShipContainerUpdate;
|
||||
|
||||
protected:
|
||||
UFUNCTION(BlueprintCallable, Category= "PlayerInfoSaveGame")
|
||||
void SetShipContainerItems(TArray<FContainerItemSaveData> NewItems);
|
||||
};
|
||||
|
||||
@ -3,11 +3,9 @@
|
||||
#include "QuestAsset.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "DialogueAsset.h"
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "AssetRegistry/AssetData.h"
|
||||
#include "Misc/MessageDialog.h"
|
||||
#include "ProjectFish/Gameplay/Subsystem/QuestManager.h"
|
||||
|
||||
void UQuestAsset::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
@ -86,31 +84,5 @@ void UQuestAsset::PostDuplicate(bool bDuplicateForPIE)
|
||||
QuestID = MaxQuestID + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void UQuestAsset::OnDialogueComplete()
|
||||
{
|
||||
bDialogueComplete = true;
|
||||
QuestManager->AcceptQuest(this, true);
|
||||
}
|
||||
|
||||
void UQuestAsset::Initialize(class UQuestManager* InQuestManager)
|
||||
{
|
||||
this->QuestManager = InQuestManager;
|
||||
bDialogueComplete = false;
|
||||
if (IsValid(DialogueTrigger))
|
||||
{
|
||||
DialogueTrigger->OnDialogueComplete.AddDynamic(this, &UQuestAsset::OnDialogueComplete);
|
||||
}
|
||||
}
|
||||
|
||||
bool UQuestAsset::Acceptable()
|
||||
{
|
||||
if (IsValid(DialogueTrigger) &&bDialogueComplete)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return AcceptAble;
|
||||
}
|
||||
@ -23,11 +23,6 @@ public:
|
||||
|
||||
virtual void PostDuplicate(bool bDuplicateForPIE) override;
|
||||
#endif
|
||||
UFUNCTION()
|
||||
void OnDialogueComplete();
|
||||
|
||||
void Initialize(class UQuestManager* InQuestManager);
|
||||
bool Acceptable();
|
||||
/** 任务编号ID */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Basic")
|
||||
int32 QuestID = 0;
|
||||
@ -36,20 +31,17 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Basic")
|
||||
FText QuestName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Basic", meta = (ToolTip = "当满足所有条件时,是否可接受"))
|
||||
bool AcceptAble = true;
|
||||
|
||||
/** 任务描述 */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Basic", meta = (MultiLine = true))
|
||||
FText QuestDescription;
|
||||
|
||||
/** 前置触发任务ID列表() */
|
||||
/** 前置任务ID列表() */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Trigger", meta = (ToolTip = "完成这些任务后才能触发当前任务, 不填写默认激活接受"))
|
||||
TArray<int32> PrerequisiteQuestIDs;
|
||||
|
||||
/** 对话完成后触发 */
|
||||
/** 任务触发条件(预留,可在蓝图中实现) */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Trigger")
|
||||
class UDialogueAsset* DialogueTrigger;
|
||||
FString TriggerCondition;
|
||||
|
||||
/** 任务目标列表 */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Objectives")
|
||||
@ -62,9 +54,5 @@ public:
|
||||
/** 任务完成条件描述(预留,可在蓝图中实现) */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest|Completion")
|
||||
FString CompletionCondition;
|
||||
|
||||
private:
|
||||
UPROPERTY()
|
||||
class UQuestManager* QuestManager;
|
||||
bool bDialogueComplete;
|
||||
|
||||
};
|
||||
|
||||
@ -478,44 +478,5 @@ public:
|
||||
int32 QuestID;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FTutorialUIControlParam
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||
TSubclassOf<class UTutorialControlWidget_Base> TutorialControlUIClass;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||
TArray<FName> HiddenUINames;
|
||||
// UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||
// TArray<FName> ShowUINames;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FTutorialStep: public FTableRowBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tutorial Asset")
|
||||
FName StepName;
|
||||
//教程对话
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tutorial Asset")
|
||||
class UDialogueAsset* Dialogue;
|
||||
//教程任务
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tutorial Asset")
|
||||
class UQuestAsset* Quest;
|
||||
//需要显示的ui
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tutorial Asset")
|
||||
TSubclassOf<UUserWidget> TutorialUI;
|
||||
//控制ui的显示
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tutorial Asset")
|
||||
TArray<FTutorialUIControlParam> UIControlParams;
|
||||
|
||||
//引导task
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tutorial Asset")
|
||||
TSubclassOf<class UTutorialTask_Base> TutorialTaskClass;
|
||||
|
||||
UPROPERTY()
|
||||
UTutorialTask_Base* TutorialTaskObject;
|
||||
};
|
||||
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "FishGameInstance.h"
|
||||
|
||||
void UFishGameInstance::OnStart()
|
||||
{
|
||||
Super::OnStart();
|
||||
InitTutorialSteps();
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "FishGameInstance.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class PROJECTFISH_API UFishGameInstance : public UGameInstance
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
/** GameInstace */
|
||||
virtual void OnStart() override;
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent)
|
||||
void InitTutorialSteps();
|
||||
};
|
||||
@ -17,11 +17,6 @@ void UFishingRodConfigSubsystem::CreateFishingRodInventory(class UShapeAsset* Fi
|
||||
playerInventoryConfig = DuplicateObject<UBagConfigAsset>(PlayerBagConfig, this);
|
||||
}
|
||||
|
||||
void UFishingRodConfigSubsystem::SetFishingRodConfig(UBagConfigAsset* FishingRodConfig)
|
||||
{
|
||||
fishingRodInventoryConfig = FishingRodConfig;
|
||||
}
|
||||
|
||||
UBagConfigAsset* UFishingRodConfigSubsystem::GetFishingRodInventory()
|
||||
{
|
||||
return this->fishingRodInventoryConfig;
|
||||
|
||||
@ -18,8 +18,6 @@ class PROJECTFISH_API UFishingRodConfigSubsystem : public UGameInstanceSubsystem
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "PlayerInventorySubsystem")
|
||||
void CreateFishingRodInventory(class UShapeAsset* FishingRodShape, class UBagConfigAsset* PlayerBagConfig);
|
||||
UFUNCTION(BlueprintCallable, Category = "PlayerInventorySubsystem")
|
||||
void SetFishingRodConfig(UBagConfigAsset* FishingRodConfig);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PlayerInventorySubsystem")
|
||||
UBagConfigAsset* GetFishingRodInventory();
|
||||
|
||||
@ -24,10 +24,9 @@ void UGameInfoManager::NewSaveGame()
|
||||
|
||||
void UGameInfoManager::SaveGameInfo()
|
||||
{
|
||||
if (!IsValid(PlayerInfo))
|
||||
if (!IsValid(PlayerInfo.Get()))
|
||||
{
|
||||
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
|
||||
}
|
||||
// 保存任务数据
|
||||
if (UQuestManager* QuestManager = GetGameInstance()->GetSubsystem<UQuestManager>())
|
||||
@ -35,7 +34,7 @@ void UGameInfoManager::SaveGameInfo()
|
||||
PlayerInfo->QuestSaveData = QuestManager->GetQuestSaveData();
|
||||
}
|
||||
|
||||
if (UGameplayStatics::SaveGameToSlot(PlayerInfo, SaveGameSlotName, 0))
|
||||
if (UGameplayStatics::SaveGameToSlot(PlayerInfo.Get(), SaveGameSlotName, 0))
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("存档保存成功"));
|
||||
}
|
||||
@ -50,7 +49,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>())
|
||||
{
|
||||
@ -75,8 +74,7 @@ bool UGameInfoManager::LoadGameInfo()
|
||||
|
||||
void UGameInfoManager::CreateGameInfo(UContainerInfo* ShipContainer, UContainerInfo* PlayerContainer)
|
||||
{
|
||||
if (!IsValid(PlayerInfo))
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
|
||||
PlayerInfo->ShipContainerItems = ShipContainer->GetSaveData();
|
||||
PlayerInfo->ShipContainerShapeID = ShipContainer->ContainerShape->GetPrimaryAssetId();
|
||||
|
||||
@ -95,7 +93,7 @@ void UGameInfoManager::CreateGameInfoAndSave(UShapeAsset* ShipContainerShape, US
|
||||
PlayerContainer->InitContainerByShape(PlayerContainerShape);
|
||||
|
||||
//创建要保存的额存档信息
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
|
||||
PlayerInfo->ShipContainerItems = ShipContainer->GetSaveData();
|
||||
PlayerInfo->ShipContainerShapeID = ShipContainer->ContainerShape->GetPrimaryAssetId();
|
||||
|
||||
@ -105,27 +103,6 @@ void UGameInfoManager::CreateGameInfoAndSave(UShapeAsset* ShipContainerShape, US
|
||||
SaveGameInfo();
|
||||
}
|
||||
|
||||
bool UGameInfoManager::IsTutorialMode()
|
||||
{
|
||||
if (!IsValid(PlayerInfo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PlayerInfo->TutorialMode;
|
||||
}
|
||||
}
|
||||
|
||||
void UGameInfoManager::SetTutorialMode(bool bTutorialMode)
|
||||
{
|
||||
if (!IsValid(PlayerInfo))
|
||||
{
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
|
||||
}
|
||||
PlayerInfo->TutorialMode = bTutorialMode;
|
||||
}
|
||||
|
||||
bool UGameInfoManager::IsFishDefeated(int32 FishID)
|
||||
{
|
||||
if (!IsValid(PlayerInfo))
|
||||
@ -139,7 +116,7 @@ void UGameInfoManager::AddDefeatedFish(int32 FishID)
|
||||
{
|
||||
if (!IsValid(PlayerInfo))
|
||||
{
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(GetGameInstance());
|
||||
PlayerInfo = NewObject<UPlayerInfoSaveGame>(this);
|
||||
}
|
||||
PlayerInfo->Fish_defeated_IDS.Add(FishID);
|
||||
SaveGameInfo();
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DialogueAsset.h"
|
||||
#include "ProjectFish/Data/PlayerInfoSaveGame.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "GameInfoManager.generated.h"
|
||||
@ -31,22 +30,14 @@ public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void CreateGameInfoAndSave(UShapeAsset* ShipContainerShape, UShapeAsset* PlayerContainerShape);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category= "GameInfo")
|
||||
bool IsTutorialMode();
|
||||
|
||||
UFUNCTION(Blueprintable, Category= "GameInfo")
|
||||
void SetTutorialMode(bool bTutorialMode);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
bool IsFishDefeated(int32 FishID);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void AddDefeatedFish(int32 FishID);
|
||||
|
||||
TObjectPtr<class UPlayerInfoSaveGame> GetPlayerInfo() {return PlayerInfo;}
|
||||
protected:
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
class UPlayerInfoSaveGame* PlayerInfo;
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
TObjectPtr<class UPlayerInfoSaveGame> PlayerInfo;
|
||||
|
||||
static FString SaveGameSlotName;
|
||||
};
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "QuestManager.h"
|
||||
|
||||
#include "DialogueAsset.h"
|
||||
#include "GameInfoManager.h"
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "Engine/AssetManager.h"
|
||||
@ -39,7 +38,6 @@ void UQuestManager::LoadAllQuests()
|
||||
LoadHandle->GetLoadedAssets(Assets); // 获取所有加载成功的资源
|
||||
for (auto questAsset : Assets)
|
||||
{
|
||||
Cast<UQuestAsset>(questAsset)->Initialize(this);
|
||||
QuestAssets.Add(Cast<UQuestAsset>(questAsset));
|
||||
}
|
||||
}
|
||||
@ -78,7 +76,14 @@ bool UQuestManager::AcceptQuest(UQuestAsset* QuestAsset, bool bSaveGameInfo )
|
||||
return false;
|
||||
}
|
||||
|
||||
AcceptQuestInternal(QuestAsset);
|
||||
// 创建运行时数据
|
||||
FQuestRuntimeData RuntimeData = CreateRuntimeData(QuestAsset);
|
||||
RuntimeData.State = EQuestState::InProgress;
|
||||
ActiveQuestsMap.Add(QuestAsset->QuestID, RuntimeData);
|
||||
|
||||
// 触发事件
|
||||
OnQuestStateChanged.Broadcast(QuestAsset->QuestID, EQuestState::InProgress);
|
||||
UE_LOG(LogTemp, Warning, TEXT("Quest %s Accepted"), *QuestAsset->QuestName.ToString());
|
||||
|
||||
if (bSaveGameInfo)
|
||||
{
|
||||
@ -89,22 +94,6 @@ bool UQuestManager::AcceptQuest(UQuestAsset* QuestAsset, bool bSaveGameInfo )
|
||||
return true;
|
||||
}
|
||||
|
||||
void UQuestManager::AcceptQuestInternal(UQuestAsset* QuestAsset)
|
||||
{
|
||||
if (QuestAsset)
|
||||
{
|
||||
// 创建运行时数据
|
||||
FQuestRuntimeData RuntimeData = CreateRuntimeData(QuestAsset);
|
||||
RuntimeData.State = EQuestState::InProgress;
|
||||
ActiveQuestsMap.Add(QuestAsset->QuestID, RuntimeData);
|
||||
|
||||
// 触发事件
|
||||
OnQuestStateChanged.Broadcast(QuestAsset->QuestID, EQuestState::InProgress);
|
||||
UE_LOG(LogTemp, Warning, TEXT("Quest %s Accepted"), *QuestAsset->QuestName.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool UQuestManager::FollowQuest(int32 QuestID, bool Follow)
|
||||
{
|
||||
FQuestRuntimeData* RuntimeData = ActiveQuestsMap.Find(QuestID);
|
||||
@ -341,21 +330,17 @@ bool UQuestManager::CanAcceptQuest(UQuestAsset* QuestAsset) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (QuestAsset->AcceptAble)
|
||||
|
||||
// 检查所有前置任务是否完成
|
||||
for (int32 PrerequisiteID : QuestAsset->PrerequisiteQuestIDs)
|
||||
{
|
||||
// 检查所有前置任务是否完成
|
||||
for (int32 PrerequisiteID : QuestAsset->PrerequisiteQuestIDs)
|
||||
if (!CompletedQuestIDs.Contains(PrerequisiteID))
|
||||
{
|
||||
if (!CompletedQuestIDs.Contains(PrerequisiteID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return QuestAsset->Acceptable();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TArray<FQuestSaveData> UQuestManager::GetQuestSaveData() const
|
||||
@ -430,6 +415,7 @@ void UQuestManager::LoadFromSaveData(const TArray<FQuestSaveData>& SaveData)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CheckAcceptableQuests(true);
|
||||
|
||||
@ -55,13 +55,10 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Quest")
|
||||
void CheckAcceptableQuests(bool bSaveGameInfo = false);
|
||||
|
||||
/** 检测并接受任务 */
|
||||
/** 接受任务 */
|
||||
UFUNCTION(BlueprintCallable, Category = "Quest")
|
||||
bool AcceptQuest(UQuestAsset* QuestAsset, bool bSaveGameInfo = false);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Quest")
|
||||
void AcceptQuestInternal(UQuestAsset* QuestAsset);
|
||||
|
||||
/** 接受任务 */
|
||||
UFUNCTION(BlueprintCallable, Category = "Quest")
|
||||
bool FollowQuest(int32 QuestID, bool Follow);
|
||||
|
||||
@ -1,174 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "TutorialManagerSubsystem.h"
|
||||
|
||||
#include "GameInfoManager.h"
|
||||
#include "QuestManager.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "Blueprint/WidgetBlueprintLibrary.h"
|
||||
#include "Engine/AssetManager.h"
|
||||
#include "Engine/StreamableManager.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "ProjectFish/DataAsset/QuestAsset.h"
|
||||
#include "ProjectFish/Gameplay/TutorialSystem/TutorialTask_Base.h"
|
||||
#include "ProjectFish/Widget/DialogueWidget_Base.h"
|
||||
#include "ProjectFish/Widget/TutorialControlWidget_Base.h"
|
||||
|
||||
void UTutorialManagerSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
Collection.InitializeDependency<UGameInfoManager>();
|
||||
|
||||
DialogueUIPath = (TEXT("/Game/UI/Dialogue/UMG_DialogueWindow.UMG_DialogueWindow_C"));
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::InitSteps(TArray<FTutorialStep> Steps)
|
||||
{
|
||||
TutorialSteps = Steps;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
ShowDialogue();
|
||||
}
|
||||
if (IsValid(CurrentStep.Quest))
|
||||
{
|
||||
AccepAndFollowQuest();
|
||||
}
|
||||
if (IsValid(CurrentStep.TutorialUI))
|
||||
{
|
||||
ShowTutorialUI();
|
||||
}
|
||||
if (CurrentStep.UIControlParams.Num() != 0)
|
||||
{
|
||||
ControlUI();
|
||||
}
|
||||
if (IsValid(CurrentStep.TutorialTaskClass))
|
||||
{
|
||||
CreateTask();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("所有教程已结束"));
|
||||
GetGameInstance()->GetSubsystem<UGameInfoManager>()->SetTutorialMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::CompleteTutorialStep()
|
||||
{
|
||||
if (bTutorialing)
|
||||
{
|
||||
if (TutorialTaskObject)
|
||||
{
|
||||
TutorialTaskObject->BeforTutorialComplete();
|
||||
TutorialTaskObject->ConditionalBeginDestroy();
|
||||
TutorialTaskObject = nullptr;
|
||||
}
|
||||
if (TutorialWidget)
|
||||
{
|
||||
TutorialWidget->RemoveFromViewport();
|
||||
TutorialWidget = nullptr;
|
||||
}
|
||||
UE_LOG(LogTemp, Warning, TEXT(" 教程进行下一步"));
|
||||
OnStepComplete.Broadcast(CurrentTutorialStep);
|
||||
CurrentTutorialStep++;
|
||||
ApplyCurrentTutorialStep();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FTutorialStep UTutorialManagerSubsystem::GetCurrentTutorialStep() const
|
||||
{
|
||||
return TutorialSteps[CurrentTutorialStep];
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::SetTutorialCompleteOnLevelLoaded()
|
||||
{
|
||||
LevelLoadedDelegateHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(
|
||||
this,
|
||||
&UTutorialManagerSubsystem::OnLevelLoaded
|
||||
);
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::OnLevelLoaded(UWorld* World)
|
||||
{
|
||||
FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(LevelLoadedDelegateHandle);
|
||||
CompleteTutorialStep();
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::OnDialogueCompleted()
|
||||
{
|
||||
DialogueWidget->RemoveFromParent();
|
||||
CompleteTutorialStep();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UTutorialManagerSubsystem::ShowDialogue()
|
||||
{
|
||||
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
|
||||
UClass* WidgetClass = LoadClass<UUserWidget>(this, *DialogueUIPath);
|
||||
if (WidgetClass)
|
||||
{
|
||||
DialogueWidget = CreateWidget<UDialogueWidget_Base>(GetWorld(), WidgetClass);
|
||||
if (DialogueWidget)
|
||||
{
|
||||
DialogueWidget->DialogueAsset = CurrentStep.Dialogue;
|
||||
DialogueWidget->DialogueAsset->OnDialogueComplete.AddDynamic(this, &UTutorialManagerSubsystem::OnDialogueCompleted);
|
||||
DialogueWidget->AddToViewport(99);
|
||||
UGameplayStatics::GetPlayerController(GetWorld(), 0)->SetShowMouseCursor(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("dialogue path is error"));
|
||||
}
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::AccepAndFollowQuest()
|
||||
{
|
||||
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
|
||||
GetGameInstance()->GetSubsystem<UQuestManager>()->AcceptQuestInternal(CurrentStep.Quest);
|
||||
GetGameInstance()->GetSubsystem<UQuestManager>()->FollowQuest(CurrentStep.Quest->QuestID, true);
|
||||
CompleteTutorialStep();
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::ShowTutorialUI()
|
||||
{
|
||||
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
|
||||
TutorialWidget = CreateWidget<UUserWidget>(GetWorld(), CurrentStep.TutorialUI);
|
||||
TutorialWidget->AddToViewport(99);
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::ControlUI()
|
||||
{
|
||||
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
|
||||
|
||||
for (auto ControlParam: CurrentStep.UIControlParams)
|
||||
{
|
||||
TArray<UUserWidget*> FoundWidgets;
|
||||
UWidgetBlueprintLibrary::GetAllWidgetsOfClass(this, FoundWidgets, ControlParam.TutorialControlUIClass, false);
|
||||
for (auto Widget: FoundWidgets)
|
||||
{
|
||||
Cast<UTutorialControlWidget_Base>(Widget)->TutorialHideUI(ControlParam.HiddenUINames);
|
||||
//Cast<UTutorialControlWidget_Base>(Widget)->TutorialShowUI(ControlParam.ShowUINames);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UTutorialManagerSubsystem::CreateTask()
|
||||
{
|
||||
FTutorialStep CurrentStep = TutorialSteps[CurrentTutorialStep];
|
||||
TutorialTaskObject = NewObject<UTutorialTask_Base>(this, CurrentStep.TutorialTaskClass);
|
||||
TutorialTaskObject->Execute(GetWorld()->GetAuthGameMode());
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "TutorialManagerSubsystem.generated.h"
|
||||
|
||||
|
||||
struct FTutorialStep;
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnStepComplete, int32, CompleteIndex);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class PROJECTFISH_API UTutorialManagerSubsystem : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
/** GameInstanceSubsystem */
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category= TutorialSubsystem)
|
||||
void InitSteps(TArray<FTutorialStep> Steps);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category= TutorialSubsystem)
|
||||
void ApplyCurrentTutorialStep();
|
||||
UFUNCTION(BlueprintCallable, Category= TutorialSubsystem)
|
||||
void CompleteTutorialStep();
|
||||
UFUNCTION(BlueprintPure, Category= TutorialSubsystem)
|
||||
FTutorialStep GetCurrentTutorialStep() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category= TutorialSubsystem)
|
||||
void SetTutorialCompleteOnLevelLoaded();
|
||||
void OnLevelLoaded(UWorld* World);
|
||||
protected:
|
||||
|
||||
//显示对话框UI
|
||||
void ShowDialogue();
|
||||
UFUNCTION()
|
||||
void OnDialogueCompleted();
|
||||
//接受任务
|
||||
void AccepAndFollowQuest();
|
||||
//显示教程UI
|
||||
void ShowTutorialUI();
|
||||
//控制指定UI
|
||||
void ControlUI();
|
||||
//创建task
|
||||
void CreateTask();
|
||||
protected:
|
||||
FDelegateHandle LevelLoadedDelegateHandle;
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnStepComplete OnStepComplete;
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
bool bTutorialing;
|
||||
|
||||
TArray<FTutorialStep> TutorialSteps;
|
||||
int32 CurrentTutorialStep = 0;
|
||||
FString DialogueUIPath;
|
||||
UPROPERTY()
|
||||
class UDialogueWidget_Base* DialogueWidget;
|
||||
|
||||
UPROPERTY()
|
||||
UUserWidget* TutorialWidget;
|
||||
|
||||
UPROPERTY()
|
||||
class UTutorialTask_Base* TutorialTaskObject;
|
||||
};
|
||||
@ -1,21 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "TutorialTask_Base.h"
|
||||
|
||||
#include "ProjectFish/Gameplay/Subsystem/TutorialManagerSubsystem.h"
|
||||
|
||||
// void UTutorialTask_Base::BeginDestroy()
|
||||
// {
|
||||
// UObject::BeginDestroy();
|
||||
// //task 删除的时候,自动完成该引导step
|
||||
// if (GetWorld())
|
||||
// GetWorld()->GetGameInstance()->GetSubsystem<UTutorialManagerSubsystem>()->CompleteTutorialStep();
|
||||
// }
|
||||
void UTutorialTask_Base::Execute_Implementation(class AGameModeBase* GameMode)
|
||||
{
|
||||
}
|
||||
|
||||
void UTutorialTask_Base::BeforTutorialComplete_Implementation()
|
||||
{
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "TutorialTask_Base.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class PROJECTFISH_API UTutorialTask_Base : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
/** UObject */
|
||||
//virtual void BeginDestroy() override;
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category= "TutorialTask")
|
||||
void Execute(class AGameModeBase* GameMode);
|
||||
virtual void Execute_Implementation(class AGameModeBase* GameMode);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category= "TutorialTask")
|
||||
void BeforTutorialComplete();
|
||||
virtual void BeforTutorialComplete_Implementation();
|
||||
|
||||
};
|
||||
@ -1,34 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "TutorialTask_Base.h"
|
||||
#include "TutorialTask_CheckShipContainer.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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;
|
||||
};
|
||||
@ -1,37 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "TutorialTask_GamePause.h"
|
||||
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
void UTutorialTask_GamePause::Execute_Implementation(class AGameModeBase* GameMode)
|
||||
{
|
||||
Super::Execute_Implementation(GameMode);
|
||||
// LevelLoadedDelegateHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(
|
||||
// this,
|
||||
// &UTutorialTask_GamePause::OnLevelLoaded
|
||||
// );
|
||||
UGameplayStatics::SetGamePaused(this, true);
|
||||
}
|
||||
|
||||
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
|
||||
// );
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "TutorialTask_Base.h"
|
||||
#include "TutorialTask_GamePause.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class PROJECTFISH_API UTutorialTask_GamePause : public UTutorialTask_Base
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
virtual void Execute_Implementation(class AGameModeBase* GameMode) override;
|
||||
|
||||
virtual void BeforTutorialComplete_Implementation() override;
|
||||
|
||||
void OnLevelLoaded(UWorld* World);
|
||||
private:
|
||||
FDelegateHandle LevelLoadedDelegateHandle;
|
||||
};
|
||||
@ -6,7 +6,6 @@ public class ProjectFish : ModuleRules
|
||||
{
|
||||
public ProjectFish(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { "Dialogue" });
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
OptimizeCode = CodeOptimization.Never;
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine",
|
||||
|
||||
@ -23,7 +23,7 @@ void USkillManager::Tick(float DeltaTime)
|
||||
|
||||
bool USkillManager::IsTickable() const
|
||||
{
|
||||
return !bGameEnd && IsValid(GameMode) && GameMode->GetBattleIsBegin() && !GameMode->IsPaused();
|
||||
return !bGameEnd && IsValid(GameMode) && GameMode->GetBattleIsBegin();
|
||||
}
|
||||
|
||||
TStatId USkillManager::GetStatId() const
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
|
||||
#include "FishFunctionLibrary.h"
|
||||
|
||||
#include "EngineUtils.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "ProjectFish/Data/ContainerInfo.h"
|
||||
|
||||
@ -26,20 +25,3 @@ int32 UFishFunctionLibrary::GetContainerItemHeight(const UObject* WorldContextOb
|
||||
{
|
||||
return ContainerItem.GetItemHeight();
|
||||
}
|
||||
|
||||
AActor* UFishFunctionLibrary::GetActorOfClass(const UObject* WorldContextObject, TSubclassOf<AActor> ActorClass)
|
||||
{
|
||||
if (ActorClass)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
|
||||
{
|
||||
for (TActorIterator<AActor> It(World, ActorClass); It; ++It)
|
||||
{
|
||||
AActor* Actor = *It;
|
||||
return Actor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -21,9 +21,6 @@ public:
|
||||
UFUNCTION(BlueprintPure, Category = "FishFunctionLibrary", meta=(WorldContext="WorldContextObject"))
|
||||
static int32 GetContainerItemWiidth(const UObject* WorldContextObject, FContainerItem ContainerItem);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "FishFunctionLibrary", meta=(WorldContext="WorldContextObject"))
|
||||
static int32 GetContainerItemHeight(const UObject* WorldContextObject, FContainerItem ContainerItem);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Actor")
|
||||
static AActor* GetActorOfClass(const UObject* WorldContextObject, TSubclassOf<AActor> ActorClass);
|
||||
UFUNCTION(BlueprintPure, Category = "FishFunctionLibrary", meta=(WorldContext="WorldContextObject"))
|
||||
static int32 GetContainerItemHeight(const UObject* WorldContextObject, FContainerItem ContainerItem);
|
||||
};
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DialogueWidget_Base.h"
|
||||
@ -1,20 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DialogueAsset.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "DialogueWidget_Base.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class PROJECTFISH_API UDialogueWidget_Base : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Dialogue Widget")
|
||||
UDialogueAsset* DialogueAsset;
|
||||
};
|
||||
@ -1,5 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "TutorialControlWidget_Base.h"
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "TutorialControlWidget_Base.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class PROJECTFISH_API UTutorialControlWidget_Base : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent)
|
||||
void TutorialHideUI(const TArray<FName>& UINames);
|
||||
// UFUNCTION(BlueprintImplementableEvent)
|
||||
// void TutorialShowUI(const TArray<FName>& UINames);
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user