mirror of
https://github.com/zeldaret/botw
synced 2026-09-04 10:12:02 -04:00
ksys/act: Start adding Awareness
Incomplete.
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <basis/seadTypes.h>
|
||||
|
||||
namespace ksys::act {
|
||||
|
||||
u32 getAwarenessTerrorFlags(u32 hash);
|
||||
u32 getAwarenessSensorFlags(u32 hash);
|
||||
|
||||
} // namespace ksys::act
|
||||
@@ -0,0 +1 @@
|
||||
#include "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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user