diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 2b6c0a97..9189ab27 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -1316,17 +1316,17 @@ 0x000000710004c1ac,AI_AIOrActionBase::ret0,8,_ZN4ksys3act2ai10ActionBase2m7Ev 0x000000710004c1b4,AI_AIOrActionBase::ret0_2,8,_ZN4ksys3act2ai10ActionBase2m8Ev 0x000000710004c1bc,AI_AIOrActionBase::m9_null,4,_ZN4ksys3act2ai10ActionBase2m9Ev -0x000000710004c1c0,AI_AIOrActionBase::ret1,8,_ZN4ksys3act2ai10ActionBase7oneShotEv +0x000000710004c1c0,AI_AIOrActionBase::ret1,8,_ZN4ksys3act2ai10ActionBase8oneShot_Ev 0x000000710004c1c8,AI_AIOrActionBase::ret0_3,8,_ZN4ksys3act2ai10ActionBase3m16Ev 0x000000710004c1d0,AI_AIOrActionBase::ret0_4,8,_ZN4ksys3act2ai10ActionBase3m17Ev 0x000000710004c1d8,AI_AIOrActionBase::ret1_0,8,_ZN4ksys3act2ai10ActionBase3m18Ev 0x000000710004c1e0,AI_AIOrActionBase::m19_null,4,_ZN4ksys3act2ai10ActionBase3m19Ev 0x000000710004c1e4,AI_AIOrActionBase::ret0_0,8,_ZN4ksys3act2ai10ActionBase3m22Ev 0x000000710004c1ec,AI_AIOrActionBase::ret0_1,8,_ZNK4ksys3act2ai10ActionBase14getNumChildrenEv -0x000000710004c1f4,AI_AIOrActionBase::ret1_1,8,_ZN4ksys3act2ai10ActionBase3m25Ev +0x000000710004c1f4,AI_AIOrActionBase::ret1_1,8,_ZN4ksys3act2ai10ActionBase12initChildrenERKNS_8AIDefSetEPN4sead4HeapE 0x000000710004c1fc,AI_AIOrActionBase::ret0_5,8,_ZNK4ksys3act2ai10ActionBase15getCurrentChildEv -0x000000710004c204,AI_ActionBase::isAction,8,_ZNK4ksys3act2ai6Action8isActionEv -0x000000710004c20c,AI_AIOrActionBase::m28,16,_ZN4ksys3act2ai10ActionBase7reenterEPS2_ +0x000000710004c204,AI_ActionBase::isAction,8,_ZNK4ksys3act2ai6Action7getTypeEv +0x000000710004c20c,AI_AIOrActionBase::m28,16,_ZN4ksys3act2ai10ActionBase7reenterEPS2_RKN4sead14SafeStringBaseIcEE 0x000000710004c21c,AI_AIOrActionBase::m29_null,4,_ZN4ksys3act2ai10ActionBase9postLeaveEv 0x000000710004c220,AI_AIOrActionBase::ret0_6,8,_ZNK4ksys3act2ai10ActionBase8getChildEi 0x000000710004c228,sub_710004C228,140, @@ -20065,7 +20065,7 @@ 0x00000071002f656c,AI_AI_ActorWaterDepthSelect::m5,36, 0x00000071002f6590,AI_AI_ActorWaterDepthSelect::m6,36, 0x00000071002f65b4,AI_AIBase::m24,8,_ZNK4ksys3act2ai2Ai14getNumChildrenEv -0x00000071002f65bc,AI_AIBase::isAction,8,_ZNK4ksys3act2ai2Ai8isActionEv +0x00000071002f65bc,AI_AIBase::isAction,8,_ZNK4ksys3act2ai2Ai7getTypeEv 0x00000071002f65c4,AI_AIBase::m29,8,_ZN4ksys3act2ai2Ai9postLeaveEv? 0x00000071002f65cc,AI_AIBase::m30,28,_ZNK4ksys3act2ai2Ai8getChildEi 0x00000071002f65e8,AI_AIBase::handlePendingChildChange,12,_ZN4ksys3act2ai2Ai25handlePendingChildChange_Ev @@ -72994,21 +72994,21 @@ 0x0000007100d1602c,j_BaseProcLink::cleanUp,4, 0x0000007100d16030,sub_7100D16030,8, 0x0000007100d16038,AI_AIOrActionBase::ctor,84,_ZN4ksys3act2ai10ActionBaseC2ERKNS2_7InitArgE -0x0000007100d1608c,AI_AIOrActionBase::preInit,808, -0x0000007100d163b4,AI_AIOrActionBase::getClassName,176, -0x0000007100d16464,AI_AIOrActionBase::x_0,24, -0x0000007100d1647c,AI_AIOrActionBase::isActorInDeleteState,12, -0x0000007100d16488,AI_AIOrActionBase::isNewChildIdx0,24, -0x0000007100d164a0,AI_AIOrActionBase::prepareEnter,348, -0x0000007100d165fc,AI_AIBase::getName,176, -0x0000007100d166ac,AI_AIOrActionBase::behaviorStuff,240, -0x0000007100d1679c,AI_AIOrActionBase::x,516, -0x0000007100d169a0,AI_AIBase::x_1,188, -0x0000007100d16a5c,AI_AIBase::prepareLeave,84, -0x0000007100d16ab0,AI_AIBase::setActorAIFlag,32, -0x0000007100d16ad0,AI_AIOrActionBase::callM12AndSetFlag40,68, -0x0000007100d16b14,AI_AIBase::prepareLeave_,240, -0x0000007100d16c04,sub_7100D16C04,60, +0x0000007100d1608c,AI_AIOrActionBase::preInit,808,_ZN4ksys3act2ai10ActionBase4initEPN4sead4HeapEb +0x0000007100d163b4,AI_AIOrActionBase::getClassName,176,_ZNK4ksys3act2ai10ActionBase12getClassNameEv +0x0000007100d16464,AI_AIOrActionBase::x_0,24,_ZNK4ksys3act2ai10ActionBase18isRootAiParamINot5Ev +0x0000007100d1647c,AI_AIOrActionBase::isActorInDeleteState,12,_ZNK4ksys3act2ai10ActionBase24isActorDeletedOrDeletingEv +0x0000007100d16488,AI_AIOrActionBase::isNewChildIdx0,24,_ZNK4ksys3act2ai10ActionBase24isActorGoingBackToRootAiEv +0x0000007100d164a0,AI_AIOrActionBase::prepareEnter,348,_ZN4ksys3act2ai10ActionBase5enterEPNS1_15InlineParamPackERKN4sead14SafeStringBaseIcEE +0x0000007100d165fc,AI_AIBase::getName,176,_ZNK4ksys3act2ai10ActionBase7getNameEv +0x0000007100d166ac,AI_AIOrActionBase::behaviorStuff,240,_ZN4ksys3act2ai10ActionBase22updateBehaviorsOnEnterEv +0x0000007100d1679c,AI_AIOrActionBase::x,516,_ZN4ksys3act2ai10ActionBase8takeOverEPS2_RKN4sead14SafeStringBaseIcEE +0x0000007100d169a0,AI_AIBase::x_1,188,_ZNK4ksys3act2ai10ActionBase10copyParamsEPNS1_15InlineParamPackEb +0x0000007100d16a5c,AI_AIBase::prepareLeave,84,_ZN4ksys3act2ai10ActionBase5leaveEv +0x0000007100d16ab0,AI_AIBase::setActorAIFlag,32,_ZN4ksys3act2ai10ActionBase16setRootAiFlagBitEi +0x0000007100d16ad0,AI_AIOrActionBase::callM12AndSetFlag40,68,_ZN4ksys3act2ai10ActionBase8reenter_EPS2_b +0x0000007100d16b14,AI_AIBase::prepareLeave_,240,_ZN4ksys3act2ai10ActionBase22updateBehaviorsOnLeaveEv +0x0000007100d16c04,sub_7100D16C04,60,_ZN4ksys3act2ai10ActionBase7oneShotEPNS1_15InlineParamPackE 0x0000007100d16c40,AI_AIOrActionBase::getActorGeneralParamList,16, 0x0000007100d16c50,AI_AIOrActionBase::sendMessageMaybe,12, 0x0000007100d16c5c,sub_7100D16C5C,12, @@ -73058,7 +73058,7 @@ 0x0000007100d175dc,ai::ParamPack::dtor,152,_ZN4ksys3act2ai9ParamPackD1Ev 0x0000007100d17674,ai::ParamPack::x,184,_ZN4ksys3act2ai9ParamPack4loadERKNS0_5ActorERKNS1_18ParamNameTypePairsEiPN4sead4HeapE 0x0000007100d1772c,ai::ParamPack::getAITreeVariablePointer,116,_ZNK4ksys3act2ai9ParamPack24getAITreeVariablePointerERKN4sead14SafeStringBaseIcEENS_14AIDefParamTypeEb -0x0000007100d177a0,ai::ParamPack::loadFromInlineParamPack,1132,_ZN4ksys3act2ai9ParamPack4copyEPNS1_15InlineParamPackEb +0x0000007100d177a0,ai::ParamPack::loadFromInlineParamPack,1132,_ZNK4ksys3act2ai9ParamPack4copyEPNS1_15InlineParamPackEb 0x0000007100d17c0c,ai::InlineParamPack::addInt,116,_ZN4ksys3act2ai15InlineParamPack6addIntEiRKN4sead14SafeStringBaseIcEEi 0x0000007100d17c80,ai::InlineParamPack::addFloat,116,_ZN4ksys3act2ai15InlineParamPack8addFloatEfRKN4sead14SafeStringBaseIcEEi 0x0000007100d17cf4,ai::InlineParamPack::addFloatArray,144,_ZN4ksys3act2ai15InlineParamPack7addVec3ERKN4sead7Vector3IfEERKNS3_14SafeStringBaseIcEEi @@ -74305,7 +74305,7 @@ 0x0000007100d6570c,ai::ActorAI::calc,1440, 0x0000007100d65cac,sub_7100D65CAC,16, 0x0000007100d65cbc,ai::ActorAI::x_0,156, -0x0000007100d65d58,ai::ActorAI::isActorInDeleteState,36, +0x0000007100d65d58,ai::ActorAI::isActorInDeleteState,36,_ZNK4ksys3act2ai6RootAi24isActorDeletedOrDeletingEv 0x0000007100d65d7c,ai::ActorAI::enter,160, 0x0000007100d65e1c,sub_7100D65E1C,892, 0x0000007100d66198,ai::ActorAI::leave,92, @@ -74323,8 +74323,8 @@ 0x0000007100d668c4,sub_7100D668C4,80, 0x0000007100d66914,sub_7100D66914,84, 0x0000007100d66968,sub_7100D66968,80, -0x0000007100d669b8,getDemoRootAIStr,36, -0x0000007100d669dc,getNullByte,12, +0x0000007100d669b8,getDemoRootAIStr,36,_ZN4ksys3act2ai16getDefaultAiNameEi +0x0000007100d669dc,getNullByte,12,_ZN4ksys3act2ai20getDefaultActionNameEi 0x0000007100d669e8,ai::ActorAI::behaviorStuff,96, 0x0000007100d66a48,ai::ActorAI::x_5,96, 0x0000007100d66aa8,sub_7100D66AA8,76, @@ -91458,7 +91458,7 @@ 0x00000071011aa068,ResourceAiprog::m5,8,_ZThn632_N4ksys3res9AIProgram9finalize_Ev 0x00000071011aa070,Aiprog::loadDefParameters,1556,_ZN4ksys3res9AIProgram14parseDefParamsEPNS1_10DefinitionEPvPN4sead4HeapERKN3agl3utl16ResParameterListEPtSD_ 0x00000071011aa684,sub_71011AA684,256,_ZN4ksys3res9AIProgram10Definition14addSInstParam_IN4sead14SafeStringBaseIcEEEEbiPKcPNS4_4HeapERKT_ -0x00000071011aa784,Aiprog::getActionsOrAIs,20,_ZNK4ksys3res9AIProgram15getActionsOrAIsENS1_12AIActionTypeE +0x00000071011aa784,Aiprog::getActionsOrAIs,20,_ZNK4ksys3res9AIProgram15getActionsOrAIsENS_3act2ai10ActionTypeE 0x00000071011aa798,sub_71011AA798,168,_ZNK4ksys3res9AIProgram13getSInstParamEPPKcRKNS1_10DefinitionERKN4sead14SafeStringBaseIcEE 0x00000071011aa840,Aiprog::x_2,208,_ZNK4ksys3res9AIProgram13getSInstParamEPN4sead14SafeStringBaseIcEERKNS1_10DefinitionERKS4_ 0x00000071011aa910,sub_71011AA910,156,_ZNK4ksys3res9AIProgram13getSInstParamEPPKiRKNS1_10DefinitionERKN4sead14SafeStringBaseIcEE? diff --git a/lib/sead b/lib/sead index 7bc4c090..fb3cc5c9 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit 7bc4c0907158f9be382017c03b339e7d33feac55 +Subproject commit fb3cc5c9de770284316ae87e65354d64eb757d9d diff --git a/src/Game/AI/Action/actionSetInstEventFlag.h b/src/Game/AI/Action/actionSetInstEventFlag.h index 4d36ae6d..e86ebe0f 100644 --- a/src/Game/AI/Action/actionSetInstEventFlag.h +++ b/src/Game/AI/Action/actionSetInstEventFlag.h @@ -12,7 +12,7 @@ public: explicit SetInstEventFlagAction(const InitArg& arg); ~SetInstEventFlagAction() override; - bool oneShot() override; + bool oneShot_() override; bool init_(sead::Heap* heap) override; void loadParams_() override; }; diff --git a/src/KingSystem/ActorSystem/actActor.h b/src/KingSystem/ActorSystem/actActor.h index c351e663..c623d4f2 100644 --- a/src/KingSystem/ActorSystem/actActor.h +++ b/src/KingSystem/ActorSystem/actActor.h @@ -43,6 +43,8 @@ public: const sead::TypedBitFlag& getStasisFlags() const { return mStasisFlags; } + void onAiEnter(const char* name, const char* context); + protected: /* 0x180 */ u8 TEMP_0x180[0x3D8]; // FIXME /* 0x558 */ ai::RootAi* mRootAi; diff --git a/src/KingSystem/ActorSystem/actAiAction.h b/src/KingSystem/ActorSystem/actAiAction.h index a7817196..cef4e366 100644 --- a/src/KingSystem/ActorSystem/actAiAction.h +++ b/src/KingSystem/ActorSystem/actAiAction.h @@ -11,7 +11,7 @@ public: explicit Action(const InitArg& arg); void calc() override; - bool isAction() const override { return true; } + ActionType getType() const override { return ActionType::Action; } protected: virtual void calc_() {} diff --git a/src/KingSystem/ActorSystem/actAiActionBase.cpp b/src/KingSystem/ActorSystem/actAiActionBase.cpp index ce814d5c..05d7e952 100644 --- a/src/KingSystem/ActorSystem/actAiActionBase.cpp +++ b/src/KingSystem/ActorSystem/actAiActionBase.cpp @@ -1,20 +1,205 @@ #include "KingSystem/ActorSystem/actAiActionBase.h" +#include "KingSystem/ActorSystem/actActorParam.h" +#include "KingSystem/ActorSystem/actAiRoot.h" +#include "KingSystem/Resource/resResourceAIProgram.h" namespace ksys::act::ai { ActionBase::ActionBase(const InitArg& arg) - : mActor{arg.actor}, mDefinitionIdx{u16(arg.def_idx)}, mRootIdx{u8(arg.root_idx)} {} + : mActor{arg.actor}, mDefinitionIdx{s16(arg.def_idx)}, mRootIdx{s8(arg.root_idx)} {} -bool ActionBase::isFinished() const { - return mFlags.isOn(Flag::Finished); +inline res::AIProgram* ActionBase::getAIProg() const { + return mActor->getParam()->getRes().mAIProgram; } -bool ActionBase::isFailed() const { - return mFlags.isOn(Flag::Failed); +bool ActionBase::init(sead::Heap* heap, bool skip_loading_map_or_tree_params) { + initFlags(getAIProg(), mDefinitionIdx, getType()); + + AIDefSet set; + set.dynamic_params.num_params = 0; + set.ai_tree_params.num_params = 0; + if (getType() == ActionType::Action) + AIClassDef::instance()->getDef(getClassName(), &set, AIDefType::Action); + else + AIClassDef::instance()->getDef(getClassName(), &set, AIDefType::AI); + + if (!initChildren(set, heap)) + return false; + + if (!skip_loading_map_or_tree_params) { + if (!mActor->getRootAi()->loadMapUnitParams(set.map_unit_params, heap)) + return false; + if (!mActor->getRootAi()->loadAITreeParams(set.ai_tree_params, heap)) + return false; + } + + if (set.dynamic_params.num_params > 0 && mFlags.isOff(Flag::DynamicParamChild)) { + if (!mParams.load(*mActor, set.dynamic_params, heap, AIDefInstParamKind::Dynamic)) + return false; + } + + loadParams_(); + return init_(heap); } -bool ActionBase::isFlag4Set() const { - return mFlags.isOn(Flag::_4); +void ActionBase::initFlags(res::AIProgram* aiprog, s32 def_idx, ActionType type) { + if (def_idx < 0) + return; + + if (aiprog->getActionsOrAIs(type)[def_idx].mTriggerAction) + mFlags.set(Flag::TriggerAction); + + if (aiprog->getActionsOrAIs(type)[def_idx].mDynamicParamChild) + mFlags.set(Flag::DynamicParamChild); +} + +const char* ActionBase::getClassName() const { + if (mDefinitionIdx < 0) { + if (mRootIdx < 0) + return ""; + return getDefaultName(getType(), mRootIdx); + } + + return getAIProg()->getAction(getType(), mDefinitionIdx).mClassName; +} + +bool ActionBase::isRootAiParamINot5() const { + return mActor->getRootAi()->getI() != 5; +} + +bool ActionBase::isActorDeletedOrDeleting() const { + return mActor->getRootAi()->isActorDeletedOrDeleting(); +} + +bool ActionBase::isActorGoingBackToRootAi() const { + return mActor->getRootAi()->mNewChildIdx == 0; +} + +void ActionBase::enter(InlineParamPack* params, const sead::SafeString& context) { + if (getType() == ActionType::Action || (getType() == ActionType::AI && getNumChildren() == 0)) { + mActor->onAiEnter(getName(), context.cstr()); + } + + resetFlags(); + if (params) + params->copyToParamPack(mParams); + updateBehaviorsOnEnter(); + enter_(params); +} + +const char* ActionBase::getName() const { + if (mDefinitionIdx >= 0) + return getAIProg()->getAction(getType(), mDefinitionIdx).mName; + + if (mRootIdx >= 0) + return getDefaultName(getType(), mRootIdx); + + return ""; +} + +void ActionBase::updateBehaviorsOnEnter() { + if (!mActor) + return; + + const sead::Buffer* indices; + if (mDefinitionIdx < 0) { + if (mRootIdx != 0 || getType() != ActionType::AI) + return; + indices = &getAIProg()->getDemoBehaviorIndices(); + } else { + indices = &getAIProg()->getAction(getType(), mDefinitionIdx).mBehaviorIndices; + } + + auto* root = mActor->getRootAi(); + for (auto indice : *indices) + root->setBehavior(root->getBehaviors().classes[indice]); +} + +bool ActionBase::takeOver(ActionBase* src, const sead::SafeString& context) { + bool ret = false; + + if (src->mDefinitionIdx == mDefinitionIdx && src->mRootIdx == mRootIdx) { + if (getType() == ActionType::Action) + mActor->onAiEnter(getName(), context.cstr()); + + // Copy the flags. + mFlags = src->mFlags; + + // Copy the param pack. + InlineParamPack pack; + src->copyParams(&pack, true); + pack.copyToParamPack(mParams); + + // Transition. + if (auto* child = getCurrentChild()) + child->leave(); + updateBehaviorsOnEnter(); + ret = reenter(src, context); + } + + mActor->getRootAi()->_16c.set(RootAiFlag::_100); + return ret; +} + +void ActionBase::copyParams(InlineParamPack* dest, bool x) const { + auto* action = this; + while (action->mFlags.isOff(Flag::_80)) { + action->mParams.copy(dest, x); + if (action->mFlags.isOff(Flag::DynamicParamChild)) + return; + action = action->getCurrentChild(); + if (!action) + return; + } + + for (s32 i = 0, n = action->getNumChildren(); i < n; ++i) { + action->getChild(i)->copyParams(dest, x); + } +} + +void ActionBase::leave() { + if (auto* child = getCurrentChild()) + child->leave(); + + updateBehaviorsOnLeave(); + leave_(); + postLeave(); +} + +void ActionBase::setRootAiFlagBit(int bit) { + mActor->getRootAi()->_16c.set(RootAiFlag(1u << bit)); +} + +bool ActionBase::reenter_(ActionBase* other, bool x) { + if (x) + return true; + enter_(nullptr); + mFlags.set(Flag::_40); + return true; +} + +void ActionBase::updateBehaviorsOnLeave() { + if (!mActor) + return; + + const sead::Buffer* indices; + if (mDefinitionIdx < 0) { + if (mRootIdx != 0 || getType() != ActionType::AI) + return; + indices = &getAIProg()->getDemoBehaviorIndices(); + } else { + indices = &getAIProg()->getAction(getType(), mDefinitionIdx).mBehaviorIndices; + } + + auto* root = mActor->getRootAi(); + for (auto indice : *indices) + root->resetBehavior(root->getBehaviors().classes[indice]); +} + +bool ActionBase::oneShot(InlineParamPack* params) { + if (params) + params->copyToParamPack(mParams); + return oneShot_(); } void ActionBase::setFinished() { diff --git a/src/KingSystem/ActorSystem/actAiActionBase.h b/src/KingSystem/ActorSystem/actAiActionBase.h index 4851ecb4..b67b7c9c 100644 --- a/src/KingSystem/ActorSystem/actAiActionBase.h +++ b/src/KingSystem/ActorSystem/actAiActionBase.h @@ -1,18 +1,30 @@ #pragma once #include +#include #include #include #include "KingSystem/ActorSystem/actActor.h" #include "KingSystem/ActorSystem/actAiParam.h" #include "KingSystem/Utils/Types.h" +namespace ksys::res { +class AIProgram; +} + namespace ksys::act { class Actor; namespace ai { +enum class ActionType { + AI = 0, + Action = 1, +}; + +enum class RootAiFlag : u16; + /// Base class for actions and AIs, which can be seen as looping actions. class ActionBase { SEAD_RTTI_BASE(ActionBase) @@ -28,17 +40,23 @@ public: explicit ActionBase(const InitArg& arg); virtual ~ActionBase() = default; - const char* getName() const; - bool init(sead::Heap* heap, bool load_map_or_tree_params); + bool init(sead::Heap* heap, bool skip_loading_map_or_tree_params); + void enter(InlineParamPack* params, const sead::SafeString& context); + bool takeOver(ActionBase* src, const sead::SafeString& context); + void leave(); + bool oneShot(InlineParamPack* params); - virtual bool isFailed() const; - virtual bool isFinished() const; - virtual bool isFlag4Set() const; + const char* getClassName() const; + const char* getName() const; + + virtual bool isFailed() const { return mFlags.isOn(Flag::Failed); } + virtual bool isFinished() const { return mFlags.isOn(Flag::Finished); } + virtual bool isFlag4Set() const { return mFlags.isOn(Flag::_4); } virtual bool m7() { return false; } virtual bool m8() { return false; } virtual void m9() {} - virtual bool oneShot() { return true; } + virtual bool oneShot_() { return true; } virtual bool init_(sead::Heap* heap) { return true; } virtual void enter_(InlineParamPack* params) {} virtual bool reenter_(ActionBase* other, bool x); @@ -53,10 +71,12 @@ public: virtual void* m22() { return nullptr; } virtual void getParams(ParamNameTypePairs* pairs, bool update_use_count) const; virtual s32 getNumChildren() const { return 0; } - virtual bool m25() { return true; } + virtual bool initChildren(const AIDefSet& set, sead::Heap* heap) { return true; } virtual ActionBase* getCurrentChild() const { return nullptr; } - virtual bool isAction() const = 0; - virtual bool reenter(ActionBase* other) { return reenter_(other, false); } + virtual ActionType getType() const = 0; + virtual bool reenter(ActionBase* other, const sead::SafeString& context) { + return reenter_(other, false); + } virtual void postLeave() {} virtual ActionBase* getChild(s32 idx) const { return nullptr; } @@ -72,17 +92,38 @@ protected: _80 = 0x80, }; + bool isRootAiParamINot5() const; + bool isActorDeletedOrDeleting() const; + bool isActorGoingBackToRootAi() const; + + void copyParams(InlineParamPack* dest, bool x) const; + void setFinished(); void setFailed(); + void setRootAiFlagBit(int bit); + void setRootAiFlag(RootAiFlag flag) { setRootAiFlagBit(sead::log2(u32(flag))); } + + void resetFlags() { + mFlags.reset(Flag::Failed); + mFlags.reset(Flag::Finished); + mFlags.reset(Flag::_4); + } + + res::AIProgram* getAIProg() const; template void getParamStatic(ParamRef* value, const sead::SafeString& key); Actor* mActor; ParamPack mParams; - u16 mDefinitionIdx; - u8 mRootIdx; + s16 mDefinitionIdx; + s8 mRootIdx; sead::TypedBitFlag mFlags; + +private: + void initFlags(res::AIProgram* aiprog, s32 def_idx, ActionType type); + void updateBehaviorsOnEnter(); + void updateBehaviorsOnLeave(); }; KSYS_CHECK_SIZE_NX150(ActionBase, 0x20); diff --git a/src/KingSystem/ActorSystem/actAiAi.h b/src/KingSystem/ActorSystem/actAiAi.h index 5a3fd9bf..df476277 100644 --- a/src/KingSystem/ActorSystem/actAiAi.h +++ b/src/KingSystem/ActorSystem/actAiAi.h @@ -17,10 +17,10 @@ public: void* m22() override; void getParams(ParamNameTypePairs* pairs, bool update_use_count) const override; s32 getNumChildren() const override { return mChildren.size(); } - bool m25() override; + bool initChildren(const AIDefSet& set, sead::Heap* heap) override; ActionBase* getCurrentChild() const override; - bool isAction() const override { return false; } - bool reenter(ActionBase* other) override; + ActionType getType() const override { return ActionType::AI; } + bool reenter(ActionBase* other, const sead::SafeString& context) override; void postLeave() override { updateChildIdx(InvalidIdx); } ActionBase* getChild(s32 idx) const override { return mChildren[idx]; } virtual const char* getPreviousName(); diff --git a/src/KingSystem/ActorSystem/actAiParam.cpp b/src/KingSystem/ActorSystem/actAiParam.cpp index abb4fd3d..6532bb48 100644 --- a/src/KingSystem/ActorSystem/actAiParam.cpp +++ b/src/KingSystem/ActorSystem/actAiParam.cpp @@ -83,7 +83,7 @@ void* ParamPack::getAITreeVariablePointer(const sead::SafeString& key, AIDefPara return getVariable(key, type, x); } -void ParamPack::copy(InlineParamPack* dest, bool x) { +void ParamPack::copy(InlineParamPack* dest, bool x) const { for (auto* param = mParams; param; param = param->next) { if (!param->data || !param->used) continue; diff --git a/src/KingSystem/ActorSystem/actAiParam.h b/src/KingSystem/ActorSystem/actAiParam.h index 058e1262..bb9ea76a 100644 --- a/src/KingSystem/ActorSystem/actAiParam.h +++ b/src/KingSystem/ActorSystem/actAiParam.h @@ -82,7 +82,7 @@ public: bool load(const Actor& actor, const ParamNameTypePairs& pairs, s32 count, sead::Heap* heap); void* getAITreeVariablePointer(const sead::SafeString& key, AIDefParamType type, bool x = false) const; - void copy(InlineParamPack* dest, bool x); + void copy(InlineParamPack* dest, bool x) const; void getPairs(ParamNameTypePairs* pairs, bool update_use_count) const; bool getString(sead::SafeString* value, const sead::SafeString& key) const; @@ -115,6 +115,9 @@ struct InlineParam { KSYS_CHECK_SIZE_NX150(InlineParam, 0x50); struct InlineParamPack { + InlineParamPack() = default; + KSYS_ALWAYS_INLINE ~InlineParamPack() = default; + InlineParam& getParam(s32 idx) { if (idx < 0) { idx = count; @@ -151,7 +154,7 @@ struct InlineParamPack { static constexpr s32 NumParamsMax = 32; InlineParam params[NumParamsMax]; - int count; + int count = 0; }; KSYS_CHECK_SIZE_NX150(InlineParamPack, 0xA08); diff --git a/src/KingSystem/ActorSystem/actAiRoot.cpp b/src/KingSystem/ActorSystem/actAiRoot.cpp index 1098c634..9498c151 100644 --- a/src/KingSystem/ActorSystem/actAiRoot.cpp +++ b/src/KingSystem/ActorSystem/actAiRoot.cpp @@ -24,4 +24,19 @@ bool RootAi::loadAITreeParams(const AIDef& def, sead::Heap* heap) { return mAiTreeParams.load(*mActor, def, heap, AIDefInstParamKind::AITree); } +bool RootAi::isActorDeletedOrDeleting() const { + return mActor->isDeletedOrDeleting(); +} + +const char* getDefaultAiName(s32 root_idx) { + static constexpr const char* names[] = {"DemoRootAI", "Root"}; + if (root_idx >= 2) + return ""; + return names[root_idx]; +} + +const char* getDefaultActionName(s32) { + return ""; +} + } // namespace ksys::act::ai diff --git a/src/KingSystem/ActorSystem/actAiRoot.h b/src/KingSystem/ActorSystem/actAiRoot.h index fbb46eeb..54c9efbe 100644 --- a/src/KingSystem/ActorSystem/actAiRoot.h +++ b/src/KingSystem/ActorSystem/actAiRoot.h @@ -1,5 +1,6 @@ #pragma once +#include #include "KingSystem/ActorSystem/actAiAi.h" #include "KingSystem/ActorSystem/actAiParam.h" #include "KingSystem/Utils/Types.h" @@ -24,12 +25,15 @@ public: void finalize(); -private: - sead::Buffer classes; + sead::Buffer classes; // TODO: rename - sead::Buffer x; + sead::Buffer x; // TODO: rename - sead::Buffer y; + sead::Buffer y; +}; + +enum class RootAiFlag : u16 { + _100 = 0x100, // 8 }; class RootAi : public Ai, public IRootAi { @@ -47,11 +51,23 @@ public: const ParamPack& getMapUnitParams() const { return mMapUnitParams; } const ParamPack& getAiTreeParams() const { return mAiTreeParams; } + u32 getI() const { return mI; } + bool isActorDeletedOrDeleting() const; + + const ClassContainer& getActions() const { return mActions; } + const ClassContainer& getAis() const { return mAis; } + const ClassContainer& getBehaviors() const { return mBehaviors; } + const ClassContainer& getQueries() const { return mQueries; } bool loadMapUnitParams(const AIDef& def, sead::Heap* heap); bool loadAITreeParams(const AIDef& def, sead::Heap* heap); + void setBehavior(Behavior* behavior); + void resetBehavior(Behavior* behavior); + private: + friend class ActionBase; + // TODO: rename and put this in a different translation unit struct SomeStruct { SomeStruct(); @@ -72,7 +88,7 @@ private: sead::SafeArray mBehaviorsByStopAndCalcTiming[2]{}; void* _138{}; SomeStruct* _140{}; - u32 mMA_I{}; + u32 mI{}; u16 mAt{}; u8 _14e{}; void* _150{}; @@ -80,11 +96,20 @@ private: void* _160{}; // TODO: is this really an atomic? sead::Atomic _168 = 1.0; - u16 _16c{}; + sead::TypedBitFlag _16c; u16 _16e{}; ParamPack mMapUnitParams; ParamPack mAiTreeParams; }; KSYS_CHECK_SIZE_NX150(RootAi, 0x180); +const char* getDefaultAiName(s32 root_idx); +const char* getDefaultActionName(s32 idx); + +inline const char* getDefaultName(ActionType type, s32 idx) { + if (type == ActionType::AI) + return getDefaultAiName(idx); + return getDefaultActionName(idx); +} + } // namespace ksys::act::ai diff --git a/src/KingSystem/Resource/resResourceAIProgram.cpp b/src/KingSystem/Resource/resResourceAIProgram.cpp index 242fb42b..2d5ceef4 100644 --- a/src/KingSystem/Resource/resResourceAIProgram.cpp +++ b/src/KingSystem/Resource/resResourceAIProgram.cpp @@ -1,6 +1,7 @@ #include "KingSystem/Resource/resResourceAIProgram.h" #include #include +#include "KingSystem/ActorSystem/actAiActionBase.h" #include "KingSystem/ActorSystem/actAiClassDef.h" #include "KingSystem/Resource/resCurrentResNameMgr.h" #include "KingSystem/Utils/HeapUtil.h" @@ -11,8 +12,9 @@ AIProgram::AIProgram() : ParamIO("aiprog", 0) {} AIProgram::~AIProgram() = default; -const sead::Buffer& AIProgram::getActionsOrAIs(AIActionType type) const { - return type == AIActionType::AI ? mAIs : mActions; +const sead::Buffer& +AIProgram::getActionsOrAIs(act::ai::ActionType type) const { + return type == act::ai::ActionType::AI ? mAIs : mActions; } void AIProgram::doCreate_(u8*, u32, sead::Heap*) { diff --git a/src/KingSystem/Resource/resResourceAIProgram.h b/src/KingSystem/Resource/resResourceAIProgram.h index 9fdf53d9..242001ce 100644 --- a/src/KingSystem/Resource/resResourceAIProgram.h +++ b/src/KingSystem/Resource/resResourceAIProgram.h @@ -9,16 +9,15 @@ #include "KingSystem/Utils/ParamIO.h" #include "KingSystem/Utils/Types.h" +namespace ksys::act::ai { +enum class ActionType : int; +} + namespace ksys::res { class AIProgram : public ParamIO, public Resource { SEAD_RTTI_OVERRIDE(AIProgram, Resource) public: - enum class AIActionType { - AI = 0, - Action = 1, - }; - struct Definition { const agl::utl::ParameterBase* findSInstParam(u32 name_hash) const; const agl::utl::ParameterBase* findSInstParam(const sead::SafeString& name) const; @@ -60,10 +59,17 @@ public: AIProgram(); ~AIProgram() override; - const sead::Buffer& getActionsOrAIs(AIActionType type) const; + const sead::Buffer& getActionsOrAIs(act::ai::ActionType type) const; const sead::Buffer& getBehaviors() const { return mBehaviors; } const sead::Buffer& getQueries() const { return mQueries; } + const AIActionDef& getAction(act::ai::ActionType type, s32 index) const { + return getActionsOrAIs(type)[index]; + } + + const sead::Buffer& getDemoAiActionIndices() const { return mDemoAIActionIndices; } + const sead::Buffer& getDemoBehaviorIndices() const { return mDemoBehaviorIndices; } + bool getSInstParam(const char** value, const Definition& def, const sead::SafeString& param_name) const; bool getSInstParam(sead::SafeString* value, const Definition& def,