ksys/act: Add Behaviors

This commit is contained in:
Léo Lam 2020-12-21 16:18:23 +01:00
parent 258bfd057a
commit 64b93c984e
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
7 changed files with 198 additions and 28 deletions

View File

@ -37218,14 +37218,14 @@
0x0000007100615afc,AI_Behavior_AcceptLSwordDamageDCCallback::dtorDelete,96,
0x0000007100615b5c,AI_Behavior_AcceptLSwordDamageDCCallback::rtti1,288,
0x0000007100615c7c,AI_Behavior_AcceptLSwordDamageDCCallback::rtti2,92,
0x0000007100615cd8,AI_BehaviorBase::m4,8,_ZN4ksys3act2ai8Behavior2m4Ev
0x0000007100615ce0,AI_BehaviorBase::m5,8,_ZN4ksys3act2ai8Behavior2m5Ev
0x0000007100615cd8,AI_BehaviorBase::m4,8,_ZN4ksys3act2ai8Behavior14hasPreDeleteCbEv
0x0000007100615ce0,AI_BehaviorBase::m5,8,_ZN4ksys3act2ai8Behavior23hasUpdateForPreDeleteCbEv
0x0000007100615ce8,AI_BehaviorBase::m11_null,4,_ZN4ksys3act2ai8Behavior3m11Ev
0x0000007100615cec,AI_BehaviorBase::m12,8,_ZN4ksys3act2ai8Behavior3m12Ev
0x0000007100615cf4,AI_BehaviorBase::m13_null,4,_ZN4ksys3act2ai8Behavior3m13Ev
0x0000007100615cec,AI_BehaviorBase::m12,8,_ZN4ksys3act2ai8Behavior18updateForPreDeleteEv
0x0000007100615cf4,AI_BehaviorBase::m13_null,4,_ZN4ksys3act2ai8Behavior11onPreDeleteEv
0x0000007100615cf8,AI_Behavior_AcceptLSwordDamageDCCallback::m14,8,
0x0000007100615d00,sub_7100615D00,140,
0x0000007100615d8c,sub_7100615D8C,140,
0x0000007100615d8c,sub_7100615D8C,140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys3act2ai8BehaviorEE9isDerivedEPKNS0_9InterfaceE
0x0000007100615e18,AI_Behavior_ActorFlagSetterAttensionNotice::ctor,52,
0x0000007100615e4c,AI_Behavior_ActorFlagSetterAttensionNotice::dtor_null,4,
0x0000007100615e50,j__ZdlPv_139,4,
@ -73145,13 +73145,13 @@
0x0000007100d24e54,AI_BehaviorBase::m1,92,_ZNK4ksys3act2ai8Behavior18getRuntimeTypeInfoEv
0x0000007100d24eb0,AI_BehaviorBase::dtorDelete,4,_ZN4ksys3act2ai8BehaviorD0Ev
0x0000007100d24eb4,AI_BehaviorBase::m8_null,4,_ZN4ksys3act2ai8Behavior2m8Ev
0x0000007100d24eb8,ai::Behaviors::ctor,28,
0x0000007100d24ed4,sub_7100D24ED4,4,
0x0000007100d24ed8,sub_7100D24ED8,200,
0x0000007100d24fa0,ai::Behaviors::init,1212,
0x0000007100d2545c,sub_7100D2545C,32,
0x0000007100d2547c,sub_7100D2547C,96,
0x0000007100d254dc,sub_7100D254DC,68,
0x0000007100d24eb8,ai::Behaviors::ctor,28,_ZN4ksys3act2ai9BehaviorsC1Ev
0x0000007100d24ed4,sub_7100D24ED4,4,_ZN4ksys3act2ai9BehaviorsD1Ev
0x0000007100d24ed8,sub_7100D24ED8,200,_ZN4ksys3act2ai9Behaviors8finalizeEv
0x0000007100d24fa0,ai::Behaviors::init,1212,_ZN4ksys3act2ai9Behaviors4initEPNS0_5ActorEPN4sead4HeapE
0x0000007100d2545c,sub_7100D2545C,32,_ZN4ksys3act2ai9Behaviors12setFactoriesEiPNS1_15BehaviorFactoryE
0x0000007100d2547c,sub_7100D2547C,96,_ZNK4ksys3act2ai9Behaviors18updateForPreDeleteEv
0x0000007100d254dc,sub_7100D254DC,68,_ZNK4ksys3act2ai9Behaviors11onPreDeleteEv
0x0000007100d25520,sub_7100D25520,100,
0x0000007100d25584,sub_7100D25584,108,
0x0000007100d255f0,ActorDebug::createInstance,136,
@ -74337,10 +74337,10 @@
0x0000007100d66d64,ai::ActorAI::rtti2,92,_ZNK4ksys3act2ai6RootAi18getRuntimeTypeInfoEv
0x0000007100d66dc0,ai::ActorAI::m6,8,_ZNK4ksys3act2ai6RootAi10isFlag4SetEv
0x0000007100d66dc8,sub_7100D66DC8,160,
0x0000007100d66e68,AI_BehaviorDummy::ctor,48,
0x0000007100d66e98,AI_BehaviorDummy::rtti1,204,
0x0000007100d66f64,AI_BehaviorDummy::rtti2,92,
0x0000007100d66fc0,j__ZdlPv_856,4,
0x0000007100d66e68,AI_BehaviorDummy::ctor,48,_ZN4ksys3act2ai13DummyBehaviorC1ERKNS1_8Behavior7InitArgE
0x0000007100d66e98,AI_BehaviorDummy::rtti1,204,_ZNK4ksys3act2ai13DummyBehavior27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x0000007100d66f64,AI_BehaviorDummy::rtti2,92,_ZNK4ksys3act2ai13DummyBehavior18getRuntimeTypeInfoEv
0x0000007100d66fc0,j__ZdlPv_856,4,_ZN4ksys3act2ai13DummyBehaviorD0Ev
0x0000007100d66fc4,AI_Behavior_ShowConstStringBoard::ctor,240,
0x0000007100d670b4,AI_Behavior_ShowConstStringBoard::m8,4,
0x0000007100d670b8,AI_Behavior_ShowConstStringBoard::m7,284,

Can't render this file because it is too large.

View File

@ -68,4 +68,6 @@ target_sources(uking PRIVATE
actionDummyAction.h
aiDummyAi.cpp
aiDummyAi.h
behaviorDummyBehavior.cpp
behaviorDummyBehavior.h
)

View File

@ -1,10 +1,10 @@
#include "KingSystem/ActorSystem/actAiActionBase.h"
#include "KingSystem/ActorSystem/actActor.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 {
@ -119,7 +119,7 @@ void ActionBase::updateBehaviorsOnEnter() {
auto* root = mActor->getRootAi();
for (auto indice : *indices)
root->setBehavior(root->getBehaviors().classes[indice]);
root->setBehavior(root->getBehaviors().getClasses()[indice]);
}
bool ActionBase::takeOver(ActionBase* src, const sead::SafeString& context) {
@ -200,7 +200,7 @@ void ActionBase::updateBehaviorsOnLeave() {
auto* root = mActor->getRootAi();
for (auto indice : *indices)
root->resetBehavior(root->getBehaviors().classes[indice]);
root->resetBehavior(root->getBehaviors().getClasses()[indice]);
}
bool ActionBase::oneShot(InlineParamPack* params) {

View File

@ -1,9 +1,137 @@
#include "KingSystem/ActorSystem/actAiBehavior.h"
#include "KingSystem/ActorSystem/actActor.h"
#include "KingSystem/ActorSystem/actActorParam.h"
#include "KingSystem/ActorSystem/actAiRoot.h"
#include "KingSystem/ActorSystem/behaviorDummyBehavior.h"
#include "KingSystem/Resource/resResourceAIProgram.h"
namespace ksys::act::ai {
Behavior::Behavior(const InitArg& arg)
: mActor(arg.actor), mDefIdx(static_cast<u16>(arg.def_idx)) {}
Behaviors::Behaviors() = default;
Behaviors::~Behaviors() {
finalize();
}
void Behaviors::finalize() {
for (s32 i = 0; i < mClasses.size(); ++i) {
if (mClasses[i]) {
delete mClasses[i];
mClasses[i] = nullptr;
}
}
mOnPreDeleteCbs.freeBuffer();
mUpdateForPreDeleteCbs.freeBuffer();
mClasses.freeBuffer();
}
bool Behaviors::init(Actor* actor, sead::Heap* heap) {
const auto* aiprog = actor->getParam()->getRes().mAIProgram;
const auto num_behaviors = aiprog->getBehaviors().size();
if (num_behaviors == 0)
return true;
if (!mClasses.tryAllocBuffer(num_behaviors, heap))
return false;
for (s32 i = 0, n = mClasses.size(); i != n; ++i)
mClasses(i) = nullptr;
auto it_class = mClasses.begin();
const auto it_class_end = mClasses.end();
Behavior::InitArg arg;
arg.actor = actor;
s32 predelete_cb_num = 0;
s32 update_cb_num = 0;
for (; it_class != it_class_end; ++it_class) {
arg.def_idx = it_class.getIndex();
const char* name = aiprog->getBehaviors()[it_class.getIndex()].mClassName;
auto* factory = getFactory(name);
if (factory)
*it_class = factory->create_fn(arg, heap);
else
*it_class = new (heap) DummyBehavior(arg);
if (!*it_class)
return false;
update_cb_num += (*it_class)->hasUpdateForPreDeleteCb();
predelete_cb_num += (*it_class)->hasPreDeleteCb();
}
// Allocate the callback lists.
if (predelete_cb_num != 0) {
if (!mOnPreDeleteCbs.tryAllocBuffer(predelete_cb_num, heap))
return false;
for (s32 i = 0; i < predelete_cb_num; ++i)
mOnPreDeleteCbs(i) = nullptr;
}
if (update_cb_num != 0) {
if (!mUpdateForPreDeleteCbs.tryAllocBuffer(update_cb_num, heap))
return false;
for (s32 i = 0; i < update_cb_num; ++i)
mUpdateForPreDeleteCbs(i) = nullptr;
}
// Initialize each class.
s32 idx_cb1 = 0, idx_cb2 = 0;
for (auto it = mClasses.begin(), end = mClasses.end(); it != end; ++it) {
if (!(*it)->init(heap))
return false;
if ((*it)->hasUpdateForPreDeleteCb()) {
mUpdateForPreDeleteCbs[idx_cb2] = *it;
++idx_cb2;
}
if ((*it)->hasPreDeleteCb()) {
mOnPreDeleteCbs[idx_cb1] = *it;
++idx_cb1;
}
}
return true;
}
bool Behaviors::updateForPreDelete() const {
bool ok = true;
for (auto* cb : mUpdateForPreDeleteCbs) {
if (cb)
ok &= cb->updateForPreDelete();
}
return ok;
}
void Behaviors::onPreDelete() const {
for (auto* cb : mOnPreDeleteCbs) {
if (cb)
cb->onPreDelete();
}
}
BehaviorFactory* Behaviors::getFactory(const sead::SafeString& name) {
const u32 name_hash = sead::HashCRC32::calcStringHash(name);
const s32 idx = sFactories.binarySearch(
name_hash, +[](const BehaviorFactory& 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 Behaviors::setFactories(int count, BehaviorFactory* factories) {
sFactories.setBuffer(count, factories);
}
} // namespace ksys::act::ai

View File

@ -3,6 +3,7 @@
#include <basis/seadTypes.h>
#include <container/seadBuffer.h>
#include <prim/seadRuntimeTypeInfo.h>
#include <prim/seadSafeString.h>
#include "KingSystem/Utils/Types.h"
namespace ksys::act {
@ -25,16 +26,18 @@ public:
explicit Behavior(const InitArg& arg);
virtual ~Behavior() = default;
virtual bool m4() { return false; }
virtual bool m5() { return false; }
bool init(sead::Heap* heap);
virtual bool hasPreDeleteCb() { return false; }
virtual bool hasUpdateForPreDeleteCb() { return false; }
virtual bool m6() { return true; }
virtual void m7() {}
virtual void m8() {}
virtual void m9() {}
virtual void m10() {}
virtual void m11() {}
virtual bool m12() { return true; }
virtual void m13() {}
virtual bool updateForPreDelete() { return true; }
virtual void onPreDelete() {}
protected:
Actor* mActor{};
@ -46,6 +49,12 @@ protected:
};
KSYS_CHECK_SIZE_NX150(Behavior, 0x28);
struct BehaviorFactory {
using CreateFn = Behavior* (*)(const Behavior::InitArg& arg, sead::Heap* heap);
u32 hash;
CreateFn create_fn;
};
class Behaviors {
public:
Behaviors();
@ -53,11 +62,22 @@ public:
void finalize();
sead::Buffer<Behavior*> classes;
// TODO: rename
sead::Buffer<Behavior*> x;
// TODO: rename
sead::Buffer<Behavior*> y;
bool init(Actor* actor, sead::Heap* heap);
bool updateForPreDelete() const;
void onPreDelete() const;
const sead::Buffer<Behavior*>& getClasses() const { return mClasses; }
static BehaviorFactory* getFactory(const sead::SafeString& name);
static void setFactories(int count, BehaviorFactory* factories);
private:
static inline sead::Buffer<BehaviorFactory> sFactories;
sead::Buffer<Behavior*> mClasses;
// Non-owning buffer.
sead::Buffer<Behavior*> mOnPreDeleteCbs;
// Non-owning buffer.
sead::Buffer<Behavior*> mUpdateForPreDeleteCbs;
};
} // namespace ksys::act::ai

View File

@ -0,0 +1,7 @@
#include "KingSystem/ActorSystem/behaviorDummyBehavior.h"
namespace ksys::act::ai {
DummyBehavior::DummyBehavior(const Behavior::InitArg& arg) : Behavior(arg) {}
} // namespace ksys::act::ai

View File

@ -0,0 +1,13 @@
#pragma once
#include "KingSystem/ActorSystem/actAiBehavior.h"
namespace ksys::act::ai {
class DummyBehavior : public Behavior {
SEAD_RTTI_OVERRIDE(DummyBehavior, Behavior)
public:
explicit DummyBehavior(const InitArg& arg);
};
} // namespace ksys::act::ai