diff --git a/data/status_ai.yml b/data/status_ai.yml index c417d943..e43fa1f5 100644 --- a/data/status_ai.yml +++ b/data/status_ai.yml @@ -755,7 +755,7 @@ ai::Fork6AI: ai::ForkActionAndJoin: status: pending ai::ForkAI: - status: pending + status: done ai::ForkBeastGanonRoot: status: pending ai::ForSaleOrNot: diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 100bfba2..dc51a275 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -74277,18 +74277,18 @@ 0x0000007100d63a78,AI_AIForkAI::ctor,48,_ZN5uking2ai6ForkAIC1ERKN4ksys3act2ai10ActionBase7InitArgE 0x0000007100d63aa8,_ZN5uking2ai6ForkAID1Ev,4,_ZN5uking2ai6ForkAID1Ev 0x0000007100d63aac,_ZN5uking2ai6ForkAID0Ev,36,_ZN5uking2ai6ForkAID0Ev -0x0000007100d63ad0,_ZN5uking2ai6ForkAI5init_EPN4sead4HeapE,20, -0x0000007100d63ae4,_ZN5uking2ai6ForkAI6enter_EPN4ksys3act2ai15InlineParamPackE,192, -0x0000007100d63ba4,_ZN5uking2ai6ForkAI7reenterEPS2_RKN4sead14SafeStringBaseIcEE,384, -0x0000007100d63d24,_ZN5uking2ai6ForkAI4calcEv,128, -0x0000007100d63da4,_ZN5uking2ai6ForkAI6leave_Ev,88, -0x0000007100d63dfc,_ZNK5uking2ai6ForkAI8isFailedEv,212, -0x0000007100d63ed0,_ZNK5uking2ai6ForkAI10isFinishedEv,200, -0x0000007100d63f98,_ZNK5uking2ai6ForkAI10isFlag4SetEv,124, -0x0000007100d64014,_ZN5uking2ai6ForkAI14handleMessage_EPN4ksys3mes7MessageE,168, -0x0000007100d640bc,_ZN5uking2ai6ForkAI15handleMessage2_EPN4ksys3mes7MessageE,168, -0x0000007100d64164,_ZNK5uking2ai6ForkAI14getCurrentNameEPN4sead22BufferedSafeStringBaseIcEEPS2_,200, -0x0000007100d6422c,_ZNK5uking2ai6ForkAI8getNamesEPN4sead22BufferedSafeStringBaseIcEE,316, +0x0000007100d63ad0,_ZN5uking2ai6ForkAI5init_EPN4sead4HeapE,20,_ZN5uking2ai6ForkAI5init_EPN4sead4HeapE +0x0000007100d63ae4,_ZN5uking2ai6ForkAI6enter_EPN4ksys3act2ai15InlineParamPackE,192,_ZN5uking2ai6ForkAI6enter_EPN4ksys3act2ai15InlineParamPackE +0x0000007100d63ba4,_ZN5uking2ai6ForkAI7reenterEPS2_RKN4sead14SafeStringBaseIcEE,384,_ZN5uking2ai6ForkAI7reenterEPN4ksys3act2ai10ActionBaseERKN4sead14SafeStringBaseIcEE +0x0000007100d63d24,_ZN5uking2ai6ForkAI4calcEv,128,_ZN5uking2ai6ForkAI4calcEv +0x0000007100d63da4,_ZN5uking2ai6ForkAI6leave_Ev,88,_ZN5uking2ai6ForkAI6leave_Ev +0x0000007100d63dfc,_ZNK5uking2ai6ForkAI8isFailedEv,212,_ZNK5uking2ai6ForkAI8isFailedEv +0x0000007100d63ed0,_ZNK5uking2ai6ForkAI10isFinishedEv,200,_ZNK5uking2ai6ForkAI10isFinishedEv +0x0000007100d63f98,_ZNK5uking2ai6ForkAI10isFlag4SetEv,124,_ZNK5uking2ai6ForkAI10isFlag4SetEv +0x0000007100d64014,_ZN5uking2ai6ForkAI14handleMessage_EPN4ksys3mes7MessageE,168,_ZN5uking2ai6ForkAI14handleMessage_EPN4ksys7MessageE +0x0000007100d640bc,_ZN5uking2ai6ForkAI15handleMessage2_EPN4ksys3mes7MessageE,168,_ZN5uking2ai6ForkAI15handleMessage2_EPN4ksys7MessageE +0x0000007100d64164,_ZNK5uking2ai6ForkAI14getCurrentNameEPN4sead22BufferedSafeStringBaseIcEEPS2_,200,_ZNK5uking2ai6ForkAI14getCurrentNameEPN4sead22BufferedSafeStringBaseIcEEPN4ksys3act2ai10ActionBaseE +0x0000007100d6422c,_ZNK5uking2ai6ForkAI8getNamesEPN4sead22BufferedSafeStringBaseIcEE,316,_ZNK5uking2ai6ForkAI8getNamesEPN4sead22BufferedSafeStringBaseIcEE 0x0000007100d64368,_ZNK5uking2ai6ForkAI27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE,288,_ZNK5uking2ai6ForkAI27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100d64488,_ZNK5uking2ai6ForkAI18getRuntimeTypeInfoEv,92,_ZNK5uking2ai6ForkAI18getRuntimeTypeInfoEv 0x0000007100d644e4,ai::ActorAI::ctor,152,_ZN4ksys3act2ai6RootAiC1ERKNS1_10ActionBase7InitArgE @@ -92278,7 +92278,7 @@ 0x00000071011deba4,AI_AIBase::getCurrentChildState,52,_ZNK4ksys3act2ai2Ai15getCurrentChildEv 0x00000071011debd8,AI_AIBase::isState,196,_ZNK4ksys3act2ai2Ai14isCurrentChildERKN4sead14SafeStringBaseIcEE 0x00000071011dec9c,ai::ActorAI::checkAction,188,_ZN4ksys3act2ai2Ai15isCurrentActionERKN4sead14SafeStringBaseIcEE -0x00000071011ded58,sub_71011DED58,24,_ZN4ksys3act2ai2Ai14changeChildIdxEt +0x00000071011ded58,sub_71011DED58,24,_ZN4ksys3act2ai2Ai14changeChildIdxEi 0x00000071011ded70,AI_AIBase::m22,116,_ZN4ksys3act2ai2Ai16changeChildLaterERKN4sead14SafeStringBaseIcEE 0x00000071011dede4,AI_AIBase::m31,224,_ZNK4ksys3act2ai2Ai8getNamesEPN4sead22BufferedSafeStringBaseIcEE 0x00000071011deec4,AI_AIBase::m23,216,_ZNK4ksys3act2ai2Ai9getParamsEPNS1_18ParamNameTypePairsEb diff --git a/src/Game/AI/AI/aiForkAI.cpp b/src/Game/AI/AI/aiForkAI.cpp index 09c5bf8b..dc738ecb 100644 --- a/src/Game/AI/AI/aiForkAI.cpp +++ b/src/Game/AI/AI/aiForkAI.cpp @@ -1,4 +1,5 @@ #include "Game/AI/AI/aiForkAI.h" +#include "KingSystem/ActorSystem/actAiRoot.h" namespace uking::ai { @@ -7,15 +8,150 @@ ForkAI::ForkAI(const InitArg& arg) : ksys::act::ai::Ai(arg) {} ForkAI::~ForkAI() = default; bool ForkAI::init_(sead::Heap* heap) { - return ksys::act::ai::Ai::init_(heap); + mFlags.set(Flag::_80); + return true; } void ForkAI::enter_(ksys::act::ai::InlineParamPack* params) { - ksys::act::ai::Ai::enter_(params); + const int num_children = getNumChildren(); + if (num_children >= 1) { + for (int i = 0; i < num_children; ++i) + getChild(i)->enter(params, getName()); + changeChildIdx(num_children - 1); + } else { + SEAD_WARN("ForkAI::enter_: no children"); + changeChildIdx(num_children - 1); + } + setRootAiFlag(ksys::act::ai::RootAiFlag::_100); +} + +bool ForkAI::reenter(ksys::act::ai::ActionBase* other, const sead::SafeString& context) { + auto* other_ = sead::DynamicCast(other); + if (!other_) + return false; + + const int num_children = getNumChildren(); + if (other_->getNumChildren() != num_children) + return false; + + changeChildIdx(other_->mPrevChildIdx); + changeChildIdx(other_->mChildIdx); + + bool ok = true; + for (int i = 0; i < num_children; ++i) { + auto* child_other = other_->getChild(i); + auto* child = getChild(i); + if (child_other && child) + ok &= child->takeOver(child_other, getName()); + } + return ok; +} + +void ForkAI::calc() { + calc_(); + + const int num_children = getNumChildren(); + for (int i = 0; i < num_children; ++i) + getChild(i)->calc(); + + handlePendingChildChange(); } void ForkAI::leave_() { - ksys::act::ai::Ai::leave_(); + const int num_children = getNumChildren(); + for (int i = num_children - 2; i >= 0; --i) + getChild(i)->leave(); +} + +bool ForkAI::isFailed() const { + const int num_children = getNumChildren(); + bool failed = false; + int i = 0; + for (; i < num_children; ++i) { + auto* child = getChild(i); + failed |= child->isFailed(); + if (!child->isFinished() && !child->isFailed() && !child->isFlag4Set()) + break; + } + return i == num_children && failed; +} + +bool ForkAI::isFinished() const { + const int num_children = getNumChildren(); + bool finished = false; + int i = 0; + for (; i < num_children; ++i) { + auto* child = getChild(i); + if (child->isFailed()) + break; + if (child->isFinished()) + finished = true; + else if (!child->isFlag4Set()) + break; + } + return i == num_children && finished; +} + +bool ForkAI::isFlag4Set() const { + const int num_children = getNumChildren(); + for (int i = 0; i < num_children; ++i) { + if (!getChild(i)->isFlag4Set()) + return false; + } + return true; +} + +bool ForkAI::handleMessage_(ksys::Message* message) { + const int num_children = getNumChildren(); + + bool ok = false; + for (int i = 0; i < num_children - 1; ++i) + ok |= getChild(i)->handleMessage(message); + + if (!ok) + return false; + + getChild(num_children - 1)->handleMessage(message); + return true; +} + +bool ForkAI::handleMessage2_(ksys::Message* message) { + const int num_children = getNumChildren(); + + bool ok = false; + for (int i = 0; i < num_children - 1; ++i) + ok |= getChild(i)->handleMessage2(message); + + if (!ok) + return false; + + getChild(num_children - 1)->handleMessage2(message); + return true; +} + +void ForkAI::getCurrentName(sead::BufferedSafeString* name, ksys::act::ai::ActionBase* last) const { + name->appendWithFormat("/%s{", getName()); + if (this != last) { + const int num_children = getNumChildren(); + for (int i = 0; i < num_children; ++i) { + getChild(i)->getCurrentName(name, last); + name->appendWithFormat(","); + } + } + name->appendWithFormat("}"); +} + +void ForkAI::getNames(sead::BufferedSafeString* out) const { + out->appendWithFormat("{"); + const int num_children = getNumChildren(); + for (int i = 0; i < num_children; ++i) { + auto* child = getChild(i); + out->appendWithFormat("/%s", child->getName()); + if (auto* ai = sead::DynamicCast(child)) + ai->getNames(out); + out->appendWithFormat(","); + } + out->appendWithFormat("}"); } } // namespace uking::ai diff --git a/src/Game/AI/AI/aiForkAI.h b/src/Game/AI/AI/aiForkAI.h index ca7ba046..be52feb1 100644 --- a/src/Game/AI/AI/aiForkAI.h +++ b/src/Game/AI/AI/aiForkAI.h @@ -12,9 +12,16 @@ public: bool init_(sead::Heap* heap) override; void enter_(ksys::act::ai::InlineParamPack* params) override; + bool reenter(ActionBase* other, const sead::SafeString& context) override; + void calc() override; void leave_() override; - -protected: + bool isFailed() const override; + bool isFinished() const override; + bool isFlag4Set() const override; + bool handleMessage_(ksys::Message* message) override; + bool handleMessage2_(ksys::Message* message) override; + void getCurrentName(sead::BufferedSafeString* name, ActionBase* last) const override; + void getNames(sead::BufferedSafeString* out) const override; }; } // namespace uking::ai diff --git a/src/KingSystem/ActorSystem/actAiAi.cpp b/src/KingSystem/ActorSystem/actAiAi.cpp index f689360b..5495aa83 100644 --- a/src/KingSystem/ActorSystem/actAiAi.cpp +++ b/src/KingSystem/ActorSystem/actAiAi.cpp @@ -214,7 +214,7 @@ bool Ai::isCurrentAction(const sead::SafeString& name) { return name == action->getName(); } -void Ai::changeChildIdx(u16 new_idx) { +void Ai::changeChildIdx(int new_idx) { const auto prev_idx = mChildIdx; mChildIdx = new_idx; mPrevChildIdx = prev_idx; diff --git a/src/KingSystem/ActorSystem/actAiAi.h b/src/KingSystem/ActorSystem/actAiAi.h index bab91af8..518c8b7a 100644 --- a/src/KingSystem/ActorSystem/actAiAi.h +++ b/src/KingSystem/ActorSystem/actAiAi.h @@ -43,7 +43,7 @@ public: protected: virtual void calc_() {} virtual void handlePendingChildChange_() { changeChild(mPendingChildIdx); } - void changeChildIdx(u16 new_idx); + void changeChildIdx(int new_idx); static constexpr u16 InvalidIdx = 0xffff;