diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 1cd24582..61a4b505 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -84403,33 +84403,33 @@ 0x0000007100fd3bc8,sub_7100FD3BC8,48, 0x0000007100fd3bf8,sub_7100FD3BF8,92, 0x0000007100fd3c54,sub_7100FD3C54,156, -0x0000007100fd3cf0,ksys::qst::LightSpotInfo::ctor,40, -0x0000007100fd3d18,sub_7100FD3D18,20, -0x0000007100fd3d2c,sub_7100FD3D2C,340, -0x0000007100fd3e80,sub_7100FD3E80,52, -0x0000007100fd3eb4,ksys::qst::LightSpotInfo::init,3580, -0x0000007100fd4cb0,sub_7100FD4CB0,788, +0x0000007100fd3cf0,ksys::qst::LightSpotInfo::ctor,40,_ZN4ksys3qst9IndicatorC1EPNS0_4StepEPN4sead4HeapE +0x0000007100fd3d18,sub_7100FD3D18,20,_ZN4ksys3qst9IndicatorD1Ev +0x0000007100fd3d2c,sub_7100FD3D2C,340,_ZN4ksys3qst9Indicator8finalizeEv +0x0000007100fd3e80,sub_7100FD3E80,52,_ZN4ksys3qst9IndicatorD0Ev +0x0000007100fd3eb4,ksys::qst::LightSpotInfo::init,3580,_ZN4ksys3qst9Indicator4initEPN2al9ByamlIterEPN4sead22BufferedSafeStringBaseIcEE! +0x0000007100fd4cb0,sub_7100FD4CB0,788,_ZN4ksys3qst9Indicator13acquireActorsEv 0x0000007100fd4fc4,sub_7100FD4FC4,1312, -0x0000007100fd54e4,sub_7100FD54E4,52, -0x0000007100fd5518,sub_7100FD5518,52, -0x0000007100fd554c,sub_7100FD554C,20, -0x0000007100fd5560,sub_7100FD5560,52, +0x0000007100fd54e4,sub_7100FD54E4,52,_ZNK4ksys3qst9Indicator14sub_7100FD54E4Ei +0x0000007100fd5518,sub_7100FD5518,52,_ZNK4ksys3qst9Indicator14sub_7100FD5518Ei +0x0000007100fd554c,sub_7100FD554C,20,_ZN4ksys3qst14IndicatorActorD1Ev +0x0000007100fd5560,sub_7100FD5560,52,_ZN4ksys3qst14IndicatorActorD0Ev 0x0000007100fd5594,sinitQuestIndicatorString,268, 0x0000007100fd56a0,sub_7100FD56A0,100, 0x0000007100fd5704,sub_7100FD5704,108, -0x0000007100fd5770,QuestMgr::createInstance,216, +0x0000007100fd5770,QuestMgr::createInstance,216,_ZN4ksys3qst7Manager14createInstanceEPN4sead4HeapE! 0x0000007100fd5848,sub_7100FD5848,476, 0x0000007100fd5a24,sub_7100FD5A24,424, -0x0000007100fd5bcc,sub_7100FD5BCC,76, -0x0000007100fd5c18,QuestMgr::cleanUp,204, -0x0000007100fd5ce4,sub_7100FD5CE4,84, -0x0000007100fd5d38,QuestMgr::init,160, +0x0000007100fd5bcc,sub_7100FD5BCC,76,_ZN4ksys3qst7ManagerD1Ev +0x0000007100fd5c18,QuestMgr::cleanUp,204,_ZN4ksys3qst7Manager7cleanUpEv +0x0000007100fd5ce4,sub_7100FD5CE4,84,_ZN4ksys3qst7ManagerD0Ev +0x0000007100fd5d38,QuestMgr::init,160,_ZN4ksys3qst7Manager4initEPN4sead4HeapE 0x0000007100fd5dd8,QuestMgr::calc,492, 0x0000007100fd5fc4,QuestMgr::setUpQuests,1052, 0x0000007100fd63e0,QuestMgr::x_0,4212, 0x0000007100fd7454,QuestMgr::a,12, 0x0000007100fd7460,sub_7100FD7460,308, -0x0000007100fd7594,QuestMgr::__auto3,124, +0x0000007100fd7594,QuestMgr::__auto3,124,_ZNK4ksys3qst7Manager12isQuestActorEPNS_3act5ActorE 0x0000007100fd7610,QuestMgr::__auto1,128, 0x0000007100fd7690,sub_7100FD7690,32, 0x0000007100fd76b0,QuestMgr::__auto2,36, @@ -84437,29 +84437,29 @@ 0x0000007100fd7820,sub_7100FD7820,120, 0x0000007100fd7898,QuestMgr::stuffPrepareFirstTimeGenStage,24, 0x0000007100fd78b0,sub_7100FD78B0,72, -0x0000007100fd78f8,sub_7100FD78F8,280, -0x0000007100fd7a10,QuestMgr::__auto4,116, -0x0000007100fd7a84,QuestMgr::__auto0,172, -0x0000007100fd7b30,sub_7100FD7B30,16, -0x0000007100fd7b40,QuestMgr::setQuestStep,624, -0x0000007100fd7db0,QuestMgr::setQuestStepFromEvent,20, +0x0000007100fd78f8,sub_7100FD78F8,280,_ZN4ksys3qst7Manager14sub_7100FD78F8Ev! +0x0000007100fd7a10,QuestMgr::__auto4,116,_ZNK4ksys3qst7Manager5auto4EPNS_3act5ActorE +0x0000007100fd7a84,QuestMgr::__auto0,172,_ZN4ksys3qst7Manager5auto0EPNS_3act5ActorE? +0x0000007100fd7b30,sub_7100FD7B30,16,_ZN4ksys3qst7Manager14sub_7100FD7B30ERKN4sead14SafeStringBaseIcEES6_b +0x0000007100fd7b40,QuestMgr::setQuestStep,624,_ZN4ksys3qst7Manager12setQuestStepERKN4sead14SafeStringBaseIcEES6_bbb? +0x0000007100fd7db0,QuestMgr::setQuestStepFromEvent,20,_ZN4ksys3qst7Manager21setQuestStepFromEventERKN4sead14SafeStringBaseIcEES6_bb 0x0000007100fd7dc4,sinitQuestManagerStrings,680, -0x0000007100fd806c,ksys::qst::Quest::ctor,472, -0x0000007100fd8244,sub_7100FD8244,220, +0x0000007100fd806c,ksys::qst::Quest::ctor,472,_ZN4ksys3qst5QuestC1ERKN4sead14SafeStringBaseIcEEPNS2_4HeapE? +0x0000007100fd8244,sub_7100FD8244,220,_ZN4ksys3qst5QuestD1Ev? 0x0000007100fd8320,sub_7100FD8320,220, 0x0000007100fd83fc,ksys::qst::Quest::init,3032, -0x0000007100fd8fd4,ksys::qst::Quest::initFlags,496, +0x0000007100fd8fd4,ksys::qst::Quest::initFlags,496,_ZN4ksys3qst5Quest9initFlagsEPNS_3gdt7ManagerE 0x0000007100fd91c4,ksys::qst::Quest::x_0,1248, -0x0000007100fd96a4,ksys::qst::Quest::x_3,176, +0x0000007100fd96a4,ksys::qst::Quest::x_3,176,_ZN4ksys3qst5Quest3x_3Ev 0x0000007100fd9754,ksys::qst::Quest::x_4,20, 0x0000007100fd9768,ksys::qst::Quest::x_5,908, -0x0000007100fd9af4,ksys::qst::Quest::x_6,56, -0x0000007100fd9b2c,ksys::qst::Quest::x_7,60, +0x0000007100fd9af4,ksys::qst::Quest::x_6,56,_ZNK4ksys3qst5Quest3x_6EPNS_3act5ActorE +0x0000007100fd9b2c,ksys::qst::Quest::x_7,60,_ZNK4ksys3qst5Quest3x_7Ev 0x0000007100fd9b68,ksys::qst::Quest::flagStuff,476, -0x0000007100fd9d44,ksys::qst::Quest::x_1,124, -0x0000007100fd9dc0,ksys::qst::Quest::setField31,12, -0x0000007100fd9dcc,ksys::qst::Quest::x_8,80, -0x0000007100fd9e1c,ksys::qst::Quest::x_9,56, +0x0000007100fd9d44,ksys::qst::Quest::x_1,124,_ZNK4ksys3qst5Quest3x_1Ev +0x0000007100fd9dc0,ksys::qst::Quest::setField31,12,_ZN4ksys3qst5Quest10setField31Ev +0x0000007100fd9dcc,ksys::qst::Quest::x_8,80,_ZN4ksys3qst5Quest3x_8EPNS_3act5ActorE +0x0000007100fd9e1c,ksys::qst::Quest::x_9,56,_ZN4ksys3qst5Quest3x_9EPNS_3act5ActorE 0x0000007100fd9e54,ksys::qst::Quest::x_10,1820, 0x0000007100fda570,_ZN4sead12CalendarTime21makeWeekDayNameLabel_EPNS_22BufferedSafeStringBaseIcEENS0_4WeekE,72, 0x0000007100fda5b8,ksys::qst::Quest::formatQLNameKey,64, @@ -84467,9 +84467,9 @@ 0x0000007100fda678,sub_7100FDA678,188, 0x0000007100fda734,sub_7100FDA734,88, 0x0000007100fda78c,sub_7100FDA78C,140, -0x0000007100fda818,ksys::qst::Quest::x_11,68, +0x0000007100fda818,ksys::qst::Quest::x_11,68,_ZN4ksys3qst5Quest4x_11Ev 0x0000007100fda85c,sinitQuestStrings2,680, -0x0000007100fdab04,ksys::qst::Step::ctor,168, +0x0000007100fdab04,ksys::qst::Step::ctor,168,_ZN4ksys3qst4StepC1EPPKhPN4sead4HeapE? 0x0000007100fdabac,sub_7100FDABAC,268, 0x0000007100fdacb8,sub_7100FDACB8,36, 0x0000007100fdacdc,sub_7100FDACDC,204, @@ -84477,14 +84477,14 @@ 0x0000007100fdb230,sub_7100FDB230,244, 0x0000007100fdb324,sub_7100FDB324,344, 0x0000007100fdb47c,sub_7100FDB47C,188, -0x0000007100fdb538,sub_7100FDB538,604, +0x0000007100fdb538,sub_7100FDB538,604,_ZNK4ksys3qst4Step14sub_7100FDB538EPNS_3act5ActorERKN4sead14SafeStringBaseIcEE? 0x0000007100fdb794,sub_7100FDB794,16, 0x0000007100fdb7a4,sub_7100FDB7A4,248, -0x0000007100fdb89c,sub_7100FDB89C,168, -0x0000007100fdb944,ksys::qst::Step::initActorData,148, -0x0000007100fdb9d8,ksys::qst::Step::initLightSpotInfo,168, +0x0000007100fdb89c,sub_7100FDB89C,168,_ZNK4ksys3qst4Step14sub_7100FDB89CEPNS_3act5ActorE +0x0000007100fdb944,ksys::qst::Step::initActorData,148,_ZN4ksys3qst4Step13initActorDataEjPN4sead22BufferedSafeStringBaseIcEE +0x0000007100fdb9d8,ksys::qst::Step::initLightSpotInfo,168,_ZN4ksys3qst4Step13initIndicatorEjPN4sead22BufferedSafeStringBaseIcEE? 0x0000007100fdba80,ksys::qst::Step::init,2084, -0x0000007100fdc2a4,sub_7100FDC2A4,324, +0x0000007100fdc2a4,sub_7100FDC2A4,324,_ZN4ksys3qst4Step14sub_7100FDC2A4EPN2al9ByamlIterE? 0x0000007100fdc3e8,sub_7100FDC3E8,244, 0x0000007100fdc4dc,sub_7100FDC4DC,280, 0x0000007100fdc5f4,sub_7100FDC5F4,20, @@ -95477,15 +95477,15 @@ 0x00000071012b43d0,sub_71012B43D0,292, 0x00000071012b44f4,sub_71012B44F4,340, 0x00000071012b4648,sinitKsysQstActorData,268, -0x00000071012b4754,ksys::qst::ActorData::ctor,28, -0x00000071012b4770,sub_71012B4770,148, -0x00000071012b4804,sub_71012B4804,156, -0x00000071012b48a0,sub_71012B48A0,52, -0x00000071012b48d4,sub_71012B48D4,48, -0x00000071012b4904,ksys::qst::ActorData::init,608, -0x00000071012b4b64,sub_71012B4B64,52, -0x00000071012b4b98,nullsub_4778,4, -0x00000071012b4b9c,j__ZdlPv_1293,4, +0x00000071012b4754,ksys::qst::ActorData::ctor,28,_ZN4ksys3qst9ActorDataC1EPN4sead4HeapE +0x00000071012b4770,sub_71012B4770,148,_ZN4ksys3qst9ActorDataD1Ev +0x00000071012b4804,sub_71012B4804,156,_ZN4ksys3qst9ActorDataD0Ev +0x00000071012b48a0,sub_71012B48A0,52,_ZNK4ksys3qst9ActorData9getTargetEi +0x00000071012b48d4,sub_71012B48D4,48,_ZN4ksys3qst9ActorData17disableAllTargetsEv +0x00000071012b4904,ksys::qst::ActorData::init,608,_ZN4ksys3qst9ActorData4initEPN2al9ByamlIterEPN4sead22BufferedSafeStringBaseIcEE? +0x00000071012b4b64,sub_71012B4B64,52,_ZN4ksys3qst9ActorData16enableAllTargetsEv +0x00000071012b4b98,nullsub_4778,4,_ZN4ksys3qst12CameraTargetD1Ev +0x00000071012b4b9c,j__ZdlPv_1293,4,_ZN4ksys3qst12CameraTargetD0Ev 0x00000071012b4ba0,sub_71012B4BA0,840, 0x00000071012b4ee8,_ZN4gsys13LightProbeMgr4Grid5setupEv,740, 0x00000071012b51cc,sub_71012B51CC,76, diff --git a/src/KingSystem/CMakeLists.txt b/src/KingSystem/CMakeLists.txt index c387306f..80c07ae8 100644 --- a/src/KingSystem/CMakeLists.txt +++ b/src/KingSystem/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory(Framework) add_subdirectory(Map) add_subdirectory(Mii) add_subdirectory(Physics) +add_subdirectory(Quest) add_subdirectory(Sound) add_subdirectory(System) add_subdirectory(Terrain) diff --git a/src/KingSystem/Quest/CMakeLists.txt b/src/KingSystem/Quest/CMakeLists.txt new file mode 100644 index 00000000..5a292618 --- /dev/null +++ b/src/KingSystem/Quest/CMakeLists.txt @@ -0,0 +1,12 @@ +target_sources(uking PRIVATE + qstActorData.cpp + qstActorData.h + qstIndicator.cpp + qstIndicator.h + qstManager.cpp + qstManager.h + qstQuest.cpp + qstQuest.h + qstStep.cpp + qstStep.h +) diff --git a/src/KingSystem/Quest/qstActorData.cpp b/src/KingSystem/Quest/qstActorData.cpp new file mode 100644 index 00000000..c5f0d041 --- /dev/null +++ b/src/KingSystem/Quest/qstActorData.cpp @@ -0,0 +1,79 @@ +#include "KingSystem/Quest/qstActorData.h" +#include "KingSystem/Utils/Byaml/Byaml.h" + +namespace ksys::qst { + +CameraTarget::~CameraTarget() = default; + +ActorData::ActorData(sead::Heap* heap) { + this->heap = heap; +} + +ActorData::~ActorData() { + for (int i = 0; i < targets.size(); ++i) { + /// @bug The object is destructed twice (UB). + std::destroy_at(targets[i]); + delete targets[i]; + } + targets.freeBuffer(); +} + +bool ActorData::init(al::ByamlIter* iter, sead::BufferedSafeString* out_message) { + if (iter == nullptr) + return true; + + sead::FixedSafeString<16> key("CameraTargets"); + al::ByamlIter target_iter; + + if (!iter->tryGetIterByKey(&target_iter, key.cstr())) + return true; + + if (!targets.tryAllocBuffer(target_iter.getSize(), heap)) { + // Failed to setup photo target storage buffer. (Insufficient memory?) + out_message->format("写真対象格納バッファの設定に失敗しました。(メモリ不足?)"); + return false; + } + + for (int i = 0; i < target_iter.getSize(); ++i) { + const char* string = nullptr; + bool result = target_iter.tryGetStringByIndex(&string, i); + + if (string == nullptr || !result) { + // Failed to get the photo target (%d). + out_message->format("写真対象(%d)の取得に失敗しました。", i); + return false; + } + + auto* target = new (heap, std::nothrow_t()) CameraTarget(); + if (target == nullptr) { + // Failed to allocate photo target information (%d). + out_message->format("写真対象情報(%d)の生成に失敗しました。"); + return false; + } + + target->enabled = false; + target->name = string; + targets.pushBack(target); + } + + return true; +} + +const CameraTarget* ActorData::getTarget(int idx) const { + if (targets.size() < 1 || idx < 0 || idx >= targets.size()) + return nullptr; + return targets[idx]; +} + +void ActorData::disableAllTargets() { + for (int i = 0; i < targets.size(); ++i) + targets[i]->enabled = false; +} + +void ActorData::enableAllTargets() { + for (int i = 0; i < targets.size(); ++i) { + targets[i]->enabled = true; + } +} + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstActorData.h b/src/KingSystem/Quest/qstActorData.h new file mode 100644 index 00000000..c6e3ab37 --- /dev/null +++ b/src/KingSystem/Quest/qstActorData.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/Utils/Types.h" + +namespace al { +class ByamlIter; +} + +namespace ksys::qst { + +struct CameraTarget { + virtual ~CameraTarget(); + bool enabled; + sead::SafeString name; +}; +KSYS_CHECK_SIZE_NX150(CameraTarget, 0x20); + +struct ActorData { + ActorData(sead::Heap* heap); + virtual ~ActorData(); + + bool init(al::ByamlIter* iter, sead::BufferedSafeString* out_message); + const CameraTarget* getTarget(int idx) const; + void disableAllTargets(); + void enableAllTargets(); + + sead::PtrArray targets; + sead::Heap* heap; +}; +KSYS_CHECK_SIZE_NX150(ActorData, 0x20); + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstIndicator.cpp b/src/KingSystem/Quest/qstIndicator.cpp new file mode 100644 index 00000000..eff0585b --- /dev/null +++ b/src/KingSystem/Quest/qstIndicator.cpp @@ -0,0 +1,194 @@ +#include "KingSystem/Quest/qstIndicator.h" +#include "KingSystem/Quest/qstStep.h" + +namespace ksys::qst { + +Indicator::Indicator(Step* step, sead::Heap* heap) { + this->heap = heap; + this->step = step; +} + +Indicator::~Indicator() { + finalize(); +} + +// NON_MATCHING: Confusing control flow +bool Indicator::init(al::ByamlIter* iter, sead::BufferedSafeString* out_message) { + if (!iter->isValid()) { + // Step (%s) is invalid data. + out_message->format("ステップ(%s)は無効なデータです。", step->name); + return false; + } + + sead::FixedSafeString<32> actor_key("IndicatorActors"); + sead::FixedSafeString<32> param_key(""); + al::ByamlIter actor_iter; + if (iter->tryGetIterByKey(&actor_iter, actor_key.cstr())) { + if (!actor_iter.isValid()) { + // Parameter [%s] for step (%s) is invalid data. + out_message->format("ステップ(%s)のパラメータ [%s] は無効なデータです。", step->name, + actor_key.cstr()); + return false; + } + + int size = actor_iter.getSize(); + if (size >= 1) { + if (!actors.tryAllocBuffer(size, heap, 8)) { + // Failed to set the actor indicator storage buffer for step (%s). (Insufficient + // memory?) + out_message->format( + "ステップ(%s)のアクター光点格納バッファの設定に失敗しました。(メモリ不足?)", + step->name); + return false; + } + + al::ByamlIter param_iter; + for (int i = 0; i < size; ++i) { + if (!actor_iter.tryGetIterByIndex(¶m_iter, i)) { + // Failed to get the actor indicator (%d) for step (%s). + out_message->format("ステップ(%s)のアクター光点(%d)の取得に失敗しました。", + step->name, i); + return false; + } + if (!param_iter.isValid()) { + // Actor indicator (%d) in step (%s) is invalid data. + out_message->format("ステップ(%s)のアクター光点(%d)は無効なデータです。", + step->name, i); + return false; + } + + bool has_far = false; + const char* instance_name = &sead::SafeString::cNullChar; + sead::Vector3f location = sead::Vector3f::zero; + const char* name = &sead::SafeString::cNullChar; + const char* off_flag = &sead::SafeString::cNullChar; + bool is_remains = false; + + param_key.format("HasFar"); + if (!param_iter.tryGetBoolByKey(&has_far, param_key.cstr())) { + continue; + } + + param_key.format("InstanceName"); + if (!param_iter.tryGetStringByKey(&instance_name, param_key.cstr())) { + // Failed to get parameter [%s] of actor indicator (%d) for step (%s). + out_message->format( + "ステップ(%s)のアクター光点(%d)のパラメータ [%s] の取得に失敗しました。", + step->name, i, param_key.cstr()); + break; + } + + param_key.format("Location"); + if (!al::tryGetByamlV3f(&location, param_iter, param_key.cstr())) { + // Failed to get parameter [%s] of actor indicator (%d) for step (%s). + out_message->format( + "ステップ(%s)のアクター光点(%d)のパラメータ [%s] の取得に失敗しました。", + step->name, i, param_key.cstr()); + break; + } + + param_key.format("Name"); + if (!param_iter.tryGetStringByKey(&name, param_key.cstr())) { + // Failed to get parameter [%s] of actor indicator (%d) for step (%s). + out_message->format( + "ステップ(%s)のアクター光点(%d)のパラメータ [%s] の取得に失敗しました。", + step->name, i, param_key.cstr()); + break; + } + + param_key.format("OffFlag"); + if (!param_iter.tryGetStringByKey(&off_flag, param_key.cstr())) { + // Failed to get parameter [%s] of actor indicator (%d) for step (%s). + out_message->format( + "ステップ(%s)のアクター光点(%d)のパラメータ [%s] の取得に失敗しました。", + step->name, i, param_key.cstr()); + break; + } + + param_key.format("IsRemains"); + param_iter.tryGetBoolByKey(&is_remains, param_key.cstr()); + + IndicatorActor* actor = actors.emplaceBack(); + actor->has_far = has_far; + actor->instance_name = instance_name; + actor->location = location; + actor->name = name; + actor->off_flag = off_flag; + actor->is_remains = is_remains; + actor->hash_instance_name = sead::HashCRC32::calcStringHash(instance_name); + actor->hash_name = sead::HashCRC32::calcStringHash(name); + + if (actor == nullptr) { + // Failed to generate actor indicator information (%d) for step (%s). + out_message->format("ステップ(%s)のアクター光点情報(%d)の生成に失敗しました。", + step->name, i); + break; + } + } + } + } + + sead::FixedSafeString<32> loc_key("IndicatorLocations"); + al::ByamlIter loc_iter; + if (iter->tryGetIterByKey(&loc_iter, loc_key.cstr())) { + if (!loc_iter.isValid()) { + // Parameter [%s] for step (%s) is invalid data. + out_message->format("ステップ(%s)のパラメータ [%s] は無効なデータです。", step->name, + loc_key.cstr()); + return false; + } + } + + acquireActors(); + return true; +} + +void Indicator::finalize() { + actors.freeBuffer(); + _28.freeBuffer(); +} + +void Indicator::acquireActors() { + sead::FixedSafeString<64> s; + + for (int i = 0; i < actors.size(); ++i) { + IndicatorActor* actor = actors[i]; + if (actor == nullptr) + continue; + + act::BaseProc* proc = Manager::sub_7100FD5848(actor->name, actor->instance_name); + if (proc != nullptr) { + if (actor->is_remains == 1) { + actor->link.acquire(proc, false); + } + continue; + } + + if (actor->has_far) { + s = actor->name; + s.append("_Far"); + proc = Manager::sub_7100FD5848(s, actor->instance_name); + if (proc != nullptr) { + if (actor->is_remains == 1) { + actor->link.acquire(proc, false); + } + } + } + } +} + +const IndicatorActor* Indicator::sub_7100FD54E4(int idx) const { + if (actors.size() < 1 || idx < 0 || idx >= actors.size()) + return nullptr; + return actors[idx]; +} + +const IndicatorActor* Indicator::sub_7100FD5518(int idx) const { + if (_28.size() < 1 || idx < 0 || idx >= _28.size()) + return nullptr; + return _28[idx]; +} + +IndicatorActor::~IndicatorActor() = default; + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstIndicator.h b/src/KingSystem/Quest/qstIndicator.h new file mode 100644 index 00000000..b4482c70 --- /dev/null +++ b/src/KingSystem/Quest/qstIndicator.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include "KingSystem/Quest/qstManager.h" +#include "KingSystem/Utils/Byaml/Byaml.h" + +namespace ksys::qst { + +struct Step; + +struct IndicatorActor { + IndicatorActor(); + virtual ~IndicatorActor(); + + act::BaseProcLink link; + bool has_far; + const char* instance_name; + sead::Vector3f location; + const char* name; + const char* off_flag; + u32 is_remains; + u32 hash_name = 0; + u32 hash_instance_name = 0; + void* _58; +}; + +struct Indicator { + Indicator(Step* step, sead::Heap* heap); + virtual ~Indicator(); + + bool init(al::ByamlIter* iter, sead::BufferedSafeString* out_message); + void finalize(); + + void acquireActors(); + void sub_7100FD4FC4(); + const IndicatorActor* sub_7100FD54E4(int idx) const; + const IndicatorActor* sub_7100FD5518(int idx) const; + + sead::ObjArray actors; + sead::ObjArray _28; + sead::Heap* heap; + Step* step; +}; + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstManager.cpp b/src/KingSystem/Quest/qstManager.cpp new file mode 100644 index 00000000..a5929790 --- /dev/null +++ b/src/KingSystem/Quest/qstManager.cpp @@ -0,0 +1,139 @@ + +#include "KingSystem/Quest/qstManager.h" +#include "KingSystem/Quest/qstActorData.h" +#include "KingSystem/Utils/HeapUtil.h" +#include "KingSystem/Utils/SafeDelete.h" + +namespace ksys::qst { + +SEAD_SINGLETON_DISPOSER_IMPL(Manager) + +Manager::~Manager() { + cleanUp(); + util::safeDeleteHeap(mHeap); +} + +void Manager::init(sead::Heap* heap) { + if (sDisable) + return; + + mHeap = util::DualHeap::tryCreate(0x99999, "QuestHeap", heap, util::getDebugHeap(), 8, + sead::Heap::cHeapDirection_Forward, true); + cleanUp(); + + _e4 = -0x51; + mFlags = 0; + _28 = _2c; + _2c = 0; + _30 = 0; +} + +void Manager::cleanUp() { + _44 = 0; + _48.freeBuffer(); + mQuests.freeBuffer(); + mHandle.unloadAndResetUnitFlag20000(); +} + +bool Manager::isQuestActor(act::Actor* actor) const { + for (int i = 0; i < mQuests.size(); ++i) { + const auto* quest = mQuests[i]; + if (quest->x_6(actor)) + return true; + } + return false; +} + +// NON_MATCHING: leftovers from a stripped debug function +void Manager::auto0(act::Actor* actor) { + if (actor == nullptr) + return; + + for (int i = 0; i < mQuests.size(); ++i) { + Quest* quest = mQuests[i]; + if (quest->_c != 2 && quest->flagStuff()) + quest->x_9(actor); + } +} + +bool Manager::auto4(act::Actor* actor) const { + auto end = mQuests.end(); + for (auto it = mQuests.begin(); it != end; ++it) { + if (it->_c != 2 && it->flagStuff() && !it->x_8(actor)) + return false; + } + return true; +} + +// NON_MATCHING: loops are nonmatching +bool Manager::sub_7100FD78F8() { + s32 size = mQuests.size(); + u32 data_count = 0; + + for (int i = 0; i < size; ++i) { + data_count += mQuests[i]->_148; + } + + if (data_count == 0) + return true; + if (!_48.tryAllocBuffer(data_count, mHeap, 8)) + return false; + + for (int i = 0; i < size; ++i) { + s32 num2 = mQuests[i]->_148; + for (int j = 0; j < num2; ++j) { + ActorData* data = mQuests[i]->sub_7100FDA5F8(j); + if (data != nullptr) { + _48.pushBack(data); + } + } + } + return true; +} + +bool Manager::sub_7100FD7B30(const sead::SafeString& quest_name, const sead::SafeString& step_name, + bool setAocVersionFlag1) { + return setQuestStep(quest_name, step_name, false, false, setAocVersionFlag1); +} + +bool Manager::setQuestStepFromEvent(const sead::SafeString& quest_name, + const sead::SafeString& step_name, bool force_run_telop, + bool setAocVersionFlag1) { + return setQuestStep(quest_name, step_name, true, force_run_telop, setAocVersionFlag1); +} + +// NON_MATCHING: quest is dereferenced several times +bool Manager::setQuestStep(const sead::SafeString& quest_name, const sead::SafeString& step_name, + bool copy_name, bool force_run_telop, bool setAocVersionFlag1) { + u32 hash = sead::HashCRC32::calcStringHash(quest_name.cstr()); + Quest* quest; + for (auto& q : mQuests) { + if (q._c - 1 <= 1 && q.mNameHash == hash) { + quest = &q; + break; + } + } + if (quest == nullptr) + return false; + + quest->setField31(); + + quest->_e8.copy(step_name); + + quest->_e0 = false; + quest->mForceRunTelop = false; + + if (copy_name) { + quest->_e0 = true; + const char* x = quest->x_11(); + if (step_name.isEmpty()) + quest->_e8.copy(sead::SafeString(x)); + } + if (force_run_telop) + quest->mForceRunTelop = true; + if (setAocVersionFlag1) + quest->mAocVersionFlags |= 1; + return true; +} + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstManager.h b/src/KingSystem/Quest/qstManager.h new file mode 100644 index 00000000..178e6732 --- /dev/null +++ b/src/KingSystem/Quest/qstManager.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/Quest/qstQuest.h" +#include "KingSystem/Resource/resHandle.h" +#include "agl/Utils/aglParameter.h" + +namespace ksys::qst { + +struct Quest; + +class Manager { + SEAD_SINGLETON_DISPOSER(Manager) +public: + Manager(); + virtual ~Manager(); + + void init(sead::Heap* heap); + void cleanUp(); + + void auto0(act::Actor* actor); + bool auto4(act::Actor* actor) const; + + bool sub_7100FD78F8(); + + bool sub_7100FD7B30(const sead::SafeString& quest_name, const sead::SafeString& step_name, + bool setAocVersionFlag1); + bool setQuestStepFromEvent(const sead::SafeString& quest_name, + const sead::SafeString& step_name, bool force_run_telop, + bool setAocVersionFlag1); + bool setQuestStep(const sead::SafeString& quest_name, const sead::SafeString& step_name, + bool copy_name, bool force_run_telop, bool setAocVersionFlag1); + + bool isQuestActor(act::Actor* actor) const; + static act::BaseProc* sub_7100FD5848(const sead::SafeString& s1, const sead::SafeString& s2); + +private: + u32 _28; + u32 _2c; + u32 _30; + void* temp; + u32 temp2; + u32 _44; + sead::PtrArray _48; + u32 _58; + u32 temp3; + u32 temp4; + res::Handle mHandle; + sead::ObjArray mQuests; + sead::Heap* mHeap = nullptr; + u16 mFlags; + u32 _e4; + s32 _e8 = -1; + u32 _d0 = 0; + + static bool sDisable; +}; + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstQuest.cpp b/src/KingSystem/Quest/qstQuest.cpp new file mode 100644 index 00000000..96e48ed4 --- /dev/null +++ b/src/KingSystem/Quest/qstQuest.cpp @@ -0,0 +1,117 @@ +#include "KingSystem/Quest/qstQuest.h" +#include "agl/Utils/aglParameter.h" + +namespace ksys::qst { + +// chunks missing +Quest::~Quest() { + mSteps.freeBuffer(); +} + +// NON_MATCHING +Quest::Quest(const sead::SafeString& name, sead::Heap* heap) : mName(name), mHeap(heap) { + _8 = 0; + _c = 0; + _10 = 0; + mNameHash = agl::utl::ParameterBase::calcHash(mName); + mAocVersionFlags = 0; +} + +void Quest::initFlags(gdt::Manager* gdm) { + if (gdm == nullptr) + return; + + mReady = gdm->getBoolHandle([&] { + sead::FixedSafeString<64> ready; + ready.format("%s_Ready", mName.cstr()); + return ready; + }()); + + mCancelled = gdm->getBoolHandle([&] { + sead::FixedSafeString<64> cancelled; + cancelled.format("%s_Cancelled", mName.cstr()); + return cancelled; + }()); + + switch (mQuestDependencyFlagType) { + default: + mDependencyFlag = gdt::InvalidHandle; + break; + case 0: + mDependencyFlag = gdm->getBoolHandle(mQuestDependencyFlag); + break; + case 1: + mDependencyFlag = gdm->getF32Handle(mQuestDependencyFlag); + break; + case 2: + mDependencyFlag = gdm->getS32Handle(mQuestDependencyFlag); + break; + } +} + +void Quest::setField31() { + _31 = 1; +} + +bool Quest::x_1() const { + bool result = false; + + if (gdt::Manager::instance() == nullptr || mCancelled == gdt::InvalidHandle) + return result; + + gdt::Manager::instance()->getBool(mCancelled, &result, true); + return result; +} + +void Quest::x_3() { + if (_c == 1 || _c == 2) + return; + + auto handle = mReady; + if (handle != ksys::gdt::InvalidHandle) { + bool result = false; + auto* gdm = gdt::Manager::instance(); + if (gdm != nullptr) { + if (gdm->getBool(handle, &result, true); !result) + gdm->setBool(true, handle); + } + } + _8 = _c; + _c = 1; + _10 = 0; +} + +bool Quest::x_6(act::Actor* actor) const { + if (!isStepUnderSize() || !mSteps[_140]->attention_off) + return false; + + return mSteps[_140]->sub_7100FDB89C(actor); +} + +bool Quest::x_7() const { + if (!isStepUnderSize()) + return false; + + return mSteps[_140]->attention_off; +} + +bool Quest::x_8(act::Actor* actor) { + if (isStepUnderCapacity()) + mSteps[_140]->sub_7100FDB538(actor, mName); + + return true; +} + +void Quest::x_9(act::Actor* actor) { + if (isStepUnderCapacity()) + mSteps[_140]->sub_7100FDB794(actor); +} + +const char* Quest::x_11() { + if (!isNextStepUnderSize()) + return &sead::SafeString::cNullChar; + + return mSteps[_140 + 1]->name; +} + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstQuest.h b/src/KingSystem/Quest/qstQuest.h new file mode 100644 index 00000000..11e5087d --- /dev/null +++ b/src/KingSystem/Quest/qstQuest.h @@ -0,0 +1,73 @@ +#pragma once + +#include "KingSystem/GameData/gdtManager.h" +#include "KingSystem/Quest/qstStep.h" +#include "KingSystem/Resource/resHandle.h" +#include "KingSystem/Utils/Byaml/Byaml.h" + +namespace ksys::qst { + +struct Step; + +struct Quest { +public: + Quest(const sead::SafeString& name, sead::Heap* heap); + virtual ~Quest(); + + bool isStepUnderCapacity() const { return (_140 >= 0 && _140 < mSteps.capacity()); } + bool isStepUnderSize() const { return (_140 >= 0 && _140 < mSteps.size()); } + bool isNextStepUnderSize() const { return (_140 + 1 >= 0 && _140 + 1 < mSteps.size()); } + + bool x_6(act::Actor* actor) const; + void initFlags(gdt::Manager* gdm); + bool flagStuff() const; + void setField31(); + ActorData* sub_7100FDA5F8(int idx); + + bool x_1() const; + void x_3(); + bool x_7() const; + bool x_8(act::Actor* actor); + void x_9(act::Actor* actor); + void x_10(const sead::SafeString& s); + const char* x_11(); + + u32 _8 = 0; + u32 _c = 0; + u32 _10; + + gdt::FlagHandle mReady = gdt::InvalidHandle; + gdt::FlagHandle mCancelled = gdt::InvalidHandle; + gdt::FlagHandle mDependencyFlag = gdt::InvalidHandle; + const char* mQuestDependencyFlag = &sead::SafeString::cNullChar; + + u32 mQuestDependencyFlagType = 3; + + u32 mNameHash = 0; + u8 mNotPostNote = 0; + u8 _31 = 0; + u8 _32 = 0; + u8 _33 = 0; + const char* mLocation = &sead::SafeString::cNullChar; + sead::FixedSafeString<64> mName; + const char* mOrderer = &sead::SafeString::cNullChar; + sead::ObjArray mSteps; + const char* mType = &sead::SafeString::cNullChar; + sead::Heap* mHeap; + al::ByamlIter* mDataIter = nullptr; + u32 mAocVersionFlags = 0; + u32 _dc = 0; + u8 _e0 = 0; + u8 mForceRunTelop = 0; + u8 _e2 = 0; + u8 _e3 = 0; + u32 _e4 = 0; + sead::FixedSafeString<64> _e8; + s32 _140 = -1; // current or next step? + u8 _144 = 0; + u32 _148 = 0; + u32 _14c; + void* _150 = nullptr; +}; + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstStep.cpp b/src/KingSystem/Quest/qstStep.cpp new file mode 100644 index 00000000..4eeada65 --- /dev/null +++ b/src/KingSystem/Quest/qstStep.cpp @@ -0,0 +1,97 @@ +#include "KingSystem/Quest/qstStep.h" +#include +#include "KingSystem/Quest/qstActorData.h" +#include "KingSystem/Quest/qstIndicator.h" + +namespace ksys::qst { + +// NON_MATCHING: regalloc +Step::Step(const u8** iter_data, sead::Heap* heap) : heap(heap) { + if (*iter_data != nullptr) { + iter = new (heap, std::nothrow_t()) al::ByamlIter(*iter_data); + } +} + +bool Step::sub_7100FDB89C(act::Actor* actor) const { + for (int i = 0; i < links.size(); ++i) { + if (!links[i]->link.hasProc()) + continue; + if (links[i]->link.hasProcById(actor)) + return true; + } + return false; +} + +bool Step::sub_7100FDB538(act::Actor* actor, const sead::SafeString& name) const { + if (actor == nullptr) + return false; + if (!_28) + return true; + + for (int i = 0; i < links.size(); ++i) { + sead::SafeString actName(actor->getName()); + sead::SafeString uniqName(actor->getUniqueName()); + if (actName != links[i]->name) + continue; + + if (uniqName != links[i]->unique_name) + continue; + + if (links[i]->sub_71012B43D0(actor, name)) { + return true; + } + } + return false; +} + +bool Step::initActorData([[maybe_unused]] u32 unused, sead::BufferedSafeString* out_message) { + if (actor_data != nullptr) { + // The photo object has already been created. + out_message->format("写真対象は既に作成されています。"); + return false; + } + + actor_data = new (heap, std::nothrow_t()) ActorData(heap); + if (actor_data == nullptr) { + // Due to insufficient memory, photo data could not be created. + out_message->format("メモリ不足のため、写真情報を作成できませんでした。"); + return false; + } + return actor_data->init(iter, out_message); +} + +bool Step::initIndicator([[maybe_unused]] u32 unused, sead::BufferedSafeString* out_message) { + if (indicator_info != nullptr) { + // The indicator information has already been created. + out_message->format("光点情報は既に作成されています。"); + return false; + } + + indicator_info = new (heap, std::nothrow_t()) Indicator(this, heap); + if (indicator_info == nullptr) { + // Due to insufficient memory, indicator information could not be created. + out_message->format("メモリ不足のため、光点情報を作成できませんでした。"); + return false; + } + return indicator_info->init(iter, out_message); +} + +bool Step::sub_7100FDC2A4(al::ByamlIter* iter) { + al::ByamlIter evt_iter; + al::ByamlIter trg_iter; + const char* value; + + if (!iter->tryGetIterByKey(&evt_iter, "TriggerEvents")) + return false; + + for (int i = 0; i < evt_iter.getSize(); ++i) { + if (evt_iter.tryGetIterByIndex(&trg_iter, i) && trg_iter.isValid() && + trg_iter.tryGetStringByKey(&value, "Trigger")) { + if (sead::SafeString("StepStart") == value) + return true; + } + } + return false; +} + +} // namespace ksys::qst diff --git a/src/KingSystem/Quest/qstStep.h b/src/KingSystem/Quest/qstStep.h new file mode 100644 index 00000000..551b3c92 --- /dev/null +++ b/src/KingSystem/Quest/qstStep.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/ActorSystem/actBaseProcLink.h" +#include "KingSystem/GameData/gdtFlagHandle.h" +#include "KingSystem/Utils/Byaml/Byaml.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::qst { + +struct ActorData; +struct Indicator; + +struct Step { + struct ActLink { + void* _0; + act::BaseProcLink link; + void* _18; + const char* name; + void* _28; + void* _30; + void* _38; + void* _40; + const char* unique_name; + + bool sub_71012B43D0(act::Actor* actor, const sead::SafeString& name) const; + }; + + Step(const u8** iter_data, sead::Heap* heap); + virtual ~Step(); + + bool sub_7100FDB89C(act::Actor* actor) const; + bool sub_7100FDB538(act::Actor* actor, const sead::SafeString& name) const; + bool sub_7100FDB794(act::Actor* actor) const; + bool initActorData(u32 unused, sead::BufferedSafeString* out_message); + bool initIndicator(u32 unused, sead::BufferedSafeString* out_message); + bool sub_7100FDC2A4(al::ByamlIter* iter); + + sead::ObjArray links; + u32 _28 = 0; + gdt::FlagHandle dep_flag = gdt::InvalidHandle; + const char* dep_flag_name = &sead::SafeString::cNullChar; + u32 _38 = 3; + u32 _3c = 0; + bool attention_off = false; + const char* message_name = &sead::SafeString::cNullChar; + const char* name = &sead::SafeString::cNullChar; + gdt::FlagHandle next_flag = gdt::InvalidHandle; + const char* next_flag_name = &sead::SafeString::cNullChar; + sead::Heap* heap = nullptr; + ActorData* actor_data = nullptr; + Indicator* indicator_info = nullptr; + al::ByamlIter* iter = nullptr; +}; +KSYS_CHECK_SIZE_NX150(Step, 0x88); + +} // namespace ksys::qst