summaryrefslogtreecommitdiff
path: root/src/KingSystem/ActorSystem
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-08-05 16:23:25 +0200
committerLéo Lam <leo@leolam.fr>2021-08-07 14:44:27 +0200
commit802be64d8e41917b002cd9c21c500c91f9b96c93 (patch)
tree029afbad7c8b5f1cbad4a75f81851d1a11e45734 /src/KingSystem/ActorSystem
parent9d4dbaf8157231bfcd67defc8809bdc2cefdebb0 (diff)
ksys/act: Start adding Awareness
Incomplete.
Diffstat (limited to 'src/KingSystem/ActorSystem')
-rw-r--r--src/KingSystem/ActorSystem/Awareness/actAwareness.cpp259
-rw-r--r--src/KingSystem/ActorSystem/Awareness/actAwareness.h154
-rw-r--r--src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.cpp47
-rw-r--r--src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.h10
-rw-r--r--src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.cpp1
-rw-r--r--src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.h24
-rw-r--r--src/KingSystem/ActorSystem/CMakeLists.txt12
7 files changed, 505 insertions, 2 deletions
diff --git a/src/KingSystem/ActorSystem/Awareness/actAwareness.cpp b/src/KingSystem/ActorSystem/Awareness/actAwareness.cpp
new file mode 100644
index 00000000..9791b1e7
--- /dev/null
+++ b/src/KingSystem/ActorSystem/Awareness/actAwareness.cpp
@@ -0,0 +1,259 @@
+#include "KingSystem/ActorSystem/Awareness/actAwareness.h"
+#include <agl/Utils/aglParameter.h>
+#include <agl/Utils/aglResParameter.h>
+#include <container/seadSafeArray.h>
+#include <cstring>
+#include <prim/seadScopedLock.h>
+#include "KingSystem/ActorSystem/Awareness/actAwarenessDefs.h"
+#include "KingSystem/ActorSystem/Awareness/actAwarenessInstance.h"
+#include "KingSystem/Resource/resHandle.h"
+#include "KingSystem/Resource/resLoadRequest.h"
+
+namespace ksys::act {
+
+SEAD_SINGLETON_DISPOSER_IMPL(Awareness)
+
+bool Awareness::Instances::registerInstance(AwarenessInstance* instance) {
+ auto lock = sead::makeScopedLock(critical_section);
+
+ if (instances.size() <= count)
+ return false;
+
+ instances[count].instance = instance;
+ ++count;
+ return true;
+}
+
+void Awareness::Instances::deregisterInstance(AwarenessInstance* instance) {
+ auto lock = sead::makeScopedLock(critical_section);
+
+ for (int i = 0; i < count; ++i) {
+ if (instances[i].instance == instance) {
+ // Swap and remove. The instance order doesn't matter here.
+ --count;
+ instances[i] = instances[count];
+ break;
+ }
+ }
+}
+
+Awareness::~Awareness() {
+ finalize();
+}
+
+void Awareness::finalize() {
+ mTerrorFilters.finalize();
+ mSensorFilters.finalize();
+ mSensorFilterBuffers.finalize();
+}
+
+bool Awareness::init(const Awareness::InitArg& arg, sead::Heap* heap) {
+ mHeap = heap;
+
+ if (!loadSystemData())
+ return false;
+
+ mInstances.instances.allocBufferAssert(arg.num_instances_max, heap);
+ if (!mInstances.instances.isBufferReady())
+ return false;
+
+ mLinks2.buffer.allocBufferAssert(arg.num_links2_max, heap);
+ if (!mLinks2.buffer.isBufferReady())
+ return false;
+
+ mLinks.buffer.allocBufferAssert(arg.num_links_max, heap);
+ if (!mLinks.buffer.isBufferReady())
+ return false;
+
+ return true;
+}
+
+// agl::utl::ResParameter::getParam being a pain as usual
+#ifdef NON_MATCHING
+bool Awareness::loadSystemData() {
+ if (!mHeap)
+ return false;
+
+ res::Handle handle;
+ res::LoadRequest req;
+ req.mRequester = "AwarenessSystemData";
+ req._26 = false;
+
+ {
+ const auto* res = sead::DynamicCast<sead::DirectResource>(
+ handle.load("Awareness/TerrorFilter.bawntable", &req));
+ if (!res)
+ return false;
+
+ const agl::utl::ResParameterArchive archive{res->getRawData()};
+ const auto root = archive.getRootList();
+ const auto list = agl::utl::getResParameterList(root, "TerrorFilter");
+ if (list.getResParameterObjNum() == 0)
+ return false;
+ if (!mTerrorFilters.allocBuffer(list.getResParameterObjNum(), mHeap))
+ return false;
+
+ for (auto it = list.objBegin(); it != list.objEnd(); ++it) {
+ const auto obj = it.getObj();
+ const u32 target = obj.getParameterObjNameHash();
+ u32 flags = 0;
+ for (auto it_p = obj.begin(); it_p != obj.end(); ++it_p) {
+ const auto param = it_p.getParam();
+ const auto enabled = *param.getData<int>();
+ if (enabled)
+ flags |= getAwarenessTerrorFlags(param.getParameterNameHash());
+ }
+ mTerrorFilters.insert(TerrorFilter{flags, target});
+ }
+ }
+
+ handle.requestUnload2();
+
+ {
+ const auto* res = sead::DynamicCast<sead::DirectResource>(
+ handle.load("Awareness/SensorFilter.bsft", &req));
+ if (!res)
+ return false;
+
+ const agl::utl::ResParameterArchive archive{res->getRawData()};
+ const auto root = archive.getRootList();
+ const auto list = agl::utl::getResParameterList(root, "SensorFilter");
+ if (list.getResParameterObjNum() == 0)
+ return false;
+ if (!mSensorFilters.allocBuffer(list.getResParameterObjNum(), mHeap))
+ return false;
+
+ for (auto it = list.objBegin(); it != list.objEnd(); ++it) {
+ const auto obj = it.getObj();
+ const u32 target = obj.getParameterObjNameHash();
+ u32 flags = 0;
+ for (auto it_p = obj.begin(); it_p != obj.end(); ++it_p) {
+ const auto param = it_p.getParam();
+ const auto enabled = *param.getData<int>();
+ if (enabled)
+ flags |= getAwarenessSensorFlags(param.getParameterNameHash());
+ }
+ mSensorFilters.insert(SensorFilter{flags, target});
+ }
+ }
+
+ handle.requestUnload2();
+
+ {
+ const auto* res = sead::DynamicCast<sead::DirectResource>(
+ handle.load("Awareness/SensorFilterBuffer.bsfbt", &req));
+ if (!res)
+ return false;
+
+ const agl::utl::ResParameterArchive archive{res->getRawData()};
+ const auto root = archive.getRootList();
+ const auto list = agl::utl::getResParameterList(root, "SensorFilterBuffer");
+ if (list.getResParameterObjNum() == 0)
+ return false;
+ if (!mSensorFilterBuffers.allocBuffer(list.getResParameterObjNum(), mHeap))
+ return false;
+
+ for (auto it = list.objBegin(); it != list.objEnd(); ++it) {
+ const auto obj = it.getObj();
+ const u32 target = obj.getParameterObjNameHash();
+
+ SensorFilterBuffer::Params params;
+ for (auto it_p = obj.begin(); it_p != obj.end(); ++it_p) {
+ const auto param = it_p.getParam();
+ std::memcpy(&params.raw[it_p.getIndex()],
+ param.ptrBytes() + param.ptr()->getOffset(), sizeof(int));
+ if (it_p.getIndex() >= params.raw.size())
+ return false;
+ }
+
+ mSensorFilterBuffers.insert(SensorFilterBuffer{params, target});
+ }
+ }
+
+ handle.requestUnload2();
+
+ return true;
+}
+#endif
+
+bool Awareness::initBeforeStageGen() {
+ mInstances.count = 0;
+ mInstances.ticks = 0;
+ mLinks2.count = 0;
+ mLinks.count = 0;
+ mUnk.finalize();
+ setPaused(false);
+ return true;
+}
+
+void Awareness::setPaused(bool paused) {
+ mFlags.changeBit(Flag(Flag::Paused), paused);
+ if (paused) {
+ mFlags.setBit(Flag(Flag::_2));
+ } else {
+ mFlags.setBit(Flag(Flag::_6));
+ }
+}
+
+void Awareness::setEventActive(bool active) {
+ mFlags.changeBit(Flag(Flag::EventActive), active);
+ if (active) {
+ mFlags.setBit(Flag(Flag::_5));
+ } else {
+ mFlags.setBit(Flag(Flag::_6));
+ }
+}
+
+void Awareness::calc() {
+ if (checkFlag(Flag::Paused)) {
+ if (checkFlag(Flag::_2))
+ resetFlag(Flag::_2);
+
+ } else if (checkFlag(Flag::EventActive)) {
+ if (checkFlag(Flag::_5)) {
+ mInstances.calcForEvent(true);
+ resetFlag(Flag::_5);
+ }
+
+ } else if (checkFlag(Flag::_3)) {
+ resetFlag(Flag::_3);
+
+ } else if (checkFlag(Flag::_6)) {
+ resetFlag(Flag::_6);
+
+ } else {
+ mInstances.calc();
+ }
+
+ mUnk.calc();
+ mLinks2.calc();
+ mLinks.calc();
+ resetFlag(Flag::_0);
+}
+
+void Awareness::Links2::calc() {
+ count = 0;
+}
+
+void Awareness::Links::calc() {
+ count = 0;
+}
+
+void Awareness::Instances::calc() {
+ ++ticks;
+ for (int i = 0; i < count; ++i) {
+ if ((i + ticks) % 8 == 0) {
+ get(i)->calc2();
+ }
+ get(i)->calc();
+ }
+}
+
+void Awareness::Instances::calcForEvent(bool check_334) {
+ for (int i = 0; i < count; ++i) {
+ if (!check_334 || get(i)->_334 < 0)
+ get(i)->calcForEvent();
+ }
+}
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/Awareness/actAwareness.h b/src/KingSystem/ActorSystem/Awareness/actAwareness.h
new file mode 100644
index 00000000..970ec635
--- /dev/null
+++ b/src/KingSystem/ActorSystem/Awareness/actAwareness.h
@@ -0,0 +1,154 @@
+#pragma once
+
+#include <container/seadBuffer.h>
+#include <container/seadOrderedSet.h>
+#include <container/seadSafeArray.h>
+#include <heap/seadDisposer.h>
+#include <prim/seadEnum.h>
+#include <prim/seadTypedBitFlag.h>
+#include <thread/seadAtomic.h>
+#include <thread/seadCriticalSection.h>
+#include "KingSystem/ActorSystem/actBaseProcLink.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::act {
+
+class AwarenessInstance;
+
+class Awareness {
+ SEAD_SINGLETON_DISPOSER(Awareness)
+
+ Awareness() = default;
+ virtual ~Awareness();
+
+public:
+ struct InitArg {
+ int num_instances_max;
+ // TODO: rename
+ int num_links_max;
+ int num_links2_max;
+ };
+
+ bool init(const InitArg& arg, sead::Heap* heap);
+ bool initBeforeStageGen();
+ void setPaused(bool paused);
+ void setEventActive(bool active);
+ void calc();
+
+private:
+ friend class AwarenessInstance;
+
+ SEAD_ENUM(Flag, _0, Paused, _2, _3, EventActive, _5, _6)
+
+ // FIXME: rename
+ struct Unk1 {
+ virtual ~Unk1() { finalize(); }
+ void finalize();
+ void calc();
+
+ void* _8{};
+ void* _10{};
+ };
+
+ struct TerrorFilter {
+ bool operator<(const TerrorFilter& rhs) const { return target < rhs.target; }
+
+ u32 flags;
+ u32 target;
+ };
+
+ struct SensorFilter {
+ bool operator<(const SensorFilter& rhs) const { return target < rhs.target; }
+
+ u32 flags;
+ u32 target;
+ };
+
+ struct SensorFilterBuffer {
+ bool operator<(const SensorFilterBuffer& rhs) const { return target < rhs.target; }
+
+ union Params {
+ struct {
+ int system;
+ int sense;
+ int sight;
+ int worry;
+ int hearing;
+ };
+ sead::SafeArray<int, 5> raw;
+ };
+ Params params;
+ u32 target;
+ };
+
+ struct InstanceRef {
+ AwarenessInstance* instance{};
+ };
+
+ struct Instances {
+ ~Instances() { instances.freeBuffer(); }
+ bool registerInstance(AwarenessInstance* instance);
+ void deregisterInstance(AwarenessInstance* instance);
+ void calc();
+ void calcForEvent(bool check_334);
+ AwarenessInstance*& get(int i) { return instances[i].instance; }
+ AwarenessInstance*& operator[](int i) { return get(i); }
+
+ sead::Buffer<InstanceRef> instances;
+ int count = 0;
+ int ticks = 0;
+ sead::CriticalSection critical_section;
+ };
+
+ // FIXME: rename
+ struct Link {
+ BaseProcLink link;
+ // TODO: physics body?
+ void* _10{};
+ };
+
+ // FIXME: rename
+ struct Link2 {
+ Link2() { _10 = 0; }
+ BaseProcLink link;
+ u8 _10{};
+ u32 _14{};
+ void* _18{};
+ };
+
+ // FIXME: rename
+ struct Links {
+ void calc();
+
+ sead::Buffer<Link> buffer;
+ sead::Atomic<int> count;
+ };
+
+ // FIXME: rename
+ struct Links2 {
+ void calc();
+
+ sead::Buffer<Link2> buffer;
+ sead::Atomic<int> count;
+ };
+
+ void finalize();
+ bool loadSystemData();
+
+ bool checkFlag(Flag flag) const { return (1u << flag) & mFlags.getDirect(); }
+ void setFlag(Flag flag) { mFlags.setBit(flag); }
+ void resetFlag(Flag flag) { mFlags.resetBit(flag); }
+
+ Instances mInstances;
+ Links mLinks;
+ Links2 mLinks2;
+ Unk1 mUnk;
+ sead::OrderedSet<TerrorFilter> mTerrorFilters;
+ sead::OrderedSet<SensorFilter> mSensorFilters;
+ sead::OrderedSet<SensorFilterBuffer> mSensorFilterBuffers;
+ sead::BitFlag8 mFlags;
+ sead::Heap* mHeap{};
+};
+KSYS_CHECK_SIZE_NX150(Awareness, 0x138);
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.cpp b/src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.cpp
new file mode 100644
index 00000000..a12c58f4
--- /dev/null
+++ b/src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.cpp
@@ -0,0 +1,47 @@
+#include "KingSystem/ActorSystem/Awareness/actAwarenessDefs.h"
+#include <agl/Utils/aglParameter.h>
+#include <container/seadSafeArray.h>
+
+namespace ksys::act {
+
+sead::SafeArray<const char*, 13> sAwarenessTerrorTypes = sead::toArray({
+ "TerrorPlayer",
+ "TerrorNpc",
+ "TerrorEnemy",
+ "TerrorGuardian",
+ "TerrorImpulse",
+ "TerrorFire",
+ "TerrorInsect",
+ "TerrorHorse",
+ "TerrorAnimal",
+ "TerrorWolfLink",
+ "TerrorIce",
+ "TerrorElectric",
+ "TerrorManMadeFire",
+});
+
+sead::SafeArray<const char*, 23> sAwarenessSensorTypes = sead::toArray({
+ "Player", "PlayerBomb", "Horse", "Enemy", "Prey", "Predator", "Domestic", "Assassin",
+ "Giant", "NPC", "Material", "Food", "Weapon", "Spirit", "Carry", "Tree",
+ "WolfLink", "Chemical", "Bullet", "Door", "Captured", "Guardian", "All",
+});
+
+u32 getAwarenessTerrorFlags(u32 hash) {
+ for (u32 i = 0; i < u32(sAwarenessTerrorTypes.size()); ++i) {
+ if (agl::utl::ParameterBase::calcHash(sAwarenessTerrorTypes(i)) == hash)
+ return 1 << i;
+ }
+
+ // XXX: wouldn't returning 0 be a better idea?
+ return 0xffffffff;
+}
+
+u32 getAwarenessSensorFlags(u32 hash) {
+ for (u32 i = 0; i < u32(sAwarenessSensorTypes.size()); ++i) {
+ if (agl::utl::ParameterBase::calcHash(sAwarenessSensorTypes(i)) == hash)
+ return 1 << i;
+ }
+ return 0xffffffff;
+}
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.h b/src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.h
new file mode 100644
index 00000000..19238ec9
--- /dev/null
+++ b/src/KingSystem/ActorSystem/Awareness/actAwarenessDefs.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+
+namespace ksys::act {
+
+u32 getAwarenessTerrorFlags(u32 hash);
+u32 getAwarenessSensorFlags(u32 hash);
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.cpp b/src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.cpp
new file mode 100644
index 00000000..ac4e5146
--- /dev/null
+++ b/src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.cpp
@@ -0,0 +1 @@
+#include "KingSystem/ActorSystem/Awareness/actAwarenessInstance.h"
diff --git a/src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.h b/src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.h
new file mode 100644
index 00000000..fba7f6ba
--- /dev/null
+++ b/src/KingSystem/ActorSystem/Awareness/actAwarenessInstance.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::act {
+
+// FIXME
+class AwarenessInstance {
+public:
+ AwarenessInstance();
+ virtual ~AwarenessInstance();
+
+ void calcForEvent();
+ void calc();
+ void calc2();
+
+ u8 _8[0x334 - 0x8];
+ s8 _334;
+ u32 _338;
+};
+KSYS_CHECK_SIZE_NX150(AwarenessInstance, 0x340);
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt
index fe74e421..c071fdf2 100644
--- a/src/KingSystem/ActorSystem/CMakeLists.txt
+++ b/src/KingSystem/ActorSystem/CMakeLists.txt
@@ -1,4 +1,14 @@
target_sources(uking PRIVATE
+ Attention/actAttention.cpp
+ Attention/actAttention.h
+
+ Awareness/actAwareness.cpp
+ Awareness/actAwareness.h
+ Awareness/actAwarenessDefs.cpp
+ Awareness/actAwarenessDefs.h
+ Awareness/actAwarenessInstance.cpp
+ Awareness/actAwarenessInstance.h
+
LOD/actLodState.cpp
LOD/actLodState.h
@@ -56,8 +66,6 @@ target_sources(uking PRIVATE
actAiRoot.h
actASSetting.cpp
actASSetting.h
- Attention/actAttention.cpp
- Attention/actAttention.h
actBaseProc.cpp
actBaseProc.h
actBaseProcCreateTask.cpp