ksys/act: Start adding Awareness

Incomplete.
This commit is contained in:
Léo Lam
2021-08-05 16:23:25 +02:00
parent 9d4dbaf815
commit 802be64d8e
10 changed files with 554 additions and 51 deletions
@@ -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
@@ -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
+10 -2
View File
@@ -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