diff options
| author | Léo Lam <leo@leolam.fr> | 2021-08-05 16:23:25 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2021-08-07 14:44:27 +0200 |
| commit | 802be64d8e41917b002cd9c21c500c91f9b96c93 (patch) | |
| tree | 029afbad7c8b5f1cbad4a75f81851d1a11e45734 /src/KingSystem/ActorSystem | |
| parent | 9d4dbaf8157231bfcd67defc8809bdc2cefdebb0 (diff) | |
ksys/act: Start adding Awareness
Incomplete.
Diffstat (limited to 'src/KingSystem/ActorSystem')
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(¶ms.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 |
