diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 07a423f4..01fd15bf 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -1321,7 +1321,7 @@ 0x000000710004c1d0,AI_AIOrActionBase::ret0_4,8,_ZN4ksys3act2ai10ActionBase15handleMessage2_EPNS_3mes7MessageE 0x000000710004c1d8,AI_AIOrActionBase::ret1_0,8,_ZN4ksys3act2ai10ActionBase18updateForPreDeleteEv 0x000000710004c1e0,AI_AIOrActionBase::m19_null,4,_ZN4ksys3act2ai10ActionBase11onPreDeleteEv -0x000000710004c1e4,AI_AIOrActionBase::ret0_0,8,_ZN4ksys3act2ai10ActionBase11changeChildERKN4sead14SafeStringBaseIcEE +0x000000710004c1e4,AI_AIOrActionBase::ret0_0,8,_ZN4ksys3act2ai10ActionBase16changeChildLaterERKN4sead14SafeStringBaseIcEE 0x000000710004c1ec,AI_AIOrActionBase::ret0_1,8,_ZNK4ksys3act2ai10ActionBase14getNumChildrenEv 0x000000710004c1f4,AI_AIOrActionBase::ret1_1,8,_ZN4ksys3act2ai10ActionBase12initChildrenERKNS_8AIDefSetEPN4sead4HeapE 0x000000710004c1fc,AI_AIOrActionBase::ret0_5,8,_ZNK4ksys3act2ai10ActionBase15getCurrentChildEv @@ -92259,24 +92259,24 @@ 0x00000071011ddfa8,AI_AIBase::dtorDelete,92,_ZN4ksys3act2ai2AiD0Ev 0x00000071011de004,AI_AIBase::m25,132,_ZN4ksys3act2ai2Ai12initChildrenERKNS_8AIDefSetEPN4sead4HeapE 0x00000071011de088,AI_AIBase::initChildStates,580,_ZN4ksys3act2ai2Ai13initChildren_EiPPKcRN4sead6BufferItEEPNS6_4HeapE -0x00000071011de2cc,AI_AIBase::x_0,340, +0x00000071011de2cc,AI_AIBase::x_0,340,_ZN4ksys3act2ai2Ai24gatherParamsFromChildrenEPN4sead4HeapE 0x00000071011de420,AI_AIBase::calcRecursively,156,_ZN4ksys3act2ai2Ai4calcEv -0x00000071011de4bc,AI_AIBase::x,76, +0x00000071011de4bc,AI_AIBase::x,76,_ZN4ksys3act2ai2Ai24handlePendingChildChangeEv 0x00000071011de508,sub_71011DE508,276, 0x00000071011de61c,sub_71011DE61C,24, -0x00000071011de634,AI_AIBase::hasCustomActionIndex,40, -0x00000071011de65c,AI_AIBase::getChildStateIndexByName,344, -0x00000071011de7b4,AI_AIBase::doChangeState,440, -0x00000071011de96c,AI_AIBase::changeState,96, -0x00000071011de9cc,AI_AIBase::m28,400, +0x00000071011de634,AI_AIBase::hasCustomActionIndex,40,_ZNK4ksys3act2ai2Ai21hasPendingChildChangeEv +0x00000071011de65c,AI_AIBase::getChildStateIndexByName,344,_ZNK4ksys3act2ai2Ai11getChildIdxERKN4sead14SafeStringBaseIcEE +0x00000071011de7b4,AI_AIBase::doChangeState,440,_ZN4ksys3act2ai2Ai11changeChildEjPNS1_15InlineParamPackE +0x00000071011de96c,AI_AIBase::changeState,96,_ZN4ksys3act2ai2Ai11changeChildEPKcPNS1_15InlineParamPackE +0x00000071011de9cc,AI_AIBase::m28,400,_ZN4ksys3act2ai2Ai7reenterEPNS1_10ActionBaseERKN4sead14SafeStringBaseIcEE 0x00000071011deb5c,AI_AIBase::m6,72,_ZNK4ksys3act2ai2Ai10isFlag4SetEv 0x00000071011deba4,AI_AIBase::getCurrentChildState,52,_ZNK4ksys3act2ai2Ai15getCurrentChildEv -0x00000071011debd8,AI_AIBase::isState,196, -0x00000071011dec9c,ai::ActorAI::checkAction,188, -0x00000071011ded58,sub_71011DED58,24,_ZN4ksys3act2ai2Ai14updateChildIdxEt -0x00000071011ded70,AI_AIBase::m22,116, -0x00000071011dede4,AI_AIBase::m31,224, -0x00000071011deec4,AI_AIBase::m23,216, +0x00000071011debd8,AI_AIBase::isState,196,_ZNK4ksys3act2ai2Ai14isCurrentChildERKN4sead14SafeStringBaseIcEE +0x00000071011dec9c,ai::ActorAI::checkAction,188,_ZN4ksys3act2ai2Ai15isCurrentActionERKN4sead14SafeStringBaseIcEE +0x00000071011ded58,sub_71011DED58,24,_ZN4ksys3act2ai2Ai14changeChildIdxEt +0x00000071011ded70,AI_AIBase::m22,116,_ZN4ksys3act2ai2Ai16changeChildLaterERKN4sead14SafeStringBaseIcEE +0x00000071011dede4,AI_AIBase::m31,224,_ZNK4ksys3act2ai2Ai8getNamesEPN4sead22BufferedSafeStringBaseIcEE +0x00000071011deec4,AI_AIBase::m23,216,_ZNK4ksys3act2ai2Ai9getParamsEPNS1_18ParamNameTypePairsEb 0x00000071011def9c,AI_AIBase::rtti1,204,_ZNK4ksys3act2ai2Ai27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x00000071011df068,AI_AIBase::rtti2,92,_ZNK4ksys3act2ai2Ai18getRuntimeTypeInfoEv 0x00000071011df0c4,ai::AIs::ctor,28,_ZN4ksys3act2ai3AisC1Ev diff --git a/src/KingSystem/ActorSystem/actAiActionBase.h b/src/KingSystem/ActorSystem/actAiActionBase.h index f490a7ad..205b9d4b 100644 --- a/src/KingSystem/ActorSystem/actAiActionBase.h +++ b/src/KingSystem/ActorSystem/actAiActionBase.h @@ -100,7 +100,7 @@ public: virtual void calc() {} virtual void getCurrentName(sead::BufferedSafeString* name, ActionBase* last) const; - virtual ActionBase* changeChild(const sead::SafeString& name) { return nullptr; } + virtual ActionBase* changeChildLater(const sead::SafeString& name) { return nullptr; } virtual void getParams(ParamNameTypePairs* pairs, bool update_use_count) const; virtual s32 getNumChildren() const { return 0; } virtual bool initChildren(const AIDefSet& set, sead::Heap* heap) { return true; } diff --git a/src/KingSystem/ActorSystem/actAiAi.cpp b/src/KingSystem/ActorSystem/actAiAi.cpp index f12391af..0f9dcb5e 100644 --- a/src/KingSystem/ActorSystem/actAiAi.cpp +++ b/src/KingSystem/ActorSystem/actAiAi.cpp @@ -70,6 +70,25 @@ bool Ai::initChildren_(s32 num_children, const char** names, sead::Buffer& return true; } +bool Ai::gatherParamsFromChildren(sead::Heap* heap) { + if (mFlags.isOff(Flag::DynamicParamChild) || mFlags.isOn(Flag::_20)) + return true; + + ParamNameTypePairs pairs; + for (auto* child : mChildren) { + if (auto* ai = sead::DynamicCast(child)) { + if (ai->mFlags.isOn(Flag::DynamicParamChild) && ai->mFlags.isOff(Flag::_20) && + !ai->gatherParamsFromChildren(heap)) { + return false; + } + } + child->getParams(&pairs, true); + } + + mFlags.set(Flag::_20); + return mParams.load(*mActor, pairs, mChildren.size(), heap); +} + void Ai::calc() { calc_(); @@ -77,7 +96,7 @@ void Ai::calc() { if (child) child->calc(); - if (mPendingChildIdx != InvalidIdx && mChildIdx != mPendingChildIdx) { + if (hasPendingChildChange()) { handlePendingChildChange_(); auto* new_child = getCurrentChild(); if (new_child) @@ -85,6 +104,86 @@ void Ai::calc() { } } +bool Ai::handlePendingChildChange() { + if (!hasPendingChildChange()) + return false; + handlePendingChildChange_(); + return true; +} + +bool Ai::hasPendingChildChange() const { + return mPendingChildIdx != InvalidIdx && mChildIdx != mPendingChildIdx; +} + +s32 Ai::getChildIdx(const sead::SafeString& name) const { + const s32 idx = mChildren.binarySearch( + name, +[](ActionBase* const& action, const sead::SafeString& key) { + if (action == nullptr) + return 0; + return sead::SafeString(action->getName()).compare(key); + }); + return idx == -1 ? InvalidIdx : idx; +} + +void Ai::changeChild(u32 idx, InlineParamPack* params) { + const auto do_change = [&](InlineParamPack* pack) { + auto* current_child = getCurrentChild(); + mNewChildIdx = idx; + if (current_child) + current_child->leave(); + + changeChildIdx(idx); + if (mChildren[idx]) + mChildren[idx]->enter(pack, getName()); + + setRootAiFlag(RootAiFlag::_100); + }; + + if (mFlags.isOff(Flag::DynamicParamChild) || params) { + do_change(params); + } else { + InlineParamPack pack; + copyParams(&pack, false); + do_change(&pack); + } +} + +void Ai::changeChild(const char* name, InlineParamPack* params) { + const auto idx = getChildIdx(name); + if (idx != InvalidIdx) + changeChild(idx, params); +} + +bool Ai::reenter(ActionBase* other, const sead::SafeString& context) { + auto* ai = sead::DynamicCast(other); + if (!ai) + return false; + + if (ai->getNumChildren() != getNumChildren()) + return false; + + mPendingChildIdx = InvalidIdx; + + const bool reenter_ret = reenter_(ai, false); + + if (mFlags.isOn(Flag::_40)) { + if (auto* child = getCurrentChild()) + child->leave(); + mFlags.reset(Flag::_40); + } + + mPrevChildIdx = ai->mPrevChildIdx; + mChildIdx = ai->mChildIdx; + if (!reenter_ret) + return false; + + auto* other_child = ai->getCurrentChild(); + auto* child = getCurrentChild(); + if (!other_child || !child) + return true; + return child->takeOver(other_child, getName()); +} + bool Ai::isFlag4Set() const { auto* child = getCurrentChild(); if (child) @@ -99,13 +198,67 @@ ActionBase* Ai::getCurrentChild() const { return mChildren[mChildIdx]; } -void Ai::updateChildIdx(u16 new_idx) { +bool Ai::isCurrentChild(const sead::SafeString& name) const { + const auto* child = getCurrentChild(); + if (!child) + return false; + return name == child->getName(); +} + +bool Ai::isCurrentAction(const sead::SafeString& name) { + auto* action = getCurrentAction(); + if (!action) + return false; + return name == action->getName(); +} + +void Ai::changeChildIdx(u16 new_idx) { const auto prev_idx = mChildIdx; mChildIdx = new_idx; mPrevChildIdx = prev_idx; mPendingChildIdx = InvalidIdx; } +ActionBase* Ai::changeChildLater(const sead::SafeString& name) { + const auto idx = getChildIdx(name); + if (idx == InvalidIdx) + return nullptr; + + if (idx == mChildIdx) + return getCurrentChild(); + + mPendingChildIdx = idx; + return mChildren[idx]; +} + +void Ai::getNames(sead::BufferedSafeString* out) const { + if (mPrevChildIdx == InvalidIdx) + return; + + const auto* child = mChildren[mPrevChildIdx]; + if (!child) + return; + + out->appendWithFormat("/%s", child->getName()); + if (auto* child_ai = sead::DynamicCast(child)) + child_ai->getNames(out); +} + +void Ai::getParams(ParamNameTypePairs* pairs, bool update_use_count) const { + auto* ptr = this; + do { + ptr->ActionBase::getParams(pairs, update_use_count); + if (ptr->mFlags.isOff(Flag::DynamicParamChild)) + return; + if (!sead::IsDerivedFrom(ptr)) + return; + if (ptr->getNumChildren() <= 0) + return; + ptr = static_cast(ptr->getChild(0)); + update_use_count = false; + } while (ptr); +} + Ais::Ais() = default; Ais::~Ais() { diff --git a/src/KingSystem/ActorSystem/actAiAi.h b/src/KingSystem/ActorSystem/actAiAi.h index b4d9e46e..aca4fb09 100644 --- a/src/KingSystem/ActorSystem/actAiAi.h +++ b/src/KingSystem/ActorSystem/actAiAi.h @@ -12,26 +12,38 @@ public: ~Ai() override; bool isFlag4Set() const override; - bool reenter_(ActionBase* other, bool x) override; void calc() override; - ActionBase* changeChild(const sead::SafeString& name) override; + ActionBase* changeChildLater(const sead::SafeString& name) override; void getParams(ParamNameTypePairs* pairs, bool update_use_count) const override; s32 getNumChildren() const override { return mChildren.size(); } bool initChildren(const AIDefSet& set, sead::Heap* heap) override; ActionBase* getCurrentChild() const override; ActionType getType() const override { return ActionType::AI; } bool reenter(ActionBase* other, const sead::SafeString& context) override; - void postLeave() override { updateChildIdx(InvalidIdx); } + void postLeave() override { changeChildIdx(InvalidIdx); } ActionBase* getChild(s32 idx) const override { return mChildren[idx]; } - virtual void getNames(sead::BufferedSafeString* out); + virtual void getNames(sead::BufferedSafeString* out) const; bool gatherParamsFromChildren(sead::Heap* heap); + void changeAS(const char* as_name, bool b, int x, int y); + // TODO: figure out what this actually does and rename + bool checkAS(int x, int y); + + /// @returns whether there was a pending child change. + bool handlePendingChildChange(); + bool hasPendingChildChange() const; + s32 getChildIdx(const sead::SafeString& name) const; + void changeChild(u32 idx, InlineParamPack* params = nullptr); + void changeChild(const char* name, InlineParamPack* params = nullptr); + + bool isCurrentChild(const sead::SafeString& name) const; + bool isCurrentAction(const sead::SafeString& name); + protected: virtual void calc_() {} - virtual void handlePendingChildChange_() { changeChildState(mPendingChildIdx); } - void updateChildIdx(u16 new_idx); - void changeChildState(u16 idx, InlineParamPack* params = nullptr); + virtual void handlePendingChildChange_() { changeChild(mPendingChildIdx); } + void changeChildIdx(u16 new_idx); static constexpr u16 InvalidIdx = 0xffff; diff --git a/src/KingSystem/ActorSystem/actAiParam.h b/src/KingSystem/ActorSystem/actAiParam.h index c426a8cb..7efaff87 100644 --- a/src/KingSystem/ActorSystem/actAiParam.h +++ b/src/KingSystem/ActorSystem/actAiParam.h @@ -35,8 +35,8 @@ KSYS_CHECK_SIZE_NX150(ParamNameType, 0x10); struct ParamNameTypePairs { void addPair(AIDefParamType type, const sead::SafeString& name, bool update_use_count); - sead::SafeArray pairs; - s32 count; + sead::SafeArray pairs{}; + s32 count = 0; }; KSYS_CHECK_SIZE_NX150(ParamNameTypePairs, 0x208);