diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 8da4fc34..2c2f7d3e 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -40497,19 +40497,19 @@ 0x0000007100683eec,AI_QueryBase::m8n,4,_ZN4ksys3act2ai5Query10loadParamsEv 0x0000007100683ef0,AI_Query_BranchByDyeColor::rtti1,204, 0x0000007100683fbc,AI_Query_BranchByDyeColor::rtti2,92, -0x0000007100684018,AI_QueryBase::m4r0,8,_ZN4ksys3act2ai5Query2m4Ev -0x0000007100684020,AI_QueryBase::m5r0,8,_ZN4ksys3act2ai5Query2m5Ev +0x0000007100684018,AI_QueryBase::m4r0,8,_ZN4ksys3act2ai5Query14hasPreDeleteCbEv +0x0000007100684020,AI_QueryBase::m5r0,8,_ZN4ksys3act2ai5Query23hasUpdateForPreDeleteCbEv 0x0000007100684028,AI_QueryBase::m6n,4,_ZN4ksys3act2ai5Query2m6Ev 0x000000710068402c,AI_QueryBase::m7r1,8,_ZN4ksys3act2ai5Query5init_EPN4sead4HeapE -0x0000007100684034,AI_QueryBase::m11r1,8,_ZN4ksys3act2ai5Query3m11Ev -0x000000710068403c,AI_QueryBase::m12n,4,_ZN4ksys3act2ai5Query3m12Ev +0x0000007100684034,AI_QueryBase::m11r1,8,_ZN4ksys3act2ai5Query18updateForPreDeleteEv +0x000000710068403c,AI_QueryBase::m12n,4,_ZN4ksys3act2ai5Query11onPreDeleteEv 0x0000007100684040,AI_QueryBase::rtti1,112,_ZNK4ksys3act2ai5Query27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x00000071006840b0,AI_QueryBase::rtti2,92,_ZNK4ksys3act2ai5Query18getRuntimeTypeInfoEv 0x000000710068410c,AI_QueryBase::dtor,20,_ZN4ksys3act2ai5QueryD2Ev 0x0000007100684120,AI_QueryBase::dtorDelete,52,_ZN4ksys3act2ai5QueryD0Ev 0x0000007100684154,AI_QueryBase::doQuery,8,_ZN4ksys3act2ai5Query7doQueryEv 0x000000710068415c,AI_QueryBase::m10n,4,_ZN4ksys3act2ai5Query3m10Ev -0x0000007100684160,sub_7100684160,140, +0x0000007100684160,sub_7100684160,140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys3act2ai5QueryEE9isDerivedEPKNS0_9InterfaceE 0x00000071006841ec,AI_Query_BranchByGameOver::ctor,48, 0x000000710068421c,AI_Query_BranchByGameOver::dtor,20, 0x0000007100684230,AI_Query_BranchByGameOver::dtorDelete,52, @@ -74062,14 +74062,14 @@ 0x0000007100d5a87c,sub_7100D5A87C,12,_ZNK4ksys3act2ai5Query17getAITreeVariableEPPN4sead14SafeStringBaseIcEERKS5_ 0x0000007100d5a888,sub_7100D5A888,12,_ZNK4ksys3act2ai5Query17getAITreeVariableEPPvRKN4sead14SafeStringBaseIcEE 0x0000007100d5a894,sub_7100D5A894,236, -0x0000007100d5a980,ai::Queries::ctor,28, -0x0000007100d5a99c,sub_7100D5A99C,4, -0x0000007100d5a9a0,sub_7100D5A9A0,200, -0x0000007100d5aa68,ai::Queries::init,1212, -0x0000007100d5af24,sub_7100D5AF24,32, -0x0000007100d5af44,sub_7100D5AF44,96, -0x0000007100d5afa4,sub_7100D5AFA4,68, -0x0000007100d5afe8,sub_7100D5AFE8,304, +0x0000007100d5a980,ai::Queries::ctor,28,_ZN4ksys3act2ai7QueriesC1Ev +0x0000007100d5a99c,sub_7100D5A99C,4,_ZN4ksys3act2ai7QueriesD1Ev +0x0000007100d5a9a0,sub_7100D5A9A0,200,_ZN4ksys3act2ai7Queries8finalizeEv +0x0000007100d5aa68,ai::Queries::init,1212,_ZN4ksys3act2ai7Queries4initEPNS0_5ActorEPN4sead4HeapE +0x0000007100d5af24,sub_7100D5AF24,32,_ZN4ksys3act2ai7Queries12setFactoriesEiPNS1_12QueryFactoryE +0x0000007100d5af44,sub_7100D5AF44,96,_ZNK4ksys3act2ai7Queries18updateForPreDeleteEv +0x0000007100d5afa4,sub_7100D5AFA4,68,_ZNK4ksys3act2ai7Queries11onPreDeleteEv +0x0000007100d5afe8,sub_7100D5AFE8,304,_ZNK4ksys3act2ai7Queries8getQueryERKN4sead14SafeStringBaseIcEE 0x0000007100d5b118,nullsub_3774,4, 0x0000007100d5b11c,j__ZdlPv_850,4, 0x0000007100d5b120,sub_7100D5B120,8, @@ -74350,12 +74350,12 @@ 0x0000007100d67448,AI_Behavior_ShowConstStringBoard::rtti2,92, 0x0000007100d674a4,AI_Behavior_ShowConstStringBoard::dtor_null,4, 0x0000007100d674a8,j__ZdlPv_857,4, -0x0000007100d674ac,AI_Query_DummyQuery::ctor,48, -0x0000007100d674dc,AI_Query_DummyQuery::m7,8, -0x0000007100d674e4,AI_Query_DummyQuery::m8,4, -0x0000007100d674e8,AI_Query_DummyQuery::rtti1,204, -0x0000007100d675b4,AI_Query_DummyQuery::rtti2,92, -0x0000007100d67610,AI_Query_DummyQuery::dtorDelete,52, +0x0000007100d674ac,AI_Query_DummyQuery::ctor,48,_ZN4ksys3act2ai10DummyQueryC1ERKNS1_5Query7InitArgE +0x0000007100d674dc,AI_Query_DummyQuery::m7,8,_ZN4ksys3act2ai10DummyQuery5init_EPN4sead4HeapE +0x0000007100d674e4,AI_Query_DummyQuery::m8,4,_ZN4ksys3act2ai10DummyQuery10loadParamsEv +0x0000007100d674e8,AI_Query_DummyQuery::rtti1,204,_ZNK4ksys3act2ai10DummyQuery27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100d675b4,AI_Query_DummyQuery::rtti2,92,_ZNK4ksys3act2ai10DummyQuery18getRuntimeTypeInfoEv +0x0000007100d67610,AI_Query_DummyQuery::dtorDelete,52,_ZN4ksys3act2ai10DummyQueryD0Ev 0x0000007100d67644,AI_Query_IsWaitRevival::ctor,48, 0x0000007100d67674,AI_Query_IsWaitRevival::dtor,20, 0x0000007100d67688,AI_Query_IsWaitRevival::dtorDelete,52, diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt index ac059bc1..464cb97b 100644 --- a/src/KingSystem/ActorSystem/CMakeLists.txt +++ b/src/KingSystem/ActorSystem/CMakeLists.txt @@ -35,6 +35,8 @@ target_sources(uking PRIVATE actAiParam.h actAiQuery.cpp actAiQuery.h + actAiQueries.cpp + actAiQueries.h actAiRoot.cpp actAiRoot.h actAttention.cpp @@ -70,4 +72,6 @@ target_sources(uking PRIVATE aiDummyAi.h behaviorDummyBehavior.cpp behaviorDummyBehavior.h + queryDummyQuery.cpp + queryDummyQuery.h ) diff --git a/src/KingSystem/ActorSystem/actAiQueries.cpp b/src/KingSystem/ActorSystem/actAiQueries.cpp new file mode 100644 index 00000000..5d900bcc --- /dev/null +++ b/src/KingSystem/ActorSystem/actAiQueries.cpp @@ -0,0 +1,143 @@ +#include "KingSystem/ActorSystem/actAiQueries.h" +#include +#include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/ActorSystem/actActorParam.h" +#include "KingSystem/ActorSystem/actAiQuery.h" +#include "KingSystem/ActorSystem/queryDummyQuery.h" +#include "KingSystem/Resource/resResourceAIProgram.h" + +namespace ksys::act::ai { + +Queries::Queries() = default; + +Queries::~Queries() { + finalize(); +} + +void Queries::finalize() { + for (s32 i = 0; i < mClasses.size(); ++i) { + if (mClasses[i]) { + delete mClasses[i]; + mClasses[i] = nullptr; + } + } + + mOnPreDeleteCbs.freeBuffer(); + mUpdateForPreDeleteCbs.freeBuffer(); + mClasses.freeBuffer(); +} + +bool Queries::init(Actor* actor, sead::Heap* heap) { + const auto* aiprog = actor->getParam()->getRes().mAIProgram; + + const auto num_Queries = aiprog->getQueries().size(); + if (num_Queries == 0) + return true; + + if (!mClasses.tryAllocBuffer(num_Queries, heap)) + return false; + for (s32 i = 0, n = mClasses.size(); i != n; ++i) + mClasses(i) = nullptr; + auto it_class = mClasses.begin(); + const auto it_class_end = mClasses.end(); + + Query::InitArg arg; + arg.actor = actor; + s32 predelete_cb_num = 0; + s32 update_cb_num = 0; + for (; it_class != it_class_end; ++it_class) { + arg.def_idx = it_class.getIndex(); + const char* name = aiprog->getQueries()[it_class.getIndex()].mClassName; + + auto* factory = getFactory(name); + if (factory) + *it_class = factory->create_fn(arg, heap); + else + *it_class = new (heap) DummyQuery(arg); + + if (!*it_class) + return false; + + update_cb_num += (*it_class)->hasUpdateForPreDeleteCb(); + predelete_cb_num += (*it_class)->hasPreDeleteCb(); + } + + // Allocate the callback lists. + if (predelete_cb_num != 0) { + if (!mOnPreDeleteCbs.tryAllocBuffer(predelete_cb_num, heap)) + return false; + for (s32 i = 0; i < predelete_cb_num; ++i) + mOnPreDeleteCbs(i) = nullptr; + } + + if (update_cb_num != 0) { + if (!mUpdateForPreDeleteCbs.tryAllocBuffer(update_cb_num, heap)) + return false; + for (s32 i = 0; i < update_cb_num; ++i) + mUpdateForPreDeleteCbs(i) = nullptr; + } + + // Initialize each class. + s32 idx_cb1 = 0, idx_cb2 = 0; + for (auto it = mClasses.begin(), end = mClasses.end(); it != end; ++it) { + if (!(*it)->init(heap)) + return false; + + if ((*it)->hasUpdateForPreDeleteCb()) { + mUpdateForPreDeleteCbs[idx_cb2] = *it; + ++idx_cb2; + } + + if ((*it)->hasPreDeleteCb()) { + mOnPreDeleteCbs[idx_cb1] = *it; + ++idx_cb1; + } + } + + return true; +} + +bool Queries::updateForPreDelete() const { + bool ok = true; + for (auto* cb : mUpdateForPreDeleteCbs) { + if (cb) + ok &= cb->updateForPreDelete(); + } + return ok; +} + +void Queries::onPreDelete() const { + for (auto* cb : mOnPreDeleteCbs) { + if (cb) + cb->onPreDelete(); + } +} + +Query* Queries::getQuery(const sead::SafeString& name) const { + for (auto* query : mClasses) { + if (name == query->getName()) + return query; + } + return nullptr; +} + +QueryFactory* Queries::getFactory(const sead::SafeString& name) { + const u32 name_hash = sead::HashCRC32::calcStringHash(name); + const s32 idx = sFactories.binarySearch( + name_hash, +[](const QueryFactory& factory, const u32& hash) { + if (factory.hash < hash) + return -1; + if (factory.hash > hash) + return 1; + return 0; + }); + if (idx < 0) + return nullptr; + return sFactories.get(idx); +} + +void Queries::setFactories(int count, QueryFactory* factories) { + sFactories.setBuffer(count, factories); +} + +} // namespace ksys::act::ai diff --git a/src/KingSystem/ActorSystem/actAiQueries.h b/src/KingSystem/ActorSystem/actAiQueries.h new file mode 100644 index 00000000..867c3081 --- /dev/null +++ b/src/KingSystem/ActorSystem/actAiQueries.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +namespace ksys::act { +class Actor; +} + +namespace ksys::act::ai { + +class Query; +struct QueryFactory; + +class Queries { +public: + Queries(); + ~Queries(); + + void finalize(); + + bool init(Actor* actor, sead::Heap* heap); + bool updateForPreDelete() const; + void onPreDelete() const; + + const sead::Buffer& getClasses() const { return mClasses; } + Query* getQuery(const sead::SafeString& name) const; + + static QueryFactory* getFactory(const sead::SafeString& name); + static void setFactories(int count, QueryFactory* factories); + +private: + static inline sead::Buffer sFactories; + sead::Buffer mClasses; + // Non-owning buffer. + sead::Buffer mOnPreDeleteCbs; + // Non-owning buffer. + sead::Buffer mUpdateForPreDeleteCbs; +}; + +} // namespace ksys::act::ai diff --git a/src/KingSystem/ActorSystem/actAiQuery.h b/src/KingSystem/ActorSystem/actAiQuery.h index 3b094943..d24a31c0 100644 --- a/src/KingSystem/ActorSystem/actAiQuery.h +++ b/src/KingSystem/ActorSystem/actAiQuery.h @@ -51,15 +51,15 @@ public: bool getAITreeVariable(sead::SafeString** value, const sead::SafeString& param) const; bool getAITreeVariable(void** value, const sead::SafeString& param) const; - virtual bool m4() { return false; } - virtual bool m5() { return false; } + virtual bool hasPreDeleteCb() { return false; } + virtual bool hasUpdateForPreDeleteCb() { return false; } virtual void m6() {} virtual bool init_(sead::Heap* heap) { return true; } virtual void loadParams() {} virtual int doQuery() { return 0; } virtual void m10() {} - virtual bool m11() { return true; } - virtual void m12() {} + virtual bool updateForPreDelete() { return true; } + virtual void onPreDelete() {} protected: res::AIProgram* getAIProg() const; @@ -80,18 +80,10 @@ protected: }; KSYS_CHECK_SIZE_NX150(Query, 0x20); -class Queries { -public: - Queries(); - ~Queries(); - - void finalize(); - - sead::Buffer classes; - // TODO: rename - sead::Buffer x; - // TODO: rename - sead::Buffer y; +struct QueryFactory { + using CreateFn = Query* (*)(const Query::InitArg& arg, sead::Heap* heap); + u32 hash; + CreateFn create_fn; }; } // namespace ksys::act::ai diff --git a/src/KingSystem/ActorSystem/actAiRoot.h b/src/KingSystem/ActorSystem/actAiRoot.h index 8f8cb4b5..64f942a7 100644 --- a/src/KingSystem/ActorSystem/actAiRoot.h +++ b/src/KingSystem/ActorSystem/actAiRoot.h @@ -5,6 +5,7 @@ #include "KingSystem/ActorSystem/actAiAi.h" #include "KingSystem/ActorSystem/actAiBehavior.h" #include "KingSystem/ActorSystem/actAiParam.h" +#include "KingSystem/ActorSystem/actAiQueries.h" #include "KingSystem/ActorSystem/actAiQuery.h" #include "KingSystem/Utils/Types.h" diff --git a/src/KingSystem/ActorSystem/queryDummyQuery.cpp b/src/KingSystem/ActorSystem/queryDummyQuery.cpp new file mode 100644 index 00000000..2fdc4406 --- /dev/null +++ b/src/KingSystem/ActorSystem/queryDummyQuery.cpp @@ -0,0 +1,13 @@ +#include "KingSystem/ActorSystem/queryDummyQuery.h" + +namespace ksys::act::ai { + +DummyQuery::DummyQuery(const Query::InitArg& arg) : Query(arg) {} + +bool DummyQuery::init_(sead::Heap* heap) { + return true; +} + +void DummyQuery::loadParams() {} + +} // namespace ksys::act::ai diff --git a/src/KingSystem/ActorSystem/queryDummyQuery.h b/src/KingSystem/ActorSystem/queryDummyQuery.h new file mode 100644 index 00000000..b228ff96 --- /dev/null +++ b/src/KingSystem/ActorSystem/queryDummyQuery.h @@ -0,0 +1,16 @@ +#pragma once + +#include "KingSystem/ActorSystem/actAiQuery.h" + +namespace ksys::act::ai { + +class DummyQuery : public Query { + SEAD_RTTI_OVERRIDE(DummyQuery, Query) +public: + explicit DummyQuery(const InitArg& arg); + + bool init_(sead::Heap* heap) override; + void loadParams() override; +}; + +} // namespace ksys::act::ai