From 8a22f0bb50bbe3aa7973d80ff1e4cc62c369f9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 17 Dec 2020 23:14:09 +0100 Subject: [PATCH] ksys/act: Add more ActionBase, Ai and RootAi functions --- data/uking_functions.csv | 101 ++++++------ lib/sead | 2 +- src/Game/AI/Action/actionSetLinkTagBasic.cpp | 4 +- src/Game/AI/Action/actionSetLinkTagBasic.h | 2 +- .../ActorSystem/actAiActionBase.cpp | 151 +++++++++++++++++- src/KingSystem/ActorSystem/actAiActionBase.h | 123 +++++++++++++- src/KingSystem/ActorSystem/actAiAi.cpp | 60 +++++++ src/KingSystem/ActorSystem/actAiAi.h | 4 + src/KingSystem/ActorSystem/actAiParam.h | 16 +- src/KingSystem/ActorSystem/actAiQuery.cpp | 1 + src/KingSystem/ActorSystem/actAiRoot.cpp | 114 +++++++++++++ src/KingSystem/ActorSystem/actAiRoot.h | 23 ++- .../Resource/resResourceAIProgram.h | 4 + 13 files changed, 530 insertions(+), 75 deletions(-) diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 9189ab27..13882fd3 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -73005,50 +73005,50 @@ 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 +0x0000007100d16ab0,AI_AIBase::setActorAIFlag,32,_ZNK4ksys3act2ai10ActionBase16setRootAiFlagBitEi 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, +0x0000007100d16c40,AI_AIOrActionBase::getActorGeneralParamList,16,_ZNK4ksys3act2ai10ActionBase13getGParamListEv 0x0000007100d16c50,AI_AIOrActionBase::sendMessageMaybe,12, 0x0000007100d16c5c,sub_7100D16C5C,12, -0x0000007100d16c68,ai::ActorAI::getCurrentAction,144, +0x0000007100d16c68,ai::ActorAI::getCurrentAction,144,_ZN4ksys3act2ai10ActionBase16getCurrentActionEv 0x0000007100d16cf8,ai::ActorAI::x_1,92, 0x0000007100d16d54,ai::ActorAI::x_2,92, 0x0000007100d16db0,AI_AIOrActionBase::setFinished,20,_ZN4ksys3act2ai10ActionBase11setFinishedEv 0x0000007100d16dc4,AI_AIOrActionBase::setFailed,20,_ZN4ksys3act2ai10ActionBase9setFailedEv -0x0000007100d16dd8,AI_AIOrActionBase::appendName,392, -0x0000007100d16f60,AI_AIOrActionBase::m23,12, -0x0000007100d16f6c,sub_7100D16F6C,32, -0x0000007100d16f8c,sub_7100D16F8C,36, -0x0000007100d16fb0,sub_7100D16FB0,116, -0x0000007100d17024,AI_AIOrActionBase::getStringStatic,116, -0x0000007100d17098,AI_AIOrActionBase::getIntStatic,116, -0x0000007100d1710c,AI_AIOrActionBase::getFloatStatic,116, -0x0000007100d17180,AI_AIOrActionBase::getVec3Static,116, -0x0000007100d171f4,AI_AIOrActionBase::getBoolStatic,116, -0x0000007100d17268,AI_AIOrActionBase::isAction,12, -0x0000007100d17274,AI_AIOrActionBase::getStringMapUnit,12, -0x0000007100d17280,AI_AIOrActionBase::getIntMapUnit,12, -0x0000007100d1728c,AI_AIOrActionBase::getFloatMapUnit,12, -0x0000007100d17298,AI_AIOrActionBase::getVec3MapUnit,12, -0x0000007100d172a4,AI_AIOrActionBase::getBoolMapUnit,12, -0x0000007100d172b0,AI_AIOrActionBase::getStringAITree,12, -0x0000007100d172bc,AI_AIOrActionBase::getIntAITreeVars,12, -0x0000007100d172c8,sub_7100D172C8,12, -0x0000007100d172d4,AI_AIOrActionBase::getVec3AITree,12, -0x0000007100d172e0,AI_AIOrActionBase::getBoolAITree,12, -0x0000007100d172ec,AI_AIOrActionBase::getAITreeVariablePointer,12, -0x0000007100d172f8,AI_AIOrActionBase::getDefaultString,16, -0x0000007100d17308,AI_AIOrActionBase::getDefaultInt,12, -0x0000007100d17314,sub_7100D17314,12, -0x0000007100d17320,AI_AIOrActionBase::getDefaultVec3,16, -0x0000007100d17330,AI_AIOrActionBase::getDefaultBool,12, -0x0000007100d1733c,ai::getDefaultBaseProcLink,12, -0x0000007100d17348,sub_7100D17348,16, -0x0000007100d17358,ai::getDefaultBaseProcHandle,16, -0x0000007100d17368,sub_7100D17368,12, -0x0000007100d17374,AI_AIOrActionBase::getDefaultString20,12, +0x0000007100d16dd8,AI_AIOrActionBase::appendName,392,_ZNK4ksys3act2ai10ActionBase14getCurrentNameEPN4sead22BufferedSafeStringBaseIcEEPS2_ +0x0000007100d16f60,AI_AIOrActionBase::m23,12,_ZNK4ksys3act2ai10ActionBase9getParamsEPNS1_18ParamNameTypePairsEb +0x0000007100d16f6c,sub_7100D16F6C,32,_ZNK4ksys3act2ai10ActionBase18resetRootAiFlagBitEi +0x0000007100d16f8c,sub_7100D16F8C,36,_ZNK4ksys3act2ai10ActionBase18testRootAiFlag2BitEi +0x0000007100d16fb0,sub_7100D16FB0,116,_ZNK4ksys3act2ai10ActionBase14getStaticParamIPKcEEbPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d17024,AI_AIOrActionBase::getStringStatic,116,_ZNK4ksys3act2ai10ActionBase14getStaticParamIN4sead14SafeStringBaseIcEEEEbPT_RKS6_ +0x0000007100d17098,AI_AIOrActionBase::getIntStatic,116,_ZNK4ksys3act2ai10ActionBase14getStaticParamIPKiEEbPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d1710c,AI_AIOrActionBase::getFloatStatic,116,_ZNK4ksys3act2ai10ActionBase14getStaticParamIPKfEEbPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d17180,AI_AIOrActionBase::getVec3Static,116,_ZNK4ksys3act2ai10ActionBase14getStaticParamIPKN4sead7Vector3IfEEEEbPT_RKNS4_14SafeStringBaseIcEE +0x0000007100d171f4,AI_AIOrActionBase::getBoolStatic,116,_ZNK4ksys3act2ai10ActionBase14getStaticParamIPKbEEbPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d17268,AI_AIOrActionBase::isAction,12,_ZNK4ksys3act2ai10ActionBase15logMissingParamERKN4sead14SafeStringBaseIcEE +0x0000007100d17274,AI_AIOrActionBase::getStringMapUnit,12,_ZNK4ksys3act2ai10ActionBase15getMapUnitParamIN4sead14SafeStringBaseIcEEEEbPT_RKS6_ +0x0000007100d17280,AI_AIOrActionBase::getIntMapUnit,12,_ZNK4ksys3act2ai10ActionBase15getMapUnitParamIPKiEEbPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d1728c,AI_AIOrActionBase::getFloatMapUnit,12,_ZNK4ksys3act2ai10ActionBase15getMapUnitParamIPKfEEbPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d17298,AI_AIOrActionBase::getVec3MapUnit,12,_ZNK4ksys3act2ai10ActionBase15getMapUnitParamIPKN4sead7Vector3IfEEEEbPT_RKNS4_14SafeStringBaseIcEE +0x0000007100d172a4,AI_AIOrActionBase::getBoolMapUnit,12,_ZNK4ksys3act2ai10ActionBase15getMapUnitParamIPKbEEbPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d172b0,AI_AIOrActionBase::getStringAITree,12,_ZNK4ksys3act2ai10ActionBase17getAITreeVariableIN4sead14SafeStringBaseIcEEEEbPPT_RKS6_ +0x0000007100d172bc,AI_AIOrActionBase::getIntAITreeVars,12,_ZNK4ksys3act2ai10ActionBase17getAITreeVariableIiEEbPPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d172c8,sub_7100D172C8,12,_ZNK4ksys3act2ai10ActionBase17getAITreeVariableIfEEbPPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d172d4,AI_AIOrActionBase::getVec3AITree,12,_ZNK4ksys3act2ai10ActionBase17getAITreeVariableIN4sead7Vector3IfEEEEbPPT_RKNS4_14SafeStringBaseIcEE +0x0000007100d172e0,AI_AIOrActionBase::getBoolAITree,12,_ZNK4ksys3act2ai10ActionBase17getAITreeVariableIbEEbPPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d172ec,AI_AIOrActionBase::getAITreeVariablePointer,12,_ZNK4ksys3act2ai10ActionBase17getAITreeVariableIvEEbPPT_RKN4sead14SafeStringBaseIcEE +0x0000007100d172f8,AI_AIOrActionBase::getDefaultString,16,_ZN4ksys3act2ai16getDefaultStringEv +0x0000007100d17308,AI_AIOrActionBase::getDefaultInt,12,_ZN4ksys3act2ai13getDefaultIntEv +0x0000007100d17314,sub_7100D17314,12,_ZN4ksys3act2ai15getDefaultFloatEv +0x0000007100d17320,AI_AIOrActionBase::getDefaultVec3,16,_ZN4ksys3act2ai14getDefaultVec3Ev +0x0000007100d17330,AI_AIOrActionBase::getDefaultBool,12,_ZN4ksys3act2ai14getDefaultBoolEv +0x0000007100d1733c,ai::getDefaultBaseProcLink,12,_ZN4ksys3act2ai22getDefaultBaseProcLinkEv +0x0000007100d17348,sub_7100D17348,16,_ZN4ksys3act2ai26getDefaultMesTransceiverIdEv +0x0000007100d17358,ai::getDefaultBaseProcHandle,16,_ZN4ksys3act2ai24getDefaultBaseProcHandleEv +0x0000007100d17368,sub_7100D17368,12,_ZN4ksys3act2ai14getDefaultRailEv +0x0000007100d17374,AI_AIOrActionBase::getDefaultString20,12,_ZN4ksys3act2ai18getDefaultString32Ev 0x0000007100d17380,AI_AIOrActionBase::rtti1,112,_ZNK4ksys3act2ai10ActionBase27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100d173f0,AI_AIOrActionBase::rtti2,92,_ZNK4ksys3act2ai10ActionBase18getRuntimeTypeInfoEv 0x0000007100d1744c,AI_AIOrActionBase::dtorDelete,52,_ZN4ksys3act2ai10ActionBaseD0Ev @@ -74310,19 +74310,20 @@ 0x0000007100d65e1c,sub_7100D65E1C,892, 0x0000007100d66198,ai::ActorAI::leave,92, 0x0000007100d661f4,ai::ActorAI::m16,788, -0x0000007100d66508,ai::ActorAI::getVariableString,156, -0x0000007100d665a4,sub_7100D665A4,80, -0x0000007100d665f4,ai::ParamPack::getFloatMapUnit,80, -0x0000007100d66644,sub_7100D66644,80, -0x0000007100d66694,ai::ActorAI::getMapUnitBool,80, -0x0000007100d66730,sub_7100D66730,80, -0x0000007100d66780,sub_7100D66780,80, -0x0000007100d667d0,ai::ActorAI::getVariable,84, -0x0000007100d66824,sub_7100D66824,80, -0x0000007100d66874,ai::ActorAI::getAITreeVariablePointer,80, -0x0000007100d668c4,sub_7100D668C4,80, -0x0000007100d66914,sub_7100D66914,84, -0x0000007100d66968,sub_7100D66968,80, +0x0000007100d66508,ai::ActorAI::getVariableString,156,_ZNK4ksys3act2ai6RootAi15getMapUnitParamEPN4sead14SafeStringBaseIcEERKS5_ +0x0000007100d665a4,sub_7100D665A4,80,_ZNK4ksys3act2ai6RootAi15getMapUnitParamEPPKiRKN4sead14SafeStringBaseIcEE +0x0000007100d665f4,ai::ParamPack::getFloatMapUnit,80,_ZNK4ksys3act2ai6RootAi15getMapUnitParamEPPKfRKN4sead14SafeStringBaseIcEE +0x0000007100d66644,sub_7100D66644,80,_ZNK4ksys3act2ai6RootAi15getMapUnitParamEPPKN4sead7Vector3IfEERKNS3_14SafeStringBaseIcEE +0x0000007100d66694,ai::ActorAI::getMapUnitBool,80,_ZNK4ksys3act2ai6RootAi15getMapUnitParamEPPKbRKN4sead14SafeStringBaseIcEE +0x0000007100d666e4,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPN4sead14SafeStringBaseIcEERKS5_,0x4c,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPN4sead14SafeStringBaseIcEERKS5_ +0x0000007100d66730,sub_7100D66730,80,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPiRKN4sead14SafeStringBaseIcEE +0x0000007100d66780,sub_7100D66780,80,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPfRKN4sead14SafeStringBaseIcEE +0x0000007100d667d0,ai::ActorAI::getVariable,84,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPN4sead7Vector3IfEERKNS3_14SafeStringBaseIcEE +0x0000007100d66824,sub_7100D66824,80,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPbRKN4sead14SafeStringBaseIcEE +0x0000007100d66874,ai::ActorAI::getAITreeVariablePointer,80,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPvRKN4sead14SafeStringBaseIcEE +0x0000007100d668c4,sub_7100D668C4,80,_ZNK4ksys3act2ai6RootAi17getAITreeVariableEPPjRKN4sead14SafeStringBaseIcEE +0x0000007100d66914,sub_7100D66914,84,_ZNK4ksys3act2ai6RootAi18getAITreeVariable2EPPN4sead7Vector3IfEERKNS3_14SafeStringBaseIcEE +0x0000007100d66968,sub_7100D66968,80,_ZNK4ksys3act2ai6RootAi18getAITreeVariable2EPPbRKN4sead14SafeStringBaseIcEE 0x0000007100d669b8,getDemoRootAIStr,36,_ZN4ksys3act2ai16getDefaultAiNameEi 0x0000007100d669dc,getNullByte,12,_ZN4ksys3act2ai20getDefaultActionNameEi 0x0000007100d669e8,ai::ActorAI::behaviorStuff,96, @@ -92256,8 +92257,8 @@ 0x00000071011ddf14,AI_AIBase::ctor,64,_ZN4ksys3act2ai2AiC1ERKNS1_10ActionBase7InitArgE 0x00000071011ddf54,AI_AIBase::dtor,84,_ZN4ksys3act2ai2AiD1Ev 0x00000071011ddfa8,AI_AIBase::dtorDelete,92,_ZN4ksys3act2ai2AiD0Ev -0x00000071011de004,AI_AIBase::m25,132, -0x00000071011de088,AI_AIBase::initChildStates,580, +0x00000071011de004,AI_AIBase::m25,132,_ZN4ksys3act2ai2Ai12initChildrenERKNS_8AIDefSetEPN4sead4HeapE +0x00000071011de088,AI_AIBase::initChildStates,580,_ZN4ksys3act2ai2Ai13initChildren_EiPPKcRN4sead6BufferItEEPNS6_4HeapE 0x00000071011de2cc,AI_AIBase::x_0,340, 0x00000071011de420,AI_AIBase::calcRecursively,156,_ZN4ksys3act2ai2Ai4calcEv 0x00000071011de4bc,AI_AIBase::x,76, diff --git a/lib/sead b/lib/sead index fb3cc5c9..7978b9ee 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit fb3cc5c9de770284316ae87e65354d64eb757d9d +Subproject commit 7978b9ee0debb7d48cdc0a09a31cf278f7f91ef3 diff --git a/src/Game/AI/Action/actionSetLinkTagBasic.cpp b/src/Game/AI/Action/actionSetLinkTagBasic.cpp index ab334e56..19d4e40d 100644 --- a/src/Game/AI/Action/actionSetLinkTagBasic.cpp +++ b/src/Game/AI/Action/actionSetLinkTagBasic.cpp @@ -8,7 +8,7 @@ SetLinkTagBasicAction::SetLinkTagBasicAction(const InitArg& arg) : ksys::act::ai SetLinkTagBasicAction::~SetLinkTagBasicAction() = default; void SetLinkTagBasicAction::enter_(ksys::act::ai::InlineParamPack* params) { - if (IsOn.value()) + if (*IsOn) mActor->emitBasicSigOn(); else mActor->emitBasicSigOff(); @@ -17,7 +17,7 @@ void SetLinkTagBasicAction::enter_(ksys::act::ai::InlineParamPack* params) { } void SetLinkTagBasicAction::loadParams_() { - getParamStatic(&IsOn, "IsOn"); + getStaticParam(&IsOn, "IsOn"); } } // namespace uking::action diff --git a/src/Game/AI/Action/actionSetLinkTagBasic.h b/src/Game/AI/Action/actionSetLinkTagBasic.h index 75fd0f03..c0bb808b 100644 --- a/src/Game/AI/Action/actionSetLinkTagBasic.h +++ b/src/Game/AI/Action/actionSetLinkTagBasic.h @@ -16,7 +16,7 @@ public: void loadParams_() override; private: - ksys::act::ai::ParamRef IsOn; + const bool* IsOn{}; }; KSYS_CHECK_SIZE_NX150(SetLinkTagBasicAction, 0x28); diff --git a/src/KingSystem/ActorSystem/actAiActionBase.cpp b/src/KingSystem/ActorSystem/actAiActionBase.cpp index 05d7e952..6de513f2 100644 --- a/src/KingSystem/ActorSystem/actAiActionBase.cpp +++ b/src/KingSystem/ActorSystem/actAiActionBase.cpp @@ -1,7 +1,10 @@ #include "KingSystem/ActorSystem/actAiActionBase.h" #include "KingSystem/ActorSystem/actActorParam.h" +#include "KingSystem/ActorSystem/actAiAction.h" #include "KingSystem/ActorSystem/actAiRoot.h" #include "KingSystem/Resource/resResourceAIProgram.h" +#include "KingSystem/Utils/InitTimeInfo.h" +#include "KingSystem/ActorSystem/actActor.h" namespace ksys::act::ai { @@ -12,6 +15,10 @@ inline res::AIProgram* ActionBase::getAIProg() const { return mActor->getParam()->getRes().mAIProgram; } +inline auto& ActionBase::getDef() const { + return getAIProg()->getAction(getType(), mDefinitionIdx); +} + bool ActionBase::init(sead::Heap* heap, bool skip_loading_map_or_tree_params) { initFlags(getAIProg(), mDefinitionIdx, getType()); @@ -60,7 +67,7 @@ const char* ActionBase::getClassName() const { return getDefaultName(getType(), mRootIdx); } - return getAIProg()->getAction(getType(), mDefinitionIdx).mClassName; + return getDef().mClassName; } bool ActionBase::isRootAiParamINot5() const { @@ -89,7 +96,7 @@ void ActionBase::enter(InlineParamPack* params, const sead::SafeString& context) const char* ActionBase::getName() const { if (mDefinitionIdx >= 0) - return getAIProg()->getAction(getType(), mDefinitionIdx).mName; + return getDef().mName; if (mRootIdx >= 0) return getDefaultName(getType(), mRootIdx); @@ -107,7 +114,7 @@ void ActionBase::updateBehaviorsOnEnter() { return; indices = &getAIProg()->getDemoBehaviorIndices(); } else { - indices = &getAIProg()->getAction(getType(), mDefinitionIdx).mBehaviorIndices; + indices = &getDef().mBehaviorIndices; } auto* root = mActor->getRootAi(); @@ -166,7 +173,7 @@ void ActionBase::leave() { postLeave(); } -void ActionBase::setRootAiFlagBit(int bit) { +void ActionBase::setRootAiFlagBit(int bit) const { mActor->getRootAi()->_16c.set(RootAiFlag(1u << bit)); } @@ -188,7 +195,7 @@ void ActionBase::updateBehaviorsOnLeave() { return; indices = &getAIProg()->getDemoBehaviorIndices(); } else { - indices = &getAIProg()->getAction(getType(), mDefinitionIdx).mBehaviorIndices; + indices = &getDef().mBehaviorIndices; } auto* root = mActor->getRootAi(); @@ -202,6 +209,20 @@ bool ActionBase::oneShot(InlineParamPack* params) { return oneShot_(); } +res::GParamList* ActionBase::getGParamList() const { + return mActor->getParam()->getRes().mGParamList; +} + +Action* ActionBase::getCurrentAction() { + auto action = std::ref(*this); + while (true) { + auto* next = action.get().getCurrentChild(); + if (!next) + return sead::DynamicCast(&action.get()); + action = *next; + } +} + void ActionBase::setFinished() { mFlags.set(Flag::Finished); mFlags.reset(Flag::Failed); @@ -212,4 +233,124 @@ void ActionBase::setFailed() { mFlags.reset(Flag::Finished); } +void ActionBase::getCurrentName(sead::BufferedSafeString* name, ActionBase* last) const { + if (!sead::IsDerivedFrom(this)) + name->appendWithFormat("/%s", getName()); + + if (this != last && getCurrentChild()) + getCurrentChild()->getCurrentName(name, last); +} + +void ActionBase::getParams(ParamNameTypePairs* pairs, bool update_use_count) const { + mParams.getPairs(pairs, update_use_count); +} + +void ActionBase::resetRootAiFlagBit(int bit) const { + mActor->getRootAi()->_16c.reset(RootAiFlag(1u << bit)); +} + +bool ActionBase::testRootAiFlag2Bit(int bit) const { + return mActor->getRootAi()->_16e.isOn(RootAiFlag2(1u << bit)); +} + +template +bool ActionBase::getStaticParam(T* value, const sead::SafeString& key) const { + return getAIProg()->getSInstParam(value, getDef(), key); +} + +template bool ActionBase::getStaticParam(const char**, const sead::SafeString&) const; +template bool ActionBase::getStaticParam(sead::SafeString*, const sead::SafeString&) const; +template bool ActionBase::getStaticParam(const int**, const sead::SafeString&) const; +template bool ActionBase::getStaticParam(const float**, const sead::SafeString&) const; +template bool ActionBase::getStaticParam(const sead::Vector3f**, const sead::SafeString&) const; +template bool ActionBase::getStaticParam(const bool**, const sead::SafeString&) const; + +void ActionBase::logMissingParam(const sead::SafeString& param) const { + // Stubbed in release versions + const auto type = getType(); + static_cast(type); +} + +template +bool ActionBase::getMapUnitParam(T* value, const sead::SafeString& key) const { + return mActor->getRootAi()->getMapUnitParam(value, key); +} + +template bool ActionBase::getMapUnitParam(sead::SafeString*, const sead::SafeString&) const; +template bool ActionBase::getMapUnitParam(const int**, const sead::SafeString&) const; +template bool ActionBase::getMapUnitParam(const float**, const sead::SafeString&) const; +template bool ActionBase::getMapUnitParam(const sead::Vector3f**, const sead::SafeString&) const; +template bool ActionBase::getMapUnitParam(const bool**, const sead::SafeString&) const; + +template +bool ActionBase::getAITreeVariable(T** value, const sead::SafeString& key) const { + return mActor->getRootAi()->getAITreeVariable(value, key); +} + +template bool ActionBase::getAITreeVariable(sead::SafeString**, const sead::SafeString&) const; +template bool ActionBase::getAITreeVariable(s32**, const sead::SafeString&) const; +template bool ActionBase::getAITreeVariable(f32**, const sead::SafeString&) const; +template bool ActionBase::getAITreeVariable(sead::Vector3f**, const sead::SafeString&) const; +template bool ActionBase::getAITreeVariable(bool**, const sead::SafeString&) const; +template bool ActionBase::getAITreeVariable(void**, const sead::SafeString&) const; + +namespace { + +BaseProcLink sDefaultBaseProcLink; +sead::FixedSafeString<32> sDefaultString32; +int sDefaultInt; +float sDefaultFloat; +bool sDefaultBool; +Rail* sDefaultRail; +struct ComplexDefaults { + util::InitConstants init_constants; + BaseProcHandle* base_proc_handle; + sead::Vector3f vec3{0, 0, 0}; + sead::SafeString string; + mes::TransceiverId transceiver_id; +}; +ComplexDefaults sDefaults; + +} // namespace + +sead::SafeString* getDefaultString() { + return &sDefaults.string; +} + +s32* getDefaultInt() { + return &sDefaultInt; +} + +f32* getDefaultFloat() { + return &sDefaultFloat; +} + +sead::Vector3f* getDefaultVec3() { + return &sDefaults.vec3; +} + +bool* getDefaultBool() { + return &sDefaultBool; +} + +BaseProcLink* getDefaultBaseProcLink() { + return &sDefaultBaseProcLink; +} + +mes::TransceiverId* getDefaultMesTransceiverId() { + return &sDefaults.transceiver_id; +} + +BaseProcHandle** getDefaultBaseProcHandle() { + return &sDefaults.base_proc_handle; +} + +Rail** getDefaultRail() { + return &sDefaultRail; +} + +sead::FixedSafeString<32>* getDefaultString32() { + return &sDefaultString32; +} + } // namespace ksys::act::ai diff --git a/src/KingSystem/ActorSystem/actAiActionBase.h b/src/KingSystem/ActorSystem/actAiActionBase.h index b67b7c9c..bfa426a2 100644 --- a/src/KingSystem/ActorSystem/actAiActionBase.h +++ b/src/KingSystem/ActorSystem/actAiActionBase.h @@ -4,13 +4,13 @@ #include #include #include -#include "KingSystem/ActorSystem/actActor.h" #include "KingSystem/ActorSystem/actAiParam.h" #include "KingSystem/Utils/Types.h" namespace ksys::res { class AIProgram; -} +class GParamList; +} // namespace ksys::res namespace ksys::act { @@ -18,12 +18,26 @@ class Actor; namespace ai { +class Action; + enum class ActionType { AI = 0, Action = 1, }; enum class RootAiFlag : u16; +enum class RootAiFlag2 : u16; + +sead::SafeString* getDefaultString(); +s32* getDefaultInt(); +f32* getDefaultFloat(); +sead::Vector3f* getDefaultVec3(); +bool* getDefaultBool(); +BaseProcLink* getDefaultBaseProcLink(); +mes::TransceiverId* getDefaultMesTransceiverId(); +BaseProcHandle** getDefaultBaseProcHandle(); +Rail** getDefaultRail(); +sead::FixedSafeString<32>* getDefaultString32(); /// Base class for actions and AIs, which can be seen as looping actions. class ActionBase { @@ -46,6 +60,8 @@ public: void leave(); bool oneShot(InlineParamPack* params); + Action* getCurrentAction(); + const char* getClassName() const; const char* getName() const; @@ -67,7 +83,7 @@ public: virtual bool m18() { return true; } virtual void m19() {} virtual void calc() {} - virtual void getCurrentName(sead::BufferedSafeString* name, ActionBase* parent) const; + virtual void getCurrentName(sead::BufferedSafeString* name, ActionBase* last) const; virtual void* m22() { return nullptr; } virtual void getParams(ParamNameTypePairs* pairs, bool update_use_count) const; virtual s32 getNumChildren() const { return 0; } @@ -100,8 +116,17 @@ protected: void setFinished(); void setFailed(); - void setRootAiFlagBit(int bit); - void setRootAiFlag(RootAiFlag flag) { setRootAiFlagBit(sead::log2(u32(flag))); } + + void setRootAiFlagBit(int bit) const; + void setRootAiFlag(RootAiFlag flag) const { setRootAiFlagBit(sead::log2(u32(flag))); } + + void resetRootAiFlagBit(int bit) const; + void resetRootAiFlag(RootAiFlag flag) const { resetRootAiFlagBit(sead::log2(u32(flag))); } + + bool testRootAiFlag2Bit(int bit) const; + bool testRootAiFlag2(RootAiFlag2 flag) const { + return testRootAiFlag2Bit(sead::log2(u32(flag))); + } void resetFlags() { mFlags.reset(Flag::Failed); @@ -110,9 +135,95 @@ protected: } res::AIProgram* getAIProg() const; + auto& getDef() const; + res::GParamList* getGParamList() const; template - void getParamStatic(ParamRef* value, const sead::SafeString& key); + bool getStaticParam(T* value, const sead::SafeString& key) const; + + void logMissingParam(const sead::SafeString& param) const; + + template + bool getMapUnitParam(T* value, const sead::SafeString& key) const; + + template + bool getAITreeVariable(T** value, const sead::SafeString& key) const; + + template + bool getDynamicParamImpl(T* value, const sead::SafeString& key, + bool (ParamPack::*getter)(T* value, const sead::SafeString& key) const, + T* default_value) const { + auto* action = this; + while (action && action->mFlags.isOff(Flag::_80)) { + if ((action->mParams.*getter)(value, key)) + return true; + if (action->mFlags.isOff(Flag::DynamicParamChild)) + goto fail; + action = action->getCurrentChild(); + if (!action) + goto fail; + } + + for (s32 i = 0, n = action->getNumChildren(); i < n; ++i) { + auto* child = action->getChild(i); + if (child->getDynamicParamImpl(value, key, getter, default_value)) + return true; + } + + fail: + logMissingParam(key); + *value = *default_value; + return false; + } + + template + bool getDynamicParamPtrImpl(T** value, const sead::SafeString& key, T* default_value) const { + return getDynamicParamImpl(value, key, &ParamPack::getPtrGeneric, &default_value); + } + + bool getDynamicParam(sead::SafeString* value, const sead::SafeString& key) const { + return getDynamicParamImpl(value, key, &ParamPack::getString, getDefaultString()); + } + + bool getDynamicParam(int** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl(value, key, getDefaultInt()); + } + + bool getDynamicParam(float** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl(value, key, getDefaultFloat()); + } + + bool getDynamicParam(sead::Vector3f** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl(value, key, getDefaultVec3()); + } + + bool getDynamicParam(bool** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl(value, key, getDefaultBool()); + } + + bool getDynamicParam(BaseProcLink** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl(value, key, + getDefaultBaseProcLink()); + } + + bool getDynamicParam(mes::TransceiverId** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl( + value, key, getDefaultMesTransceiverId()); + } + + bool getDynamicParam(BaseProcHandle*** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl(value, key, + getDefaultBaseProcHandle()); + } + + bool getDynamicParam(Rail*** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl(value, key, getDefaultRail()); + } + + bool getDynamicParam(sead::SafeString** value, const sead::SafeString& key) const { + return getDynamicParamPtrImpl( + value, key, static_cast(getDefaultString32())); + } Actor* mActor; ParamPack mParams; diff --git a/src/KingSystem/ActorSystem/actAiAi.cpp b/src/KingSystem/ActorSystem/actAiAi.cpp index 5dee7b68..9533981e 100644 --- a/src/KingSystem/ActorSystem/actAiAi.cpp +++ b/src/KingSystem/ActorSystem/actAiAi.cpp @@ -1,14 +1,74 @@ #include "KingSystem/ActorSystem/actAiAi.h" +#include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/ActorSystem/actActorParam.h" +#include "KingSystem/ActorSystem/actActorUtil.h" +#include "KingSystem/ActorSystem/actAiAction.h" #include "KingSystem/ActorSystem/actAiRoot.h" +#include "KingSystem/Resource/resResourceAIProgram.h" namespace ksys::act::ai { +inline res::AIProgram* ActionBase::getAIProg() const { + return mActor->getParam()->getRes().mAIProgram; +} + Ai::Ai(const ActionBase::InitArg& arg) : ActionBase(arg) {} Ai::~Ai() { mChildren.freeBuffer(); } +bool Ai::initChildren(const AIDefSet& set, sead::Heap* heap) { + if (set.num_children > 0) { + if (mDefinitionIdx < 0) + return false; + + auto indices = getAIProg()->getAI(mDefinitionIdx).mChildIndices; + if (!initChildren_(set.num_children, nullptr, indices, heap)) + return false; + } + return true; +} + +bool Ai::initChildren_(s32 num_children, const char** names, sead::Buffer& indices, + sead::Heap* heap) { + auto* actor = mActor; + + if (indices.size() != num_children && !isPlayerProfile(actor) && !isCameraProfile(actor)) + return false; + + if (num_children <= 0) + return false; + + if (!mChildren.tryAllocBuffer(num_children, heap)) + return false; + + for (s32 i = 0; i < num_children; ++i) + mChildren(i) = nullptr; + + auto* root_ai = actor->getRootAi(); + + const auto num_ais = actor->getParam()->getRes().mAIProgram->getAIs().size(); + const bool is_root_ai = sead::IsDerivedFrom(this); + const auto effective_ai_count = is_root_ai + num_ais; + + auto it_idx = indices.begin(); + auto it_ptr = mChildren.begin(); + const auto it_idx_end = indices.end(); + const auto it_ptr_end = mChildren.end(); + + for (; it_ptr != it_ptr_end && it_idx != it_idx_end; ++it_ptr, ++it_idx) { + if (*it_idx < effective_ai_count) + *it_ptr = root_ai->getAis().classes[*it_idx]; + else + *it_ptr = root_ai->getActions().classes[*it_idx - effective_ai_count]; + + if (*it_ptr == nullptr) + return false; + } + return true; +} + void Ai::calc() { calc_(); diff --git a/src/KingSystem/ActorSystem/actAiAi.h b/src/KingSystem/ActorSystem/actAiAi.h index df476277..acb8c56b 100644 --- a/src/KingSystem/ActorSystem/actAiAi.h +++ b/src/KingSystem/ActorSystem/actAiAi.h @@ -39,6 +39,10 @@ protected: u16 mPendingChildIdx = InvalidIdx; u16 mNewChildIdx = InvalidIdx; sead::Buffer mChildren; + +private: + bool initChildren_(s32 num_children, const char** names, sead::Buffer& indices, + sead::Heap* heap); }; KSYS_CHECK_SIZE_NX150(Ai, 0x38); diff --git a/src/KingSystem/ActorSystem/actAiParam.h b/src/KingSystem/ActorSystem/actAiParam.h index 7c7dd232..3f3dab10 100644 --- a/src/KingSystem/ActorSystem/actAiParam.h +++ b/src/KingSystem/ActorSystem/actAiParam.h @@ -85,6 +85,13 @@ public: void copy(InlineParamPack* dest, bool x) const; void getPairs(ParamNameTypePairs* pairs, bool update_use_count) const; + template + bool getPtrGeneric(T** value, const sead::SafeString& key) const { + auto* ptr = static_cast(getAITreeVariablePointer(key, Type)); + *value = ptr; + return ptr != nullptr; + } + bool getString(sead::SafeString* value, const sead::SafeString& key) const; bool setString(const sead::SafeString& value, const sead::SafeString& key) const; @@ -157,15 +164,6 @@ struct InlineParamPack { }; KSYS_CHECK_SIZE_NX150(InlineParamPack, 0xA08); -template -class ParamRef { -public: - const T& value() const { return *mValue; } - void setValuePtr(const T* ptr) { mValue = ptr; } - -private: - const T* mValue = nullptr; -}; } // namespace act::ai } // namespace ksys diff --git a/src/KingSystem/ActorSystem/actAiQuery.cpp b/src/KingSystem/ActorSystem/actAiQuery.cpp index d2259fd8..9ba2adae 100644 --- a/src/KingSystem/ActorSystem/actAiQuery.cpp +++ b/src/KingSystem/ActorSystem/actAiQuery.cpp @@ -1,4 +1,5 @@ #include "KingSystem/ActorSystem/actAiQuery.h" +#include "KingSystem/ActorSystem/actActor.h" #include "KingSystem/ActorSystem/actActorParam.h" #include "KingSystem/ActorSystem/actAiRoot.h" #include "KingSystem/Resource/resResourceAIProgram.h" diff --git a/src/KingSystem/ActorSystem/actAiRoot.cpp b/src/KingSystem/ActorSystem/actAiRoot.cpp index 9498c151..85da4dff 100644 --- a/src/KingSystem/ActorSystem/actAiRoot.cpp +++ b/src/KingSystem/ActorSystem/actAiRoot.cpp @@ -1,4 +1,6 @@ #include "KingSystem/ActorSystem/actAiRoot.h" +#include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/Utils/InitTimeInfo.h" namespace ksys::act::ai { @@ -28,6 +30,118 @@ bool RootAi::isActorDeletedOrDeleting() const { return mActor->isDeletedOrDeleting(); } +bool RootAi::getMapUnitParam(sead::SafeString* value, const sead::SafeString& key) const { + sead::SafeString out; + if (mMapUnitParams.getString(&out, key)) { + *value = out.cstr(); + return true; + } + *value = sead::SafeString::cEmptyString; + return false; +} + +bool RootAi::getMapUnitParam(const s32** value, const sead::SafeString& key) const { + auto* ptr = + static_cast(mMapUnitParams.getAITreeVariablePointer(key, AIDefParamType::Int)); + static const s32 sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +bool RootAi::getMapUnitParam(const f32** value, const sead::SafeString& key) const { + auto* ptr = + static_cast(mMapUnitParams.getAITreeVariablePointer(key, AIDefParamType::Float)); + static const f32 sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +bool RootAi::getMapUnitParam(const sead::Vector3f** value, const sead::SafeString& key) const { + auto* ptr = static_cast( + mMapUnitParams.getAITreeVariablePointer(key, AIDefParamType::Vec3)); + *value = ptr ? ptr : &sead::Vector3f::zero; + return ptr != nullptr; +} + +bool RootAi::getMapUnitParam(const bool** value, const sead::SafeString& key) const { + auto* ptr = + static_cast(mMapUnitParams.getAITreeVariablePointer(key, AIDefParamType::Bool)); + static const bool sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +namespace { +sead::FixedSafeString<64> sDefaultString; + +struct Vec3Wrapper { + util::InitTimeInfoEx init_time_info_ex; + sead::Vector3f sDefaultVec3{0, 0, 0}; +}; +Vec3Wrapper sDefaultAITreeVariables; +} // namespace + +bool RootAi::getAITreeVariable(sead::SafeString** value, const sead::SafeString& key) const { + auto* ptr = static_cast( + mAiTreeParams.getAITreeVariablePointer(key, AIDefParamType::String)); + *value = ptr ? ptr : &sDefaultString; + return ptr != nullptr; +} + +bool RootAi::getAITreeVariable(s32** value, const sead::SafeString& key) const { + auto* ptr = static_cast(mAiTreeParams.getAITreeVariablePointer(key, AIDefParamType::Int)); + static s32 sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +bool RootAi::getAITreeVariable(f32** value, const sead::SafeString& key) const { + auto* ptr = + static_cast(mAiTreeParams.getAITreeVariablePointer(key, AIDefParamType::Float)); + static f32 sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +bool RootAi::getAITreeVariable(sead::Vector3f** value, const sead::SafeString& key) const { + auto* ptr = static_cast( + mAiTreeParams.getAITreeVariablePointer(key, AIDefParamType::Vec3)); + *value = ptr ? ptr : &sDefaultAITreeVariables.sDefaultVec3; + return ptr != nullptr; +} + +bool RootAi::getAITreeVariable(bool** value, const sead::SafeString& key) const { + auto* ptr = + static_cast(mAiTreeParams.getAITreeVariablePointer(key, AIDefParamType::Bool)); + static bool sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +bool RootAi::getAITreeVariable(void** value, const sead::SafeString& key) const { + auto* ptr = static_cast( + mAiTreeParams.getAITreeVariablePointer(key, AIDefParamType::AITreeVariablePointer)); + static void* sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +bool RootAi::getAITreeVariable(u32** value, const sead::SafeString& key) const { + auto* ptr = + static_cast(mAiTreeParams.getAITreeVariablePointer(key, AIDefParamType::UInt)); + static u32 sDefault{}; + *value = ptr ? ptr : &sDefault; + return ptr != nullptr; +} + +bool RootAi::getAITreeVariable2(sead::Vector3f** value, const sead::SafeString& key) const { + return getAITreeVariable(value, key); +} + +bool RootAi::getAITreeVariable2(bool** value, const sead::SafeString& key) const { + return getAITreeVariable(value, key); +} + const char* getDefaultAiName(s32 root_idx) { static constexpr const char* names[] = {"DemoRootAI", "Root"}; if (root_idx >= 2) diff --git a/src/KingSystem/ActorSystem/actAiRoot.h b/src/KingSystem/ActorSystem/actAiRoot.h index 54c9efbe..160dbfca 100644 --- a/src/KingSystem/ActorSystem/actAiRoot.h +++ b/src/KingSystem/ActorSystem/actAiRoot.h @@ -36,6 +36,9 @@ enum class RootAiFlag : u16 { _100 = 0x100, // 8 }; +// TODO: rename +enum class RootAiFlag2 : u16 {}; + class RootAi : public Ai, public IRootAi { SEAD_RTTI_OVERRIDE(RootAi, Ai) public: @@ -62,6 +65,24 @@ public: bool loadMapUnitParams(const AIDef& def, sead::Heap* heap); bool loadAITreeParams(const AIDef& def, sead::Heap* heap); + bool getMapUnitParam(sead::SafeString* value, const sead::SafeString& key) const; + bool getMapUnitParam(const s32** value, const sead::SafeString& key) const; + bool getMapUnitParam(const f32** value, const sead::SafeString& key) const; + bool getMapUnitParam(const sead::Vector3f** value, const sead::SafeString& key) const; + bool getMapUnitParam(const bool** value, const sead::SafeString& key) const; + + bool getAITreeVariable(sead::SafeString** value, const sead::SafeString& key) const; + bool getAITreeVariable(s32** value, const sead::SafeString& key) const; + bool getAITreeVariable(f32** value, const sead::SafeString& key) const; + bool getAITreeVariable(sead::Vector3f** value, const sead::SafeString& key) const; + bool getAITreeVariable(bool** value, const sead::SafeString& key) const; + bool getAITreeVariable(void** value, const sead::SafeString& key) const; + bool getAITreeVariable(u32** value, const sead::SafeString& key) const; + // TODO: rename + bool getAITreeVariable2(sead::Vector3f** value, const sead::SafeString& key) const; + // TODO: rename + bool getAITreeVariable2(bool** value, const sead::SafeString& key) const; + void setBehavior(Behavior* behavior); void resetBehavior(Behavior* behavior); @@ -97,7 +118,7 @@ private: // TODO: is this really an atomic? sead::Atomic _168 = 1.0; sead::TypedBitFlag _16c; - u16 _16e{}; + sead::TypedBitFlag _16e; ParamPack mMapUnitParams; ParamPack mAiTreeParams; }; diff --git a/src/KingSystem/Resource/resResourceAIProgram.h b/src/KingSystem/Resource/resResourceAIProgram.h index 242001ce..016d903b 100644 --- a/src/KingSystem/Resource/resResourceAIProgram.h +++ b/src/KingSystem/Resource/resResourceAIProgram.h @@ -63,6 +63,10 @@ public: const sead::Buffer& getBehaviors() const { return mBehaviors; } const sead::Buffer& getQueries() const { return mQueries; } + const AIActionDef& getAI(s32 index) const { return mAIs[index]; } + const sead::Buffer& getAIs() const { return mAIs; } + const sead::Buffer& getActions() const { return mAIs; } + const AIActionDef& getAction(act::ai::ActionType type, s32 index) const { return getActionsOrAIs(type)[index]; }