409 lines
9.1 KiB
C++
409 lines
9.1 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "QuestManager.h"
|
|
|
|
#include "AssetRegistry/AssetRegistryModule.h"
|
|
#include "Engine/AssetManager.h"
|
|
#include "ProjectFish/DataAsset/QuestAsset.h"
|
|
#include "ProjectFish/Quest/QuestTypes.h"
|
|
|
|
|
|
void UQuestManager::Initialize(FSubsystemCollectionBase& Collection)
|
|
{
|
|
Super::Initialize(Collection);
|
|
}
|
|
|
|
void UQuestManager::Deinitialize()
|
|
{
|
|
Super::Deinitialize();
|
|
ActiveQuestsMap.Empty();
|
|
CompletedQuestIDs.Empty();
|
|
}
|
|
|
|
void UQuestManager::LoadAllQuests()
|
|
{
|
|
if (QuestAssets.Num() == 0)
|
|
{
|
|
// 获得所有任务资源id
|
|
TArray<FPrimaryAssetId> QuestAssetIds;
|
|
UAssetManager::Get().GetPrimaryAssetIdList(TEXT("QuestAsset"), QuestAssetIds);
|
|
|
|
// 异步加载所有任务资产
|
|
TSharedPtr<FStreamableHandle> LoadHandle = UAssetManager::Get().LoadPrimaryAssets(QuestAssetIds);
|
|
if (LoadHandle.IsValid())
|
|
{
|
|
LoadHandle->WaitUntilComplete();
|
|
TArray<UObject*> Assets;
|
|
LoadHandle->GetLoadedAssets(Assets); // 获取所有加载成功的资源
|
|
for (auto questAsset : Assets)
|
|
{
|
|
QuestAssets.Add(Cast<UQuestAsset>(questAsset));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void UQuestManager::CheckAcceptableQuests()
|
|
{
|
|
for (auto QuestAsset : QuestAssets)
|
|
{
|
|
if (!ActiveQuestsMap.Find(QuestAsset->QuestID) && !CompletedQuestIDs.Contains(QuestAsset->QuestID))
|
|
{
|
|
//任务不在当前已激活的任务 和 已完成的任务列表中
|
|
AcceptQuest(QuestAsset);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool UQuestManager::AcceptQuest(UQuestAsset* QuestAsset)
|
|
{
|
|
if (!QuestAsset)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 检查是否已经接受或完成
|
|
if (ActiveQuestsMap.Contains(QuestAsset->QuestID) || CompletedQuestIDs.Contains(QuestAsset->QuestID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 检查前置任务
|
|
if (!CanAcceptQuest(QuestAsset))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 创建运行时数据
|
|
FQuestRuntimeData RuntimeData = CreateRuntimeData(QuestAsset);
|
|
RuntimeData.State = EQuestState::InProgress;
|
|
ActiveQuestsMap.Add(QuestAsset->QuestID, RuntimeData);
|
|
|
|
// 触发事件
|
|
OnQuestStateChanged.Broadcast(QuestAsset->QuestID);
|
|
UE_LOG(LogTemp, Warning, TEXT("Quest %s Accepted"), *QuestAsset->QuestName.ToString());
|
|
return true;
|
|
}
|
|
|
|
bool UQuestManager::FollowQuest(int32 QuestID, bool Follow)
|
|
{
|
|
FQuestRuntimeData* RuntimeData = ActiveQuestsMap.Find(QuestID);
|
|
if (!RuntimeData)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (Follow)
|
|
{
|
|
FollowingQuestIDs.Add(QuestID);
|
|
}
|
|
else
|
|
{
|
|
FollowingQuestIDs.Remove(QuestID);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool UQuestManager::CompleteQuest(int32 QuestID)
|
|
{
|
|
FQuestRuntimeData* RuntimeData = ActiveQuestsMap.Find(QuestID);
|
|
if (!RuntimeData)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 检查所有目标是否完成
|
|
for (const FQuestProgress& Progress : RuntimeData->ObjectiveProgress)
|
|
{
|
|
if (!Progress.bCompleted)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 标记为已完成
|
|
RuntimeData->State = EQuestState::Completed;
|
|
CompletedQuestIDs.Add(QuestID);
|
|
|
|
// 触发事件
|
|
OnQuestStateChanged.Broadcast(QuestID);
|
|
UE_LOG(LogTemp, Warning, TEXT("Quest id = %d Complete"), QuestID);
|
|
// 从活动任务中移除
|
|
ActiveQuestsMap.Remove(QuestID);
|
|
|
|
//检测是否有其他可接受的任务
|
|
CheckAcceptableQuests();
|
|
return true;
|
|
}
|
|
|
|
bool UQuestManager::AbandonQuest(int32 QuestID)
|
|
{
|
|
if (!ActiveQuestsMap.Contains(QuestID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ActiveQuestsMap.Remove(QuestID);
|
|
OnQuestStateChanged.Broadcast(QuestID);
|
|
|
|
return true;
|
|
}
|
|
|
|
void UQuestManager::UpdateObjectiveProgress(int32 QuestID, int32 ObjectiveIndex, int32 Progress)
|
|
{
|
|
FQuestRuntimeData* RuntimeData = ActiveQuestsMap.Find(QuestID);
|
|
if (!RuntimeData || !RuntimeData->QuestAsset)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 检查索引有效性
|
|
if (!RuntimeData->ObjectiveProgress.IsValidIndex(ObjectiveIndex))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 获取目标配置
|
|
const FQuestObjective& Objective = RuntimeData->QuestAsset->Objectives[ObjectiveIndex];
|
|
FQuestProgress& ProgressData = RuntimeData->ObjectiveProgress[ObjectiveIndex];
|
|
|
|
// 更新进度
|
|
ProgressData.CurrentProgress = FMath::Clamp(Progress, 0, Objective.RequiredAmount);
|
|
|
|
// 检查是否完成
|
|
if (ProgressData.CurrentProgress >= Objective.RequiredAmount)
|
|
{
|
|
ProgressData.bCompleted = true;
|
|
}
|
|
|
|
// 触发事件
|
|
OnQuestObjectiveUpdated.Broadcast(QuestID, ObjectiveIndex);
|
|
|
|
// 检查任务是否完成
|
|
CheckQuestCompletion(QuestID);
|
|
}
|
|
|
|
void UQuestManager::UpdateObjectiveByTargetID(FName TargetID, int32 ProgressDelta)
|
|
{
|
|
// 遍历所有活动任务,查找匹配的目标
|
|
for (TPair<int32, FQuestRuntimeData>& Pair : ActiveQuestsMap)
|
|
{
|
|
FQuestRuntimeData& RuntimeData = Pair.Value;
|
|
if (!RuntimeData.QuestAsset)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 查找匹配的目标
|
|
for (int32 i = 0; i < RuntimeData.QuestAsset->Objectives.Num(); ++i)
|
|
{
|
|
const FQuestObjective& Objective = RuntimeData.QuestAsset->Objectives[i];
|
|
if (Objective.TargetID == TargetID)
|
|
{
|
|
// 增加进度
|
|
int32 NewProgress = RuntimeData.ObjectiveProgress[i].CurrentProgress + ProgressDelta;
|
|
UpdateObjectiveProgress(Pair.Key, i, NewProgress);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EQuestState UQuestManager::GetQuestState(int32 QuestID) const
|
|
{
|
|
if (CompletedQuestIDs.Contains(QuestID))
|
|
{
|
|
return EQuestState::Completed;
|
|
}
|
|
|
|
const FQuestRuntimeData* RuntimeData = ActiveQuestsMap.Find(QuestID);
|
|
if (RuntimeData)
|
|
{
|
|
return RuntimeData->State;
|
|
}
|
|
|
|
return EQuestState::NotStarted;
|
|
}
|
|
|
|
bool UQuestManager::IsQuestFollowing(int32 QuestID) const
|
|
{
|
|
return FollowingQuestIDs.Contains(QuestID);
|
|
}
|
|
|
|
TArray<UQuestAsset*> UQuestManager::GetActiveQuests() const
|
|
{
|
|
TArray<UQuestAsset*> Result;
|
|
for (const TPair<int32, FQuestRuntimeData>& Pair : ActiveQuestsMap)
|
|
{
|
|
if (Pair.Value.State == EQuestState::InProgress && Pair.Value.QuestAsset)
|
|
{
|
|
Result.Add(Pair.Value.QuestAsset);
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
TArray<UQuestAsset*> UQuestManager::GetCompletedQuests() const
|
|
{
|
|
TArray<UQuestAsset*> Result;
|
|
for (const TPair<int32, FQuestRuntimeData>& Pair : ActiveQuestsMap)
|
|
{
|
|
if (Pair.Value.State == EQuestState::Completed && Pair.Value.QuestAsset)
|
|
{
|
|
Result.Add(Pair.Value.QuestAsset);
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
bool UQuestManager::GetQuestProgress(int32 QuestID, TArray<FQuestProgress>& OutProgress) const
|
|
{
|
|
const FQuestRuntimeData* RuntimeData = ActiveQuestsMap.Find(QuestID);
|
|
if (RuntimeData)
|
|
{
|
|
OutProgress = RuntimeData->ObjectiveProgress;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool UQuestManager::CanAcceptQuest(UQuestAsset* QuestAsset) const
|
|
{
|
|
if (!QuestAsset)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 检查所有前置任务是否完成
|
|
for (int32 PrerequisiteID : QuestAsset->PrerequisiteQuestIDs)
|
|
{
|
|
if (!CompletedQuestIDs.Contains(PrerequisiteID))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
TArray<FQuestSaveData> UQuestManager::GetQuestSaveData() const
|
|
{
|
|
TArray<FQuestSaveData> SaveDataArray;
|
|
|
|
for (const TPair<int32, FQuestRuntimeData>& Pair : ActiveQuestsMap)
|
|
{
|
|
FQuestSaveData SaveData;
|
|
SaveData.QuestID = Pair.Key;
|
|
SaveData.QuestState = Pair.Value.State;
|
|
|
|
// 保存目标进度
|
|
for (const FQuestProgress& Progress : Pair.Value.ObjectiveProgress)
|
|
{
|
|
SaveData.ObjectiveProgress.Add(Progress.CurrentProgress);
|
|
SaveData.ObjectiveCompleted.Add(Progress.bCompleted);
|
|
}
|
|
//设置追踪状态
|
|
if (FollowingQuestIDs.Contains(Pair.Key))
|
|
{
|
|
SaveData.bFollowing = true;
|
|
}
|
|
else
|
|
{
|
|
SaveData.bFollowing = false;
|
|
}
|
|
SaveDataArray.Add(SaveData);
|
|
}
|
|
|
|
return SaveDataArray;
|
|
}
|
|
|
|
void UQuestManager::LoadFromSaveData(const TArray<FQuestSaveData>& SaveData)
|
|
{
|
|
// 清空现有数据
|
|
ActiveQuestsMap.Empty();
|
|
CompletedQuestIDs.Empty();
|
|
FollowingQuestIDs.Empty();
|
|
|
|
LoadAllQuests();
|
|
|
|
for (const FQuestSaveData& Data : SaveData)
|
|
{
|
|
if (Data.QuestState == EQuestState::Completed)
|
|
{
|
|
CompletedQuestIDs.Add(Data.QuestID);
|
|
}
|
|
else if (Data.QuestState == EQuestState::InProgress)
|
|
{
|
|
for (auto questAsset: QuestAssets)
|
|
{
|
|
if (questAsset->QuestID == Data.QuestID)
|
|
{
|
|
FQuestRuntimeData RuntimeData = CreateRuntimeData(questAsset);
|
|
for (int i =0; i < RuntimeData.ObjectiveProgress.Num(); i++)
|
|
{
|
|
RuntimeData.ObjectiveProgress[i].CurrentProgress = Data.ObjectiveProgress[i];
|
|
RuntimeData.ObjectiveProgress[i].bCompleted = Data.ObjectiveCompleted[i];
|
|
}
|
|
|
|
RuntimeData.State = EQuestState::InProgress;
|
|
ActiveQuestsMap.Add(questAsset->QuestID, RuntimeData);
|
|
//添加追踪任务列表
|
|
if (Data.bFollowing)
|
|
{
|
|
FollowingQuestIDs.Add(questAsset->QuestID);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CheckAcceptableQuests();
|
|
}
|
|
|
|
void UQuestManager::CheckQuestCompletion(int32 QuestID)
|
|
{
|
|
FQuestRuntimeData* RuntimeData = ActiveQuestsMap.Find(QuestID);
|
|
if (!RuntimeData)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 检查所有目标是否完成
|
|
bool bAllCompleted = true;
|
|
for (const FQuestProgress& Progress : RuntimeData->ObjectiveProgress)
|
|
{
|
|
if (!Progress.bCompleted)
|
|
{
|
|
bAllCompleted = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 如果所有目标完成,自动完成任务
|
|
if (bAllCompleted)
|
|
{
|
|
CompleteQuest(QuestID);
|
|
}
|
|
}
|
|
|
|
FQuestRuntimeData UQuestManager::CreateRuntimeData(UQuestAsset* QuestAsset)
|
|
{
|
|
FQuestRuntimeData RuntimeData;
|
|
RuntimeData.QuestAsset = QuestAsset;
|
|
RuntimeData.State = EQuestState::NotStarted;
|
|
|
|
// 初始化目标进度
|
|
for (int32 i = 0; i < QuestAsset->Objectives.Num(); ++i)
|
|
{
|
|
FQuestProgress Progress;
|
|
Progress.CurrentProgress = 0;
|
|
Progress.bCompleted = false;
|
|
RuntimeData.ObjectiveProgress.Add(Progress);
|
|
}
|
|
|
|
return RuntimeData;
|
|
}
|