ksys/act: Implement Actions, Ais

This commit is contained in:
Léo Lam
2020-12-19 21:59:21 +01:00
parent dbe6afa97a
commit 62014b715b
11 changed files with 462 additions and 38 deletions
+30 -30
View File
@@ -73442,14 +73442,14 @@
0x0000007100d322e8,AI_Action_DemoVisibleOff::leave,160,
0x0000007100d32388,AI_Action_DemoVisibleOff::rtti1,288,
0x0000007100d324a8,AI_Action_DemoVisibleOff::rtti2,92,
0x0000007100d32504,AI_Action_AreaCulling::ctor,48,
0x0000007100d32534,AI_Action_LinkTagCountAction::enter,16,
0x0000007100d32544,AI_Action_LinkTagCountAction::calc,4,
0x0000007100d32548,AI_Action_LinkTagCountAction::leave,4,
0x0000007100d3254c,AI_Action_LinkTagCountAction::loadParams,4,
0x0000007100d32550,AI_Action_LinkTagCountAction::rtti1,288,
0x0000007100d32670,AI_Action_LinkTagCountAction::rtti2,92,
0x0000007100d326cc,AI_Action_LinkTagCountAction::dtorDelete,52,
0x0000007100d32504,AI_Action_AreaCulling::ctor,48,_ZN4ksys3act2ai11DummyActionC1ERKNS1_10ActionBase7InitArgE
0x0000007100d32534,AI_Action_LinkTagCountAction::enter,16,_ZN4ksys3act2ai11DummyAction6enter_EPNS1_15InlineParamPackE
0x0000007100d32544,AI_Action_LinkTagCountAction::calc,4,_ZN4ksys3act2ai11DummyAction5calc_Ev
0x0000007100d32548,AI_Action_LinkTagCountAction::leave,4,_ZN4ksys3act2ai11DummyAction6leave_Ev
0x0000007100d3254c,AI_Action_LinkTagCountAction::loadParams,4,_ZN4ksys3act2ai11DummyAction11loadParams_Ev
0x0000007100d32550,AI_Action_LinkTagCountAction::rtti1,288,_ZNK4ksys3act2ai11DummyAction27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x0000007100d32670,AI_Action_LinkTagCountAction::rtti2,92,_ZNK4ksys3act2ai11DummyAction18getRuntimeTypeInfoEv
0x0000007100d326cc,AI_Action_LinkTagCountAction::dtorDelete,52,_ZN4ksys3act2ai11DummyActionD0Ev
0x0000007100d32700,AI_Action_DummyDropTable::ctor,72,
0x0000007100d32748,AI_Action_DummyDropTable::dtor,20,
0x0000007100d3275c,AI_Action_DummyDropTable::dtorDelete,52,
@@ -91920,14 +91920,14 @@
0x00000071011c24fc,AI_ActionBase::rtti1,204,_ZNK4ksys3act2ai6Action27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x00000071011c25c8,AI_ActionBase::rtti2,92,_ZNK4ksys3act2ai6Action18getRuntimeTypeInfoEv
0x00000071011c2624,AI_ActionBase::dtorDelete,52,_ZN4ksys3act2ai6ActionD0Ev
0x00000071011c2658,ai::Actions::ctor,28,
0x00000071011c2674,sub_71011C2674,4,
0x00000071011c2678,sub_71011C2678,200,
0x00000071011c2740,ai::Actions::init,1248,
0x00000071011c2c20,sub_71011C2C20,32,
0x00000071011c2c40,sub_71011C2C40,300,
0x00000071011c2d6c,sub_71011C2D6C,96,
0x00000071011c2dcc,sub_71011C2DCC,68,
0x00000071011c2658,ai::Actions::ctor,28,_ZN4ksys3act2ai7ActionsC1Ev
0x00000071011c2674,sub_71011C2674,4,_ZN4ksys3act2ai7ActionsD1Ev
0x00000071011c2678,sub_71011C2678,200,_ZN4ksys3act2ai7Actions8finalizeEv
0x00000071011c2740,ai::Actions::init,1248,_ZN4ksys3act2ai7Actions4initEPNS0_5ActorEPN4sead4HeapE
0x00000071011c2c20,sub_71011C2C20,32,_ZN4ksys3act2ai7Actions12setFactoriesEiPNS1_13ActionFactoryE
0x00000071011c2c40,sub_71011C2C40,300,_ZN4ksys3act2ai7Actions5cloneERKNS1_6ActionEPN4sead4HeapE
0x00000071011c2d6c,sub_71011C2D6C,96,_ZNK4ksys3act2ai7Actions17onActorPreDelete2Ev
0x00000071011c2dcc,sub_71011C2DCC,68,_ZNK4ksys3act2ai7Actions17onActorPreDelete1Ev
0x00000071011c2e10,Dummy::construct,68,
0x00000071011c2e54,getDummyBaseProcLink,12,
0x00000071011c2e60,Actor::ctor,1208,
@@ -92279,13 +92279,13 @@
0x00000071011deec4,AI_AIBase::m23,216,
0x00000071011def9c,AI_AIBase::rtti1,204,_ZNK4ksys3act2ai2Ai27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x00000071011df068,AI_AIBase::rtti2,92,_ZNK4ksys3act2ai2Ai18getRuntimeTypeInfoEv
0x00000071011df0c4,ai::AIs::ctor,28,
0x00000071011df0e0,sub_71011DF0E0,4,
0x00000071011df0e4,sub_71011DF0E4,200,
0x00000071011df1ac,ai::AIs::init,1276,
0x00000071011df6a8,sub_71011DF6A8,32,
0x00000071011df6c8,sub_71011DF6C8,96,
0x00000071011df728,sub_71011DF728,68,
0x00000071011df0c4,ai::AIs::ctor,28,_ZN4ksys3act2ai3AisC1Ev
0x00000071011df0e0,sub_71011DF0E0,4,_ZN4ksys3act2ai3AisD1Ev
0x00000071011df0e4,sub_71011DF0E4,200,_ZN4ksys3act2ai3Ais8finalizeEv
0x00000071011df1ac,ai::AIs::init,1276,_ZN4ksys3act2ai3Ais4initEPNS0_5ActorEPN4sead4HeapE
0x00000071011df6a8,sub_71011DF6A8,32,_ZN4ksys3act2ai3Ais12setFactoriesEiPNS1_9AiFactoryE
0x00000071011df6c8,sub_71011DF6C8,96,_ZNK4ksys3act2ai3Ais17onActorPreDelete2Ev
0x00000071011df728,sub_71011DF728,68,_ZNK4ksys3act2ai3Ais17onActorPreDelete1Ev
0x00000071011df76c,sub_71011DF76C,92,_ZN4ksys10AIClassDef18SingletonDisposer_D2Ev
0x00000071011df7c8,sub_71011DF7C8,100,_ZN4ksys10AIClassDef18SingletonDisposer_D0Ev
0x00000071011df82c,AIClassDef::createInstance,132,_ZN4ksys10AIClassDef14createInstanceEPN4sead4HeapE
@@ -94107,13 +94107,13 @@
0x0000007101257018,sub_7101257018,964,
0x00000071012573dc,sub_71012573DC,32,
0x00000071012573fc,sub_71012573FC,616,
0x0000007101257664,AI_AIDummy::ctor,48,
0x0000007101257694,AI_AIDummy::enter,4,
0x0000007101257698,AI_AIDummy::calc,4,
0x000000710125769c,AI_AIDummy::rtti1,288,
0x00000071012577bc,AI_AIDummy::rtti2,92,
0x0000007101257818,AI_AIDummy::dtorDelete,36,
0x000000710125783c,AI_AIDummy::m6,8,
0x0000007101257664,AI_AIDummy::ctor,48,_ZN4ksys3act2ai7DummyAiC1ERKNS1_10ActionBase7InitArgE
0x0000007101257694,AI_AIDummy::enter,4,_ZN4ksys3act2ai7DummyAi6enter_EPNS1_15InlineParamPackE
0x0000007101257698,AI_AIDummy::calc,4,_ZN4ksys3act2ai7DummyAi5calc_Ev
0x000000710125769c,AI_AIDummy::rtti1,288,_ZNK4ksys3act2ai7DummyAi27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x00000071012577bc,AI_AIDummy::rtti2,92,_ZNK4ksys3act2ai7DummyAi18getRuntimeTypeInfoEv
0x0000007101257818,AI_AIDummy::dtorDelete,36,_ZN4ksys3act2ai7DummyAiD0Ev
0x000000710125783c,AI_AIDummy::m6,8,_ZNK4ksys3act2ai7DummyAi10isFlag4SetEv
0x0000007101257844,sub_7101257844,64,
0x0000007101257884,sub_7101257884,156,
0x0000007101257920,sub_7101257920,12,
Can't render this file because it is too large.
@@ -63,4 +63,9 @@ target_sources(uking PRIVATE
actInstParamPack.h
actLifeRecoveryInfo.h
actTag.h
actionDummyAction.cpp
actionDummyAction.h
aiDummyAi.cpp
aiDummyAi.h
)
+156
View File
@@ -1,5 +1,10 @@
#include "KingSystem/ActorSystem/actAiAction.h"
#include <codec/seadHashCRC32.h>
#include "KingSystem/ActorSystem/actActor.h"
#include "KingSystem/ActorSystem/actActorParam.h"
#include "KingSystem/ActorSystem/actAiRoot.h"
#include "KingSystem/ActorSystem/actionDummyAction.h"
#include "KingSystem/Resource/resResourceAIProgram.h"
namespace ksys::act::ai {
@@ -9,4 +14,155 @@ void Action::calc() {
calc_();
}
Actions::Actions() = default;
Actions::~Actions() {
finalize();
}
void Actions::finalize() {
for (s32 i = 0; i < classes.size(); ++i) {
if (classes[i]) {
delete classes[i];
classes[i] = nullptr;
}
}
predelete1_callbacks.freeBuffer();
predelete2_callbacks.freeBuffer();
classes.freeBuffer();
}
bool Actions::init(Actor* actor, sead::Heap* heap) {
const auto* aiprog = actor->getParam()->getRes().mAIProgram;
const auto num_actions = aiprog->getActions().size();
if (num_actions == 0)
return true;
if (!classes.tryAllocBuffer(num_actions, heap))
return false;
for (s32 i = 0; i < num_actions; ++i)
classes(i) = nullptr;
auto it_class = classes.begin();
const auto it_class_end = classes.end();
Action::InitArg arg{};
arg.actor = actor;
arg.def_idx = -1;
arg.root_idx = -1;
s32 predelete1_callback_num = 0;
s32 predelete2_callback_num = 0;
for (; it_class != it_class_end; ++it_class) {
const char* name;
if (it_class.getIndex() >= num_actions) {
arg.root_idx = it_class.getIndex() - num_actions;
arg.def_idx = -1;
name = getDefaultActionName(arg.root_idx);
} else {
arg.def_idx = it_class.getIndex();
name = aiprog->getActions()[it_class.getIndex()].mClassName;
}
auto* factory = getFactory(name);
if (factory)
*it_class = factory->create_fn(arg, heap);
else
*it_class = new (heap) DummyAction(arg);
if (!*it_class)
return false;
predelete2_callback_num += (*it_class)->m8();
predelete1_callback_num += (*it_class)->m7();
}
// Allocate the callback lists.
if (predelete1_callback_num != 0) {
if (!predelete1_callbacks.tryAllocBuffer(predelete1_callback_num, heap))
return false;
for (s32 i = 0; i < predelete1_callback_num; ++i)
predelete1_callbacks(i) = nullptr;
}
if (predelete2_callback_num != 0) {
if (!predelete2_callbacks.tryAllocBuffer(predelete2_callback_num, heap))
return false;
for (s32 i = 0; i < predelete2_callback_num; ++i)
predelete2_callbacks(i) = nullptr;
}
// Initialize each class.
s32 idx_cb1 = 0, idx_cb2 = 0;
for (auto it = classes.begin(), end = classes.end(); it != end; ++it) {
if (!(*it)->init(heap, false))
return false;
if ((*it)->m8()) {
predelete2_callbacks[idx_cb2] = *it;
++idx_cb2;
}
if ((*it)->m7()) {
predelete1_callbacks[idx_cb1] = *it;
++idx_cb1;
}
}
return true;
}
Action* Actions::clone(const Action& action, sead::Heap* heap) {
auto* factory = getFactory(action.getClassName());
if (!factory)
return nullptr;
Action::InitArg arg;
arg.actor = action.getActor();
arg.def_idx = action.getDefinitionIdx();
auto* clone = factory->create_fn(arg, heap);
if (!clone) {
return nullptr;
}
if (!clone->init(heap, true)) {
delete clone;
return nullptr;
}
return clone;
}
bool Actions::onActorPreDelete2() const {
bool ok = true;
for (auto* action : predelete2_callbacks) {
if (action)
ok &= action->m18();
}
return ok;
}
void Actions::onActorPreDelete1() const {
for (auto* action : predelete1_callbacks) {
if (action)
action->m19();
}
}
ActionFactory* Actions::getFactory(const sead::SafeString& name) {
const u32 name_hash = sead::HashCRC32::calcStringHash(name);
const s32 idx = sFactories.binarySearch(
name_hash, +[](const ActionFactory& 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 Actions::setFactories(int count, ActionFactory* factories) {
sFactories.setBuffer(count, factories);
}
} // namespace ksys::act::ai
+22 -4
View File
@@ -1,5 +1,6 @@
#pragma once
#include <basis/seadTypes.h>
#include <container/seadBuffer.h>
#include "KingSystem/ActorSystem/actAiActionBase.h"
#include "KingSystem/Utils/Types.h"
@@ -19,6 +20,12 @@ protected:
};
KSYS_CHECK_SIZE_NX150(Action, 0x20);
struct ActionFactory {
using CreateFn = Action* (*)(const Action::InitArg& arg, sead::Heap* heap);
u32 hash;
CreateFn create_fn;
};
class Actions {
public:
Actions();
@@ -26,11 +33,22 @@ public:
void finalize();
bool init(Actor* actor, sead::Heap* heap);
bool onActorPreDelete2() const;
void onActorPreDelete1() const;
static Action* clone(const Action& action, sead::Heap* heap);
static ActionFactory* getFactory(const sead::SafeString& name);
static void setFactories(int count, ActionFactory* factories);
sead::Buffer<Action*> classes;
// TODO: rename
sead::Buffer<Action*> x;
// TODO: rename
sead::Buffer<Action*> y;
// Non-owning buffer.
sead::Buffer<Action*> predelete1_callbacks;
// Non-owning buffer.
sead::Buffer<Action*> predelete2_callbacks;
private:
static inline sead::Buffer<ActionFactory> sFactories;
};
} // namespace ksys::act::ai
@@ -62,6 +62,8 @@ public:
Action* getCurrentAction();
Actor* getActor() const { return mActor; }
s32 getDefinitionIdx() const { return mDefinitionIdx; }
const char* getClassName() const;
const char* getName() const;
+158
View File
@@ -4,6 +4,7 @@
#include "KingSystem/ActorSystem/actActorUtil.h"
#include "KingSystem/ActorSystem/actAiAction.h"
#include "KingSystem/ActorSystem/actAiRoot.h"
#include "KingSystem/ActorSystem/aiDummyAi.h"
#include "KingSystem/Resource/resResourceAIProgram.h"
namespace ksys::act::ai {
@@ -105,4 +106,161 @@ void Ai::updateChildIdx(u16 new_idx) {
mPendingChildIdx = InvalidIdx;
}
Ais::Ais() = default;
Ais::~Ais() {
finalize();
}
void Ais::finalize() {
for (s32 i = 0; i < classes.size(); ++i) {
if (classes[i]) {
delete classes[i];
classes[i] = nullptr;
}
}
predelete1_callbacks.freeBuffer();
predelete2_callbacks.freeBuffer();
classes.freeBuffer();
}
bool Ais::init(Actor* actor, sead::Heap* heap) {
const auto* aiprog = actor->getParam()->getRes().mAIProgram;
const auto num_ais = aiprog->getAIs().size();
if (num_ais < 0)
return false;
if (!classes.tryAllocBuffer(num_ais + 1, heap))
return false;
for (s32 i = 0, n = classes.size(); i != n; ++i)
classes(i) = nullptr;
auto it_class = classes.begin();
const auto it_class_end = classes.end();
Ai::InitArg arg{};
arg.actor = actor;
arg.def_idx = -1;
arg.root_idx = -1;
s32 predelete1_callback_num = 0;
s32 predelete2_callback_num = 0;
for (; it_class != it_class_end; ++it_class) {
const char* name;
if (it_class.getIndex() >= num_ais) {
arg.root_idx = it_class.getIndex() - num_ais;
arg.def_idx = -1;
name = getDefaultAiName(arg.root_idx);
} else {
arg.def_idx = it_class.getIndex();
name = aiprog->getAIs()[it_class.getIndex()].mClassName;
}
auto* factory = getFactory(name);
if (factory)
*it_class = factory->create_fn(arg, heap);
else
*it_class = new (heap) DummyAi(arg);
if (!*it_class)
return false;
predelete2_callback_num += (*it_class)->m8();
predelete1_callback_num += (*it_class)->m7();
}
// Allocate the callback lists.
if (predelete1_callback_num != 0) {
if (!predelete1_callbacks.tryAllocBuffer(predelete1_callback_num, heap))
return false;
for (s32 i = 0; i < predelete1_callback_num; ++i)
predelete1_callbacks(i) = nullptr;
}
if (predelete2_callback_num != 0) {
if (!predelete2_callbacks.tryAllocBuffer(predelete2_callback_num, heap))
return false;
for (s32 i = 0; i < predelete2_callback_num; ++i)
predelete2_callbacks(i) = nullptr;
}
// Initialize each class.
s32 idx_cb1 = 0, idx_cb2 = 0;
for (auto it = classes.begin(), end = classes.end(); it != end; ++it) {
if (!(*it)->init(heap, false))
return false;
if ((*it)->m8()) {
predelete2_callbacks[idx_cb2] = *it;
++idx_cb2;
}
if ((*it)->m7()) {
predelete1_callbacks[idx_cb1] = *it;
++idx_cb1;
}
}
for (auto* ai : classes) {
if (!ai->gatherParamsFromChildren(heap))
return false;
}
return true;
}
Ai* Ais::clone(const Ai& action, sead::Heap* heap) {
auto* factory = getFactory(action.getClassName());
if (!factory)
return nullptr;
Ai::InitArg arg;
arg.actor = action.getActor();
arg.def_idx = action.getDefinitionIdx();
auto* clone = factory->create_fn(arg, heap);
if (!clone) {
return nullptr;
}
if (!clone->init(heap, true)) {
delete clone;
return nullptr;
}
return clone;
}
bool Ais::onActorPreDelete2() const {
bool ok = true;
for (auto* action : predelete2_callbacks) {
if (action)
ok &= action->m18();
}
return ok;
}
void Ais::onActorPreDelete1() const {
for (auto* action : predelete1_callbacks) {
if (action)
action->m19();
}
}
AiFactory* Ais::getFactory(const sead::SafeString& name) {
const u32 name_hash = sead::HashCRC32::calcStringHash(name);
const s32 idx = sFactories.binarySearch(
name_hash, +[](const AiFactory& 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 Ais::setFactories(int count, AiFactory* factories) {
sFactories.setBuffer(count, factories);
}
} // namespace ksys::act::ai
+23 -4
View File
@@ -25,6 +25,8 @@ public:
ActionBase* getChild(s32 idx) const override { return mChildren[idx]; }
virtual const char* getPreviousName();
bool gatherParamsFromChildren(sead::Heap* heap);
protected:
virtual void calc_() {}
virtual void handlePendingChildChange_() { changeChildState(mPendingChildIdx); }
@@ -46,6 +48,12 @@ private:
};
KSYS_CHECK_SIZE_NX150(Ai, 0x38);
struct AiFactory {
using CreateFn = Ai* (*)(const Ai::InitArg& arg, sead::Heap* heap);
u32 hash;
CreateFn create_fn;
};
class Ais {
public:
Ais();
@@ -53,11 +61,22 @@ public:
void finalize();
bool init(Actor* actor, sead::Heap* heap);
bool onActorPreDelete2() const;
void onActorPreDelete1() const;
static Ai* clone(const Ai& ai, sead::Heap* heap);
static AiFactory* getFactory(const sead::SafeString& name);
static void setFactories(int count, AiFactory* factories);
sead::Buffer<Ai*> classes;
// TODO: rename
sead::Buffer<Ai*> x;
// TODO: rename
sead::Buffer<Ai*> y;
// Non-owning buffer.
sead::Buffer<Ai*> predelete1_callbacks;
// Non-owning buffer.
sead::Buffer<Ai*> predelete2_callbacks;
private:
static inline sead::Buffer<AiFactory> sFactories;
};
} // namespace ksys::act::ai
@@ -0,0 +1,17 @@
#include "KingSystem/ActorSystem/actionDummyAction.h"
namespace ksys::act::ai {
DummyAction::DummyAction(const InitArg& arg) : Action(arg) {}
void DummyAction::enter_(InlineParamPack* params) {
mFlags.set(ActionBase::Flag::_4);
}
void DummyAction::calc_() {}
void DummyAction::leave_() {}
void DummyAction::loadParams_() {}
} // namespace ksys::act::ai
@@ -0,0 +1,19 @@
#pragma once
#include "KingSystem/ActorSystem/actAiAction.h"
namespace ksys::act::ai {
class DummyAction : public Action {
SEAD_RTTI_OVERRIDE(DummyAction, Action)
public:
explicit DummyAction(const InitArg& arg);
void enter_(InlineParamPack* params) override;
void leave_() override;
void loadParams_() override;
protected:
void calc_() override;
};
} // namespace ksys::act::ai
+11
View File
@@ -0,0 +1,11 @@
#include "KingSystem/ActorSystem/aiDummyAi.h"
namespace ksys::act::ai {
DummyAi::DummyAi(const ActionBase::InitArg& arg) : Ai(arg) {}
void DummyAi::enter_(InlineParamPack* params) {}
void DummyAi::calc_() {}
} // namespace ksys::act::ai
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include "KingSystem/ActorSystem/actAiAi.h"
namespace ksys::act::ai {
class DummyAi : public Ai {
SEAD_RTTI_OVERRIDE(DummyAi, Ai)
public:
explicit DummyAi(const InitArg& arg);
bool isFlag4Set() const override { return true; }
void enter_(InlineParamPack* params) override;
protected:
void calc_() override;
};
} // namespace ksys::act::ai