botw/src/KingSystem/GameData/gdtManager.h

612 lines
35 KiB
C++

#pragma once
#include <container/seadRingBuffer.h>
#include <container/seadSafeArray.h>
#include <filedevice/seadArchiveFileDevice.h>
#include <framework/seadMethodTree.h>
#include <heap/seadDisposer.h>
#include <prim/seadDelegateEventSlot.h>
#include <prim/seadTypedBitFlag.h>
#include <thread/seadMutex.h>
#include <type_traits>
#include "KingSystem/GameData/gdtTriggerParam.h"
#include "KingSystem/Resource/resHandle.h"
#include "KingSystem/System/KingEditor.h"
#include "KingSystem/Utils/Byaml/Byaml.h"
#include "KingSystem/Utils/Types.h"
namespace sead {
class Framework;
class MethodTreeMgr;
} // namespace sead
namespace ksys::gdt {
namespace detail {
template <typename T>
struct SetterTraits {
static constexpr bool isVectorType() {
return std::is_same_v<T, sead::Vector2f> || std::is_same_v<T, sead::Vector3f> ||
std::is_same_v<T, sead::Vector4f>;
}
static constexpr bool isStringType() { return std::is_same_v<T, const char*>; }
static constexpr bool isInlineType() {
return std::is_same_v<T, bool> || std::is_same_v<T, s32> || std::is_same_v<T, f32> ||
isStringType();
}
using ArgType = std::conditional_t<isInlineType(), T, const T&>;
using WrapperArgType = std::conditional_t<isStringType(), const sead::SafeString&, ArgType>;
using NoCheckForceArgType = T;
static ArgType convertValue(WrapperArgType v) {
if constexpr (isStringType())
return v.cstr();
else
return v;
}
};
} // namespace detail
enum class FlagHandle : u32 {};
constexpr FlagHandle InvalidHandle = FlagHandle(-1);
class TriggerParamRef {
public:
TriggerParamRef(TriggerParam** param_1, TriggerParam** param, bool check_permissions,
bool propagate_param_1_changes, bool change_only_once)
: mParam1(param_1), mParam(param), mCheckPermissions(check_permissions),
mPropagateParam1Changes(propagate_param_1_changes), mChangeOnlyOnce(change_only_once) {}
virtual ~TriggerParamRef() = default;
class Proxy {
public:
TriggerParam* getBuffer() const { return mUseParam1 ? *mRef.mParam1 : *mRef.mParam; }
TriggerParam* getBuffer0() const { return *mRef.mParam; }
TriggerParam* getBuffer1() const { return *mRef.mParam1; }
// region Value getters
#define PROXY_GET_SET_IMPL_(GET_NAME, SET_NAME, TYPE) \
bool GET_NAME(TYPE* value, s32 index) const { \
return getBuffer()->GET_NAME(value, index, mRef.mCheckPermissions); \
} \
bool GET_NAME(TYPE* value, s32 array_index, s32 index) const { \
return getBuffer()->GET_NAME(value, array_index, index, mRef.mCheckPermissions); \
} \
bool GET_NAME(TYPE* value, const sead::SafeString& name) const { \
return getBuffer()->GET_NAME(value, name, mRef.mCheckPermissions); \
} \
bool GET_NAME(TYPE* value, const sead::SafeString& array_name, s32 index) const { \
return getBuffer()->GET_NAME(value, array_name, index, mRef.mCheckPermissions); \
} \
\
bool SET_NAME(TYPE const& value, s32 idx, bool bypass_one_trigger_check = false) { \
if (mRef.mChangeOnlyOnce) \
return false; \
if (!getBuffer1()->SET_NAME(value, idx, mRef.mCheckPermissions, bypass_one_trigger_check)) \
return false; \
if (mRef.mPropagateParam1Changes) \
getBuffer0()->SET_NAME(value, idx, mRef.mCheckPermissions, bypass_one_trigger_check); \
return true; \
} \
bool SET_NAME(TYPE const& value, s32 array_idx, s32 idx, \
bool bypass_one_trigger_check = false) { \
if (mRef.mChangeOnlyOnce) \
return false; \
if (!getBuffer1()->SET_NAME(value, array_idx, idx, mRef.mCheckPermissions, \
bypass_one_trigger_check)) \
return false; \
if (mRef.mPropagateParam1Changes) \
getBuffer0()->SET_NAME(value, array_idx, idx, mRef.mCheckPermissions, \
bypass_one_trigger_check); \
return true; \
} \
bool SET_NAME(TYPE const& value, const sead::SafeString& name, \
bool bypass_one_trigger_check = false) { \
if (mRef.mChangeOnlyOnce) \
return false; \
if (!getBuffer1()->SET_NAME(value, name, mRef.mCheckPermissions, true, \
bypass_one_trigger_check)) \
return false; \
if (mRef.mPropagateParam1Changes) \
getBuffer0()->SET_NAME(value, name, mRef.mCheckPermissions, true, \
bypass_one_trigger_check); \
return true; \
} \
bool SET_NAME(TYPE const& value, const sead::SafeString& name, s32 idx, \
bool bypass_one_trigger_check = false) { \
if (mRef.mChangeOnlyOnce) \
return false; \
if (!getBuffer1()->SET_NAME(value, name, idx, mRef.mCheckPermissions, true, \
bypass_one_trigger_check)) \
return false; \
if (mRef.mPropagateParam1Changes) \
getBuffer0()->SET_NAME(value, name, idx, mRef.mCheckPermissions, true, \
bypass_one_trigger_check); \
return true; \
}
PROXY_GET_SET_IMPL_(getBool, setBool, bool)
PROXY_GET_SET_IMPL_(getS32, setS32, s32)
PROXY_GET_SET_IMPL_(getF32, setF32, f32)
PROXY_GET_SET_IMPL_(getStr, setStr, char const*)
PROXY_GET_SET_IMPL_(getStr64, setStr64, char const*)
PROXY_GET_SET_IMPL_(getStr256, setStr256, char const*)
PROXY_GET_SET_IMPL_(getVec2f, setVec2f, sead::Vector2f)
PROXY_GET_SET_IMPL_(getVec3f, setVec3f, sead::Vector3f)
PROXY_GET_SET_IMPL_(getVec4f, setVec4f, sead::Vector4f)
#undef PROXY_GET_SET_IMPL_
#define PROXY_RESET_IMPL_(NAME) \
bool NAME(s32 idx) { return getBuffer1()->NAME(idx, mRef.mCheckPermissions); } \
bool NAME(s32 idx, s32 sub_idx) { \
return getBuffer1()->NAME(idx, sub_idx, mRef.mCheckPermissions); \
} \
bool NAME(const sead::SafeString& name) { \
return getBuffer1()->NAME(name, mRef.mCheckPermissions); \
} \
bool NAME(const sead::SafeString& name, s32 sub_idx) { \
return getBuffer1()->NAME(name, sub_idx, mRef.mCheckPermissions); \
}
PROXY_RESET_IMPL_(resetBool)
PROXY_RESET_IMPL_(resetS32)
PROXY_RESET_IMPL_(resetF32)
PROXY_RESET_IMPL_(resetStr)
PROXY_RESET_IMPL_(resetStr64)
PROXY_RESET_IMPL_(resetStr256)
PROXY_RESET_IMPL_(resetVec2f)
PROXY_RESET_IMPL_(resetVec3f)
PROXY_RESET_IMPL_(resetVec4f)
#undef PROXY_RESET_IMPL_
private:
friend class TriggerParamRef;
Proxy(const TriggerParamRef& ref, bool param1) : mUseParam1(param1), mRef(ref) {}
bool mUseParam1;
const TriggerParamRef& mRef;
};
Proxy get() const { return Proxy(*this, false); }
Proxy get1() const { return Proxy(*this, true); }
void setBuffers(TriggerParam** param1, TriggerParam** param) {
mParam1 = param1;
mParam = param;
}
bool shouldCheckPermissions() const { return mCheckPermissions; }
bool shouldPropagateParam1Changes() const { return mPropagateParam1Changes; }
bool shouldChangeOnlyOnce() const { return mChangeOnlyOnce; }
void setCheckPermissions(bool on) { mCheckPermissions = on; }
void setPropagateParam1Changes(bool on) { mPropagateParam1Changes = on; }
void setChangeOnlyOnce(bool on) { mChangeOnlyOnce = on; }
private:
TriggerParam** mParam1;
TriggerParam** mParam;
bool mCheckPermissions;
bool mPropagateParam1Changes;
bool mChangeOnlyOnce;
};
KSYS_CHECK_SIZE_NX150(TriggerParamRef, 0x20);
class IManager {
public:
virtual ~IManager() = 0;
};
inline IManager::~IManager() = default;
class Manager : public IManager, public KingEditorComponent {
SEAD_SINGLETON_DISPOSER(Manager)
Manager();
~Manager() override;
const char* getName() const override { return "GameData"; }
void syncData(const char* data) override;
public:
struct ResetEvent {
virtual ~ResetEvent() = default;
TriggerParam* param = nullptr;
};
struct ReinitEvent {
virtual ~ReinitEvent() = default;
};
using ResetSignal = sead::DelegateEvent<ResetEvent*>;
using ReinitSignal = sead::DelegateEvent<ReinitEvent*>;
sead::Heap* getGameDataHeap() const { return mGameDataHeap; }
sead::Heap* getSaveAreaHeap() const { return mSaveAreaHeap; }
sead::Heap* getGameDataComHeap() const { return mGameDataComHeap; }
TriggerParamRef& getParam() { return mParam; }
TriggerParamRef& getParamBypassPerm() { return mParamBypassPerm; }
#define GDT_GET_HANDLE_(NAME, GET_IDX_NAME) \
FlagHandle NAME(const sead::SafeString& name) const { \
const auto prefix = mCurrentFlagHandlePrefix; \
const auto hash = sead::HashCRC32::calcStringHash(name); \
return makeFlagHandle(prefix, mParam.get1().getBuffer()->GET_IDX_NAME(hash)); \
}
GDT_GET_HANDLE_(getBoolHandle, TriggerParam::getBoolIdx)
GDT_GET_HANDLE_(getS32Handle, TriggerParam::getS32Idx)
GDT_GET_HANDLE_(getF32Handle, TriggerParam::getF32Idx)
GDT_GET_HANDLE_(getStrHandle, TriggerParam::getStrIdx)
GDT_GET_HANDLE_(getStr64Handle, TriggerParam::getStr64Idx)
GDT_GET_HANDLE_(getStr256Handle, TriggerParam::getStr256Idx)
GDT_GET_HANDLE_(getVec2fHandle, TriggerParam::getVec2fIdx)
GDT_GET_HANDLE_(getVec3fHandle, TriggerParam::getVec3fIdx)
GDT_GET_HANDLE_(getVec4fHandle, TriggerParam::getVec4fIdx)
GDT_GET_HANDLE_(getBoolArrayHandle, TriggerParam::getBoolArrayIdx)
GDT_GET_HANDLE_(getS32ArrayHandle, TriggerParam::getS32ArrayIdx)
GDT_GET_HANDLE_(getF32ArrayHandle, TriggerParam::getF32ArrayIdx)
GDT_GET_HANDLE_(getStrArrayHandle, TriggerParam::getStrArrayIdx)
GDT_GET_HANDLE_(getStr64ArrayHandle, TriggerParam::getStr64ArrayIdx)
GDT_GET_HANDLE_(getStr256ArrayHandle, TriggerParam::getStr256ArrayIdx)
GDT_GET_HANDLE_(getVec2fArrayHandle, TriggerParam::getVec2fArrayIdx)
GDT_GET_HANDLE_(getVec3fArrayHandle, TriggerParam::getVec3fArrayIdx)
GDT_GET_HANDLE_(getVec4fArrayHandle, TriggerParam::getVec4fArrayIdx)
#undef GDT_GET_HANDLE_
#define GDT_GET_(NAME, T) \
bool NAME(FlagHandle handle, T* value, bool debug = false) { \
return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \
return ref.get().NAME(value, idx); \
}); \
} \
bool NAME(FlagHandle handle, T* value, s32 sub_idx, bool debug = false) { \
return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \
return ref.get().NAME(value, idx, sub_idx); \
}); \
}
GDT_GET_(getBool, bool)
GDT_GET_(getS32, s32)
GDT_GET_(getF32, f32)
GDT_GET_(getStr, char const*)
GDT_GET_(getStr64, char const*)
GDT_GET_(getStr256, char const*)
GDT_GET_(getVec2f, sead::Vector2f)
GDT_GET_(getVec3f, sead::Vector3f)
GDT_GET_(getVec4f, sead::Vector4f)
#undef GDT_GET_
#define GDT_SET_(NAME, TRAITS) \
/* Setters (by handle) */ \
KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, FlagHandle handle, bool debug, \
bool force) { \
if (mBitFlags.isOn(BitFlag::_40000)) \
return false; \
return unwrapHandle<true>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \
return ref.get().NAME(value, idx, force); \
}); \
} \
bool NAME(TRAITS::ArgType value, FlagHandle handle) { \
return NAME(value, handle, false, false); \
} \
bool NAME##NoCheck(TRAITS::ArgType value, FlagHandle handle) { \
return NAME(value, handle, true, false); \
} \
bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, FlagHandle handle) { \
return NAME(value, handle, true, true); \
} \
/* Setters for arrays (by handle) */ \
KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, FlagHandle handle, bool debug, bool force, \
s32 sub_idx) { \
if (mBitFlags.isOn(BitFlag::_40000)) \
return false; \
return unwrapHandle<true>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \
return ref.get().NAME(value, idx, sub_idx, force); \
}); \
} \
bool NAME(TRAITS::ArgType value, FlagHandle handle, s32 sub_idx) { \
return NAME(value, handle, false, false, sub_idx); \
} \
bool NAME##NoCheck(TRAITS::ArgType value, FlagHandle handle, s32 sub_idx) { \
return NAME(value, handle, true, false, sub_idx); \
} \
bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, FlagHandle handle, s32 sub_idx) { \
return NAME(value, handle, true, true, sub_idx); \
} \
/* Setters (by name) */ \
KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, const sead::SafeString& name, bool debug, \
bool force) { \
if (mBitFlags.isOn(BitFlag::_40000)) \
return false; \
auto& ref = debug ? getParamBypassPerm() : getParam(); \
return ref.get().NAME(value, name, force); \
} \
[[gnu::noinline]] bool NAME(TRAITS::ArgType value, const sead::SafeString& name) { \
return NAME(value, name, false, false); \
} \
[[gnu::noinline]] bool NAME##NoCheck(TRAITS::ArgType value, const sead::SafeString& name) { \
return NAME(value, name, true, false); \
} \
[[gnu::noinline]] bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, \
const sead::SafeString& name) { \
return NAME(value, name, true, true); \
} \
/* Setters for arrays (by name) */ \
KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, const sead::SafeString& name, bool debug, \
bool force, s32 sub_idx) { \
if (mBitFlags.isOn(BitFlag::_40000)) \
return false; \
auto& ref = debug ? getParamBypassPerm() : getParam(); \
return ref.get().NAME(value, name, sub_idx, force); \
} \
[[gnu::noinline]] bool NAME(TRAITS::ArgType value, const sead::SafeString& name, \
s32 sub_idx) { \
return NAME(value, name, false, false, sub_idx); \
} \
[[gnu::noinline]] bool NAME##NoCheck(TRAITS::ArgType value, const sead::SafeString& name, \
s32 sub_idx) { \
return NAME(value, name, true, false, sub_idx); \
} \
[[gnu::noinline]] bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, \
const sead::SafeString& name, s32 sub_idx) { \
return NAME(value, name, true, true, sub_idx); \
} \
\
bool NAME(TRAITS::WrapperArgType value, FlagHandle handle, bool debug) { \
if (debug) { \
onChangedByDebug(); \
return NAME##NoCheckForce(TRAITS::convertValue(value), handle); \
} \
return NAME(TRAITS::convertValue(value), handle); \
} \
bool NAME(TRAITS::WrapperArgType value, const sead::SafeString& name, bool debug) { \
if (debug) { \
onChangedByDebug(); \
return NAME##NoCheckForce(TRAITS::convertValue(value), name); \
} \
return NAME(TRAITS::convertValue(value), name); \
} \
inline bool NAME##Special(TRAITS::WrapperArgType value, const sead::SafeString& name, \
bool debug, bool force = false) { \
if (debug) { \
onChangedByDebug(); \
auto& ref = debug ? getParamBypassPerm() : getParam(); \
return ref.get().NAME(TRAITS::convertValue(value), name, force); \
} \
return NAME(TRAITS::convertValue(value), name); \
} \
\
bool NAME(TRAITS::WrapperArgType value, FlagHandle handle, bool debug, s32 sub_idx) { \
if (debug) { \
onChangedByDebug(); \
return NAME##NoCheckForce(TRAITS::convertValue(value), handle, sub_idx); \
} \
return NAME(TRAITS::convertValue(value), handle, sub_idx); \
} \
bool NAME(TRAITS::WrapperArgType value, const sead::SafeString& name, bool debug, \
s32 sub_idx) { \
if (debug) { \
onChangedByDebug(); \
return NAME##NoCheckForce(TRAITS::convertValue(value), name, sub_idx); \
} \
return NAME(TRAITS::convertValue(value), name, sub_idx); \
}
GDT_SET_(setBool, detail::SetterTraits<bool>)
GDT_SET_(setS32, detail::SetterTraits<s32>)
GDT_SET_(setF32, detail::SetterTraits<f32>)
GDT_SET_(setStr, detail::SetterTraits<const char*>)
GDT_SET_(setStr64, detail::SetterTraits<const char*>)
GDT_SET_(setStr256, detail::SetterTraits<const char*>)
GDT_SET_(setVec2f, detail::SetterTraits<sead::Vector2f>)
GDT_SET_(setVec3f, detail::SetterTraits<sead::Vector3f>)
GDT_SET_(setVec4f, detail::SetterTraits<sead::Vector4f>)
#undef GDT_SET_
#define GDT_RESET_(NAME) \
KSYS_ALWAYS_INLINE bool NAME##_(FlagHandle handle, bool debug) { \
if (mBitFlags.isOn(BitFlag::_40000)) \
return false; \
return unwrapHandle<false>( \
handle, debug, [&](u32 idx, TriggerParamRef& ref) { return ref.get().NAME(idx); }); \
} \
inline bool NAME(FlagHandle handle) { return NAME##_(handle, false); } \
inline bool NAME##NoCheck(FlagHandle handle) { return NAME##_(handle, true); } \
\
KSYS_ALWAYS_INLINE bool NAME##_(FlagHandle handle, bool debug, s32 sub_idx) { \
if (mBitFlags.isOn(BitFlag::_40000)) \
return false; \
return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \
return ref.get().NAME(idx, sub_idx); \
}); \
} \
inline bool NAME(FlagHandle handle, s32 sub_idx) { return NAME##_(handle, false, sub_idx); } \
inline bool NAME##NoCheck(FlagHandle handle, s32 sub_idx) { \
return NAME##_(handle, true, sub_idx); \
} \
\
inline bool NAME(FlagHandle handle, bool debug) { \
if (debug) { \
onChangedByDebug(); \
return NAME##NoCheck(handle); \
} \
return NAME(handle); \
} \
inline bool NAME(FlagHandle handle, bool debug, s32 sub_idx) { \
if (debug) { \
onChangedByDebug(); \
return NAME##NoCheck(handle, sub_idx); \
} \
return NAME(handle, sub_idx); \
}
GDT_RESET_(resetBool)
GDT_RESET_(resetS32)
GDT_RESET_(resetF32)
GDT_RESET_(resetStr)
GDT_RESET_(resetStr64)
GDT_RESET_(resetStr256)
GDT_RESET_(resetVec2f)
GDT_RESET_(resetVec3f)
GDT_RESET_(resetVec4f)
#undef GDT_RESET_
void increaseS32CommonFlag(s32 value, const sead::SafeString& name, s32 sub_idx, bool debug) {
if (!mIncreaseLogger)
return;
mIncreaseLogger->addRecord(value, name, sub_idx, debug);
if (debug)
onChangedByDebug();
}
void init(sead::Heap* heap, sead::Framework* framework);
void addReinitCallback(ReinitSignal::Slot& slot);
void removeReinitCallback(ReinitSignal::Slot& slot);
private:
enum class BitFlag {
_1 = 0x1,
_2 = 0x2,
_4 = 0x4,
_8 = 0x8,
_10 = 0x10,
_20 = 0x20,
_40 = 0x40,
_80 = 0x80,
_100 = 0x100,
_200 = 0x200,
_400 = 0x400,
_800 = 0x800,
_1000 = 0x1000,
_2000 = 0x2000,
_4000 = 0x4000,
_8000 = 0x8000,
_10000 = 0x10000,
_20000 = 0x20000,
_40000 = 0x40000,
};
enum class ResetFlag {
};
struct MethodTreeNode {
virtual ~MethodTreeNode() = default;
sead::MethodTreeNode node{nullptr};
sead::MethodTreeMgr* method_tree_mgr = nullptr;
};
struct IncreaseLogger {
struct Record {
bool debug = false;
u32 name_hash = 0;
s32 sub_idx = -1;
s32 value = 0;
};
KSYS_CHECK_SIZE_NX150(Record, 0x10);
void addRecord(s32 value, const sead::SafeString& name, s32 sub_idx, bool debug);
u64 _0 = 0;
sead::SafeArray<sead::FixedRingBuffer<Record, 64>, 3> ring_buffers[2];
sead::SafeArray<Record, 0xc0> arrays[2]{};
};
static FlagHandle makeFlagHandle(u32 prefix, s32 idx) {
return FlagHandle(idx | (prefix << 24));
}
/// Extracts a flag index out of a FlagHandle and passes it to the specified callable.
/// fn must be callable with a u32 + TriggerParamRef&
template <bool Write, bool BypassPerm, typename Fn>
KSYS_ALWAYS_INLINE bool unwrapHandle(FlagHandle handle, const Fn& fn) {
const u32 idx = static_cast<u32>(handle);
auto& ref = BypassPerm ? getParamBypassPerm() : getParam();
const auto check = [&] { return !Write || !ref.shouldChangeOnlyOnce(); };
if (mBitFlags.isOff(BitFlag::_8000) && handle != InvalidHandle)
return check() && fn(idx, ref);
return idx >> 24 == mCurrentFlagHandlePrefix && check() && fn(idx & 0xFFFFFF, ref);
}
/// Extracts a flag index out of a FlagHandle and passes it to the specified callable.
/// fn must be callable with a u32 + TriggerParamRef&
template <bool Write, typename Fn>
KSYS_ALWAYS_INLINE bool unwrapHandle(FlagHandle handle, bool debug, const Fn& fn) {
return debug ? unwrapHandle<Write, true>(handle, fn) :
unwrapHandle<Write, false>(handle, fn);
}
void onChangedByDebug() {
setBool(true, "IsChangedByDebug");
mBitFlags.set(BitFlag::_800);
}
void loadGameData(const sead::SafeString& path);
void loadShopGameDataInfo(const sead::SafeString& path);
void unloadResources();
sead::Heap* mGameDataHeap = nullptr;
sead::Heap* mSaveAreaHeap = nullptr;
sead::Heap* mGameDataComHeap = nullptr;
res::Handle mGameDataArcHandle;
sead::SafeArray<res::Handle, 32> mBgdataHandles;
sead::ArchiveFileDevice mGameDataArc{nullptr};
res::Handle mShopGameDataInfoHandle;
al::ByamlIter mShopAreaInfoValues;
const u8* mShopAreaInfoHashes = nullptr;
al::ByamlIter mShopSoldOutInfoValues;
const u8* mShopSoldOutInfoHashes = nullptr;
TriggerParamRef mParamBypassPerm{&mFlagBuffer1, &mFlagBuffer, false, false, false};
TriggerParamRef mParam{&mFlagBuffer1, &mFlagBuffer, true, false, false};
IncreaseLogger* mIncreaseLogger = nullptr;
TriggerParam* mFlagBuffer1;
TriggerParam* mFlagBuffer;
TriggerParam* mRetryBuffer;
TriggerParam* mGimmickResetBuffer;
sead::TypedBitFlag<BitFlag> mBitFlags;
sead::TypedBitFlag<ResetFlag> mResetFlags;
u32 _c20 = 0;
u32 mNumFlagsToReset = 0;
u32 mCurrentFlagHandlePrefix = 0;
ReinitSignal mReinitSignal;
ResetSignal mResetSignal;
MethodTreeNode mMethodTreeNode;
void* mDelegate1 = nullptr; // FIXME: figure out what this is
sead::IDelegateR<const sead::SafeString&>* mGetMapNameDelegate = nullptr;
sead::FixedSafeString<64> mStr; // TODO: rename
u32 mTrackerBlockSaveNumberFlagCrc32 = 0;
u32 mSyncStep = 0;
sead::Mutex mMutex;
};
KSYS_CHECK_SIZE_NX150(Manager, 0xdc8);
} // namespace ksys::gdt