| 1 | #pragma once |
| 2 | |
| 3 | #include <container/seadRingBuffer.h> |
| 4 | #include <container/seadSafeArray.h> |
| 5 | #include <filedevice/seadArchiveFileDevice.h> |
| 6 | #include <framework/seadMethodTree.h> |
| 7 | #include <heap/seadDisposer.h> |
| 8 | #include <prim/seadDelegateEventSlot.h> |
| 9 | #include <prim/seadTypedBitFlag.h> |
| 10 | #include <thread/seadMutex.h> |
| 11 | #include <type_traits> |
| 12 | #include "KingSystem/GameData/gdtFlagHandle.h" |
| 13 | #include "KingSystem/GameData/gdtTriggerParam.h" |
| 14 | #include "KingSystem/Resource/resHandle.h" |
| 15 | #include "KingSystem/System/CoreInfo.h" |
| 16 | #include "KingSystem/System/KingEditor.h" |
| 17 | #include "KingSystem/Utils/Byaml/Byaml.h" |
| 18 | #include "KingSystem/Utils/Types.h" |
| 19 | |
| 20 | namespace sead { |
| 21 | class Framework; |
| 22 | class MethodTreeMgr; |
| 23 | } // namespace sead |
| 24 | |
| 25 | namespace ksys::map { |
| 26 | class MubinIter; |
| 27 | } |
| 28 | |
| 29 | namespace ksys::gdt { |
| 30 | |
| 31 | namespace detail { |
| 32 | |
| 33 | template <typename T> |
| 34 | struct SetterTraits { |
| 35 | static constexpr bool isVectorType() { |
| 36 | return std::is_same_v<T, sead::Vector2f> || std::is_same_v<T, sead::Vector3f> || |
| 37 | std::is_same_v<T, sead::Vector4f>; |
| 38 | } |
| 39 | |
| 40 | static constexpr bool isStringType() { return std::is_same_v<T, const char*>; } |
| 41 | |
| 42 | static constexpr bool isInlineType() { |
| 43 | return std::is_same_v<T, bool> || std::is_same_v<T, s32> || std::is_same_v<T, f32> || |
| 44 | isStringType(); |
| 45 | } |
| 46 | |
| 47 | using ArgType = std::conditional_t<isInlineType(), T, const T&>; |
| 48 | using WrapperArgType = std::conditional_t<isStringType(), const sead::SafeString&, ArgType>; |
| 49 | using NoCheckForceArgType = T; |
| 50 | |
| 51 | static ArgType convertValue(WrapperArgType v) { |
| 52 | if constexpr (isStringType()) |
| 53 | return v.cstr(); |
| 54 | else |
| 55 | return v; |
| 56 | } |
| 57 | }; |
| 58 | |
| 59 | } // namespace detail |
| 60 | |
| 61 | class TriggerParamRef { |
| 62 | public: |
| 63 | TriggerParamRef(TriggerParam** param_1, TriggerParam** param, bool check_permissions, |
| 64 | bool propagate_param_1_changes, bool change_only_once) |
| 65 | : mParam1(param_1), mParam(param), mCheckPermissions(check_permissions), |
| 66 | mPropagateParam1Changes(propagate_param_1_changes), mChangeOnlyOnce(change_only_once) {} |
| 67 | |
| 68 | virtual ~TriggerParamRef() = default; |
| 69 | |
| 70 | class Proxy { |
| 71 | public: |
| 72 | TriggerParam* getBuffer() const { return mUseParam1 ? *mRef.mParam1 : *mRef.mParam; } |
| 73 | TriggerParam* getBuffer0() const { return *mRef.mParam; } |
| 74 | TriggerParam* getBuffer1() const { return *mRef.mParam1; } |
| 75 | |
| 76 | // region Value getters |
| 77 | |
| 78 | #define PROXY_GET_SET_IMPL_(GET_NAME, SET_NAME, TYPE) \ |
| 79 | bool GET_NAME(TYPE* value, s32 index) const { \ |
| 80 | return getBuffer()->GET_NAME(value, index, mRef.mCheckPermissions); \ |
| 81 | } \ |
| 82 | bool GET_NAME(TYPE* value, s32 array_index, s32 index) const { \ |
| 83 | return getBuffer()->GET_NAME(value, array_index, index, mRef.mCheckPermissions); \ |
| 84 | } \ |
| 85 | bool GET_NAME(TYPE* value, const sead::SafeString& name) const { \ |
| 86 | return getBuffer()->GET_NAME(value, name, mRef.mCheckPermissions); \ |
| 87 | } \ |
| 88 | bool GET_NAME(TYPE* value, const sead::SafeString& array_name, s32 index) const { \ |
| 89 | return getBuffer()->GET_NAME(value, array_name, index, mRef.mCheckPermissions); \ |
| 90 | } \ |
| 91 | \ |
| 92 | bool SET_NAME(TYPE const& value, s32 idx, bool bypass_one_trigger_check = false) { \ |
| 93 | if (mRef.mChangeOnlyOnce) \ |
| 94 | return false; \ |
| 95 | if (!getBuffer1()->SET_NAME(value, idx, mRef.mCheckPermissions, bypass_one_trigger_check)) \ |
| 96 | return false; \ |
| 97 | if (mRef.mPropagateParam1Changes) \ |
| 98 | getBuffer0()->SET_NAME(value, idx, mRef.mCheckPermissions, bypass_one_trigger_check); \ |
| 99 | return true; \ |
| 100 | } \ |
| 101 | bool SET_NAME(TYPE const& value, s32 array_idx, s32 idx, \ |
| 102 | bool bypass_one_trigger_check = false) { \ |
| 103 | if (mRef.mChangeOnlyOnce) \ |
| 104 | return false; \ |
| 105 | if (!getBuffer1()->SET_NAME(value, array_idx, idx, mRef.mCheckPermissions, \ |
| 106 | bypass_one_trigger_check)) \ |
| 107 | return false; \ |
| 108 | if (mRef.mPropagateParam1Changes) \ |
| 109 | getBuffer0()->SET_NAME(value, array_idx, idx, mRef.mCheckPermissions, \ |
| 110 | bypass_one_trigger_check); \ |
| 111 | return true; \ |
| 112 | } \ |
| 113 | bool SET_NAME(TYPE const& value, const sead::SafeString& name, \ |
| 114 | bool bypass_one_trigger_check = false) { \ |
| 115 | if (mRef.mChangeOnlyOnce) \ |
| 116 | return false; \ |
| 117 | if (!getBuffer1()->SET_NAME(value, name, mRef.mCheckPermissions, true, \ |
| 118 | bypass_one_trigger_check)) \ |
| 119 | return false; \ |
| 120 | if (mRef.mPropagateParam1Changes) \ |
| 121 | getBuffer0()->SET_NAME(value, name, mRef.mCheckPermissions, true, \ |
| 122 | bypass_one_trigger_check); \ |
| 123 | return true; \ |
| 124 | } \ |
| 125 | bool SET_NAME(TYPE const& value, const sead::SafeString& name, s32 idx, \ |
| 126 | bool bypass_one_trigger_check = false) { \ |
| 127 | if (mRef.mChangeOnlyOnce) \ |
| 128 | return false; \ |
| 129 | if (!getBuffer1()->SET_NAME(value, name, idx, mRef.mCheckPermissions, true, \ |
| 130 | bypass_one_trigger_check)) \ |
| 131 | return false; \ |
| 132 | if (mRef.mPropagateParam1Changes) \ |
| 133 | getBuffer0()->SET_NAME(value, name, idx, mRef.mCheckPermissions, true, \ |
| 134 | bypass_one_trigger_check); \ |
| 135 | return true; \ |
| 136 | } |
| 137 | |
| 138 | PROXY_GET_SET_IMPL_(getBool, setBool, bool) |
| 139 | PROXY_GET_SET_IMPL_(getS32, setS32, s32) |
| 140 | PROXY_GET_SET_IMPL_(getF32, setF32, f32) |
| 141 | PROXY_GET_SET_IMPL_(getStr, setStr, char const*) |
| 142 | PROXY_GET_SET_IMPL_(getStr64, setStr64, char const*) |
| 143 | PROXY_GET_SET_IMPL_(getStr256, setStr256, char const*) |
| 144 | PROXY_GET_SET_IMPL_(getVec2f, setVec2f, sead::Vector2f) |
| 145 | PROXY_GET_SET_IMPL_(getVec3f, setVec3f, sead::Vector3f) |
| 146 | PROXY_GET_SET_IMPL_(getVec4f, setVec4f, sead::Vector4f) |
| 147 | |
| 148 | #undef PROXY_GET_SET_IMPL_ |
| 149 | |
| 150 | #define PROXY_RESET_IMPL_(NAME) \ |
| 151 | bool NAME(s32 idx) { return getBuffer1()->NAME(idx, mRef.mCheckPermissions); } \ |
| 152 | bool NAME(s32 idx, s32 sub_idx) { \ |
| 153 | return getBuffer1()->NAME(idx, sub_idx, mRef.mCheckPermissions); \ |
| 154 | } \ |
| 155 | bool NAME(const sead::SafeString& name) { \ |
| 156 | return getBuffer1()->NAME(name, mRef.mCheckPermissions); \ |
| 157 | } \ |
| 158 | bool NAME(const sead::SafeString& name, s32 sub_idx) { \ |
| 159 | return getBuffer1()->NAME(name, sub_idx, mRef.mCheckPermissions); \ |
| 160 | } |
| 161 | |
| 162 | PROXY_RESET_IMPL_(resetBool) |
| 163 | PROXY_RESET_IMPL_(resetS32) |
| 164 | PROXY_RESET_IMPL_(resetF32) |
| 165 | PROXY_RESET_IMPL_(resetStr) |
| 166 | PROXY_RESET_IMPL_(resetStr64) |
| 167 | PROXY_RESET_IMPL_(resetStr256) |
| 168 | PROXY_RESET_IMPL_(resetVec2f) |
| 169 | PROXY_RESET_IMPL_(resetVec3f) |
| 170 | PROXY_RESET_IMPL_(resetVec4f) |
| 171 | |
| 172 | #undef PROXY_RESET_IMPL_ |
| 173 | |
| 174 | private: |
| 175 | friend class TriggerParamRef; |
| 176 | Proxy(const TriggerParamRef& ref, bool param1) : mUseParam1(param1), mRef(ref) {} |
| 177 | |
| 178 | bool mUseParam1; |
| 179 | const TriggerParamRef& mRef; |
| 180 | }; |
| 181 | |
| 182 | Proxy get() const { return Proxy(*this, false); } |
| 183 | Proxy get1() const { return Proxy(*this, true); } |
| 184 | |
| 185 | void setBuffers(TriggerParam** param1, TriggerParam** param) { |
| 186 | mParam1 = param1; |
| 187 | mParam = param; |
| 188 | } |
| 189 | |
| 190 | bool shouldCheckPermissions() const { return mCheckPermissions; } |
| 191 | bool shouldPropagateParam1Changes() const { return mPropagateParam1Changes; } |
| 192 | bool shouldChangeOnlyOnce() const { return mChangeOnlyOnce; } |
| 193 | |
| 194 | void setCheckPermissions(bool on) { mCheckPermissions = on; } |
| 195 | void setPropagateParam1Changes(bool on) { mPropagateParam1Changes = on; } |
| 196 | void setChangeOnlyOnce(bool on) { mChangeOnlyOnce = on; } |
| 197 | |
| 198 | private: |
| 199 | TriggerParam** mParam1; |
| 200 | TriggerParam** mParam; |
| 201 | bool mCheckPermissions; |
| 202 | bool mPropagateParam1Changes; |
| 203 | bool mChangeOnlyOnce; |
| 204 | }; |
| 205 | KSYS_CHECK_SIZE_NX150(TriggerParamRef, 0x20); |
| 206 | |
| 207 | class IManager { |
| 208 | public: |
| 209 | virtual ~IManager() = 0; |
| 210 | }; |
| 211 | |
| 212 | inline IManager::~IManager() = default; |
| 213 | |
| 214 | class Manager : public IManager, public KingEditorComponent { |
| 215 | SEAD_SINGLETON_DISPOSER(Manager) |
| 216 | Manager(); |
| 217 | ~Manager() override; |
| 218 | const char* getName() const override { return "GameData" ; } |
| 219 | void syncData(char* data) override; |
| 220 | |
| 221 | public: |
| 222 | struct ResetEvent { |
| 223 | virtual ~ResetEvent() = default; |
| 224 | TriggerParam* param = nullptr; |
| 225 | }; |
| 226 | |
| 227 | struct ReinitEvent { |
| 228 | virtual ~ReinitEvent() = default; |
| 229 | }; |
| 230 | |
| 231 | using ResetSignal = sead::DelegateEvent<ResetEvent*>; |
| 232 | using ReinitSignal = sead::DelegateEvent<ReinitEvent*>; |
| 233 | |
| 234 | void init(sead::Heap* heap, sead::Framework* framework); |
| 235 | void calc(); |
| 236 | |
| 237 | void addReinitCallback(ReinitSignal::Slot& slot); |
| 238 | void removeReinitCallback(ReinitSignal::Slot& slot); |
| 239 | |
| 240 | void setCurrentRupeeFlagName(const sead::SafeString& name); |
| 241 | void requestResetAllFlagsToInitial(); |
| 242 | |
| 243 | /// Checks whether quest flags (e.g. Kass shrine quest flags) are set or cleared properly |
| 244 | /// and takes any action necessary to fix them. |
| 245 | void fixQuestFlags(); |
| 246 | void fixQuestFlagsDlc2(); |
| 247 | |
| 248 | sead::Heap* getGameDataHeap() const { return mGameDataHeap; } |
| 249 | sead::Heap* getSaveAreaHeap() const { return mSaveAreaHeap; } |
| 250 | sead::Heap* getGameDataComHeap() const { return mGameDataComHeap; } |
| 251 | |
| 252 | TriggerParamRef& getParam() { return mParam; } |
| 253 | TriggerParamRef& getParamBypassPerm() { return mParamBypassPerm; } |
| 254 | |
| 255 | #define GDT_GET_HANDLE_(NAME, GET_IDX_NAME) \ |
| 256 | FlagHandle NAME(const sead::SafeString& name) const { \ |
| 257 | const auto prefix = mCurrentFlagHandlePrefix; \ |
| 258 | const auto hash = sead::HashCRC32::calcStringHash(name); \ |
| 259 | return makeFlagHandle(prefix, mParam.get1().getBuffer()->GET_IDX_NAME(hash)); \ |
| 260 | } |
| 261 | |
| 262 | GDT_GET_HANDLE_(getBoolHandle, TriggerParam::getBoolIdx) |
| 263 | GDT_GET_HANDLE_(getS32Handle, TriggerParam::getS32Idx) |
| 264 | GDT_GET_HANDLE_(getF32Handle, TriggerParam::getF32Idx) |
| 265 | GDT_GET_HANDLE_(getStrHandle, TriggerParam::getStrIdx) |
| 266 | GDT_GET_HANDLE_(getStr64Handle, TriggerParam::getStr64Idx) |
| 267 | GDT_GET_HANDLE_(getStr256Handle, TriggerParam::getStr256Idx) |
| 268 | GDT_GET_HANDLE_(getVec2fHandle, TriggerParam::getVec2fIdx) |
| 269 | GDT_GET_HANDLE_(getVec3fHandle, TriggerParam::getVec3fIdx) |
| 270 | GDT_GET_HANDLE_(getVec4fHandle, TriggerParam::getVec4fIdx) |
| 271 | |
| 272 | GDT_GET_HANDLE_(getBoolArrayHandle, TriggerParam::getBoolArrayIdx) |
| 273 | GDT_GET_HANDLE_(getS32ArrayHandle, TriggerParam::getS32ArrayIdx) |
| 274 | GDT_GET_HANDLE_(getF32ArrayHandle, TriggerParam::getF32ArrayIdx) |
| 275 | GDT_GET_HANDLE_(getStrArrayHandle, TriggerParam::getStrArrayIdx) |
| 276 | GDT_GET_HANDLE_(getStr64ArrayHandle, TriggerParam::getStr64ArrayIdx) |
| 277 | GDT_GET_HANDLE_(getStr256ArrayHandle, TriggerParam::getStr256ArrayIdx) |
| 278 | GDT_GET_HANDLE_(getVec2fArrayHandle, TriggerParam::getVec2fArrayIdx) |
| 279 | GDT_GET_HANDLE_(getVec3fArrayHandle, TriggerParam::getVec3fArrayIdx) |
| 280 | GDT_GET_HANDLE_(getVec4fArrayHandle, TriggerParam::getVec4fArrayIdx) |
| 281 | |
| 282 | #undef GDT_GET_HANDLE_ |
| 283 | |
| 284 | #define GDT_GET_(NAME, T) \ |
| 285 | bool NAME(FlagHandle handle, T* value, bool debug = false, \ |
| 286 | bool ignore_trigger_param_result = false) { \ |
| 287 | return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \ |
| 288 | const bool result = ref.get().NAME(value, idx); \ |
| 289 | return ignore_trigger_param_result || result; \ |
| 290 | }); \ |
| 291 | } \ |
| 292 | bool NAME(FlagHandle handle, T* value, s32 sub_idx, bool debug = false, \ |
| 293 | bool ignore_trigger_param_result = false) { \ |
| 294 | return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \ |
| 295 | const bool result = ref.get().NAME(value, idx, sub_idx); \ |
| 296 | return ignore_trigger_param_result || result; \ |
| 297 | }); \ |
| 298 | } |
| 299 | |
| 300 | GDT_GET_(getBool, bool) |
| 301 | GDT_GET_(getS32, s32) |
| 302 | GDT_GET_(getF32, f32) |
| 303 | GDT_GET_(getStr, char const*) |
| 304 | GDT_GET_(getStr64, char const*) |
| 305 | GDT_GET_(getStr256, char const*) |
| 306 | GDT_GET_(getVec2f, sead::Vector2f) |
| 307 | GDT_GET_(getVec3f, sead::Vector3f) |
| 308 | GDT_GET_(getVec4f, sead::Vector4f) |
| 309 | |
| 310 | #undef GDT_GET_ |
| 311 | |
| 312 | #define GDT_SET_(NAME, TRAITS) \ |
| 313 | /* Setters (by handle) */ \ |
| 314 | KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, FlagHandle handle, bool debug, \ |
| 315 | bool force) { \ |
| 316 | if (mBitFlags.isOn(BitFlag::_40000)) \ |
| 317 | return false; \ |
| 318 | return unwrapHandle<true>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \ |
| 319 | return ref.get().NAME(value, idx, force); \ |
| 320 | }); \ |
| 321 | } \ |
| 322 | bool NAME(TRAITS::ArgType value, FlagHandle handle) { \ |
| 323 | return NAME(value, handle, false, false); \ |
| 324 | } \ |
| 325 | bool NAME##NoCheck(TRAITS::ArgType value, FlagHandle handle) { \ |
| 326 | return NAME(value, handle, true, false); \ |
| 327 | } \ |
| 328 | bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, FlagHandle handle) { \ |
| 329 | return NAME(value, handle, true, true); \ |
| 330 | } \ |
| 331 | /* Setters for arrays (by handle) */ \ |
| 332 | KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, FlagHandle handle, bool debug, bool force, \ |
| 333 | s32 sub_idx) { \ |
| 334 | if (mBitFlags.isOn(BitFlag::_40000)) \ |
| 335 | return false; \ |
| 336 | return unwrapHandle<true>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \ |
| 337 | return ref.get().NAME(value, idx, sub_idx, force); \ |
| 338 | }); \ |
| 339 | } \ |
| 340 | bool NAME(TRAITS::ArgType value, FlagHandle handle, s32 sub_idx) { \ |
| 341 | return NAME(value, handle, false, false, sub_idx); \ |
| 342 | } \ |
| 343 | bool NAME##NoCheck(TRAITS::ArgType value, FlagHandle handle, s32 sub_idx) { \ |
| 344 | return NAME(value, handle, true, false, sub_idx); \ |
| 345 | } \ |
| 346 | bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, FlagHandle handle, s32 sub_idx) { \ |
| 347 | return NAME(value, handle, true, true, sub_idx); \ |
| 348 | } \ |
| 349 | /* Setters (by name) */ \ |
| 350 | KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, const sead::SafeString& name, bool debug, \ |
| 351 | bool force) { \ |
| 352 | if (mBitFlags.isOn(BitFlag::_40000)) \ |
| 353 | return false; \ |
| 354 | auto& ref = debug ? getParamBypassPerm() : getParam(); \ |
| 355 | return ref.get().NAME(value, name, force); \ |
| 356 | } \ |
| 357 | bool NAME(TRAITS::ArgType value, const sead::SafeString& name); \ |
| 358 | bool NAME##_(TRAITS::ArgType value, const sead::SafeString& name); \ |
| 359 | bool NAME##NoCheck(TRAITS::ArgType value, const sead::SafeString& name); \ |
| 360 | bool NAME##NoCheck_(TRAITS::ArgType value, const sead::SafeString& name); \ |
| 361 | bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, const sead::SafeString& name); \ |
| 362 | /* Setters for arrays (by name) */ \ |
| 363 | KSYS_ALWAYS_INLINE bool NAME(TRAITS::ArgType value, const sead::SafeString& name, bool debug, \ |
| 364 | bool force, s32 sub_idx) { \ |
| 365 | if (mBitFlags.isOn(BitFlag::_40000)) \ |
| 366 | return false; \ |
| 367 | auto& ref = debug ? getParamBypassPerm() : getParam(); \ |
| 368 | return ref.get().NAME(value, name, sub_idx, force); \ |
| 369 | } \ |
| 370 | bool NAME(TRAITS::ArgType value, const sead::SafeString& name, s32 sub_idx); \ |
| 371 | bool NAME##_(TRAITS::ArgType value, const sead::SafeString& name, s32 sub_idx); \ |
| 372 | bool NAME##NoCheck(TRAITS::ArgType value, const sead::SafeString& name, s32 sub_idx); \ |
| 373 | bool NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, const sead::SafeString& name, \ |
| 374 | s32 sub_idx); \ |
| 375 | \ |
| 376 | bool NAME(TRAITS::WrapperArgType value, FlagHandle handle, bool debug) { \ |
| 377 | if (debug) { \ |
| 378 | onChangedByDebug(); \ |
| 379 | return NAME##NoCheckForce(TRAITS::convertValue(value), handle); \ |
| 380 | } \ |
| 381 | return NAME(TRAITS::convertValue(value), handle); \ |
| 382 | } \ |
| 383 | bool NAME(TRAITS::WrapperArgType value, const sead::SafeString& name, bool debug) { \ |
| 384 | if (debug) { \ |
| 385 | onChangedByDebug(); \ |
| 386 | return NAME##NoCheckForce(TRAITS::convertValue(value), name); \ |
| 387 | } \ |
| 388 | return NAME(TRAITS::convertValue(value), name); \ |
| 389 | } \ |
| 390 | inline bool NAME##Special(TRAITS::WrapperArgType value, const sead::SafeString& name, \ |
| 391 | bool debug, bool force = false) { \ |
| 392 | if (debug) { \ |
| 393 | onChangedByDebug(); \ |
| 394 | auto& ref = debug ? getParamBypassPerm() : getParam(); \ |
| 395 | return ref.get().NAME(TRAITS::convertValue(value), name, force); \ |
| 396 | } \ |
| 397 | return NAME(TRAITS::convertValue(value), name); \ |
| 398 | } \ |
| 399 | \ |
| 400 | bool NAME(TRAITS::WrapperArgType value, FlagHandle handle, bool debug, s32 sub_idx) { \ |
| 401 | if (debug) { \ |
| 402 | onChangedByDebug(); \ |
| 403 | return NAME##NoCheckForce(TRAITS::convertValue(value), handle, sub_idx); \ |
| 404 | } \ |
| 405 | return NAME(TRAITS::convertValue(value), handle, sub_idx); \ |
| 406 | } \ |
| 407 | bool NAME(TRAITS::WrapperArgType value, const sead::SafeString& name, bool debug, \ |
| 408 | s32 sub_idx) { \ |
| 409 | if (debug) { \ |
| 410 | onChangedByDebug(); \ |
| 411 | return NAME##NoCheckForce(TRAITS::convertValue(value), name, sub_idx); \ |
| 412 | } \ |
| 413 | return NAME(TRAITS::convertValue(value), name, sub_idx); \ |
| 414 | } |
| 415 | |
| 416 | GDT_SET_(setBool, detail::SetterTraits<bool>) |
| 417 | GDT_SET_(setS32, detail::SetterTraits<s32>) |
| 418 | GDT_SET_(setF32, detail::SetterTraits<f32>) |
| 419 | GDT_SET_(setStr, detail::SetterTraits<const char*>) |
| 420 | GDT_SET_(setStr64, detail::SetterTraits<const char*>) |
| 421 | GDT_SET_(setStr256, detail::SetterTraits<const char*>) |
| 422 | GDT_SET_(setVec2f, detail::SetterTraits<sead::Vector2f>) |
| 423 | GDT_SET_(setVec3f, detail::SetterTraits<sead::Vector3f>) |
| 424 | GDT_SET_(setVec4f, detail::SetterTraits<sead::Vector4f>) |
| 425 | |
| 426 | #undef GDT_SET_ |
| 427 | |
| 428 | #define GDT_RESET_(NAME) \ |
| 429 | bool NAME(const sead::SafeString& name); \ |
| 430 | bool NAME##_(const sead::SafeString& name); \ |
| 431 | bool NAME(const sead::SafeString& name, int sub_idx); \ |
| 432 | KSYS_ALWAYS_INLINE bool NAME##_(FlagHandle handle, bool debug) { \ |
| 433 | if (mBitFlags.isOn(BitFlag::_40000)) \ |
| 434 | return false; \ |
| 435 | return unwrapHandle<false>( \ |
| 436 | handle, debug, [&](u32 idx, TriggerParamRef& ref) { return ref.get().NAME(idx); }); \ |
| 437 | } \ |
| 438 | inline bool NAME(FlagHandle handle) { return NAME##_(handle, false); } \ |
| 439 | inline bool NAME##NoCheck(FlagHandle handle) { return NAME##_(handle, true); } \ |
| 440 | \ |
| 441 | KSYS_ALWAYS_INLINE bool NAME##_(FlagHandle handle, bool debug, s32 sub_idx) { \ |
| 442 | if (mBitFlags.isOn(BitFlag::_40000)) \ |
| 443 | return false; \ |
| 444 | return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \ |
| 445 | return ref.get().NAME(idx, sub_idx); \ |
| 446 | }); \ |
| 447 | } \ |
| 448 | inline bool NAME(FlagHandle handle, s32 sub_idx) { return NAME##_(handle, false, sub_idx); } \ |
| 449 | inline bool NAME##NoCheck(FlagHandle handle, s32 sub_idx) { \ |
| 450 | return NAME##_(handle, true, sub_idx); \ |
| 451 | } \ |
| 452 | \ |
| 453 | inline bool NAME(FlagHandle handle, bool debug) { \ |
| 454 | if (debug) { \ |
| 455 | onChangedByDebug(); \ |
| 456 | return NAME##NoCheck(handle); \ |
| 457 | } \ |
| 458 | return NAME(handle); \ |
| 459 | } \ |
| 460 | inline bool NAME(FlagHandle handle, bool debug, s32 sub_idx) { \ |
| 461 | if (debug) { \ |
| 462 | onChangedByDebug(); \ |
| 463 | return NAME##NoCheck(handle, sub_idx); \ |
| 464 | } \ |
| 465 | return NAME(handle, sub_idx); \ |
| 466 | } |
| 467 | |
| 468 | GDT_RESET_(resetBool) |
| 469 | GDT_RESET_(resetS32) |
| 470 | GDT_RESET_(resetF32) |
| 471 | GDT_RESET_(resetStr) |
| 472 | GDT_RESET_(resetStr64) |
| 473 | GDT_RESET_(resetStr256) |
| 474 | GDT_RESET_(resetVec2f) |
| 475 | GDT_RESET_(resetVec3f) |
| 476 | GDT_RESET_(resetVec4f) |
| 477 | |
| 478 | #undef GDT_RESET_ |
| 479 | |
| 480 | void incrementS32NoCheck(s32 value, const sead::SafeString& name); |
| 481 | void incrementS32(s32 value, const sead::SafeString& name); |
| 482 | |
| 483 | void increaseS32CommonFlag(s32 value, const sead::SafeString& name, s32 sub_idx, bool debug) { |
| 484 | if (!mIncreaseLogger) |
| 485 | return; |
| 486 | |
| 487 | mIncreaseLogger->addRecord(value, name, sub_idx, debug); |
| 488 | if (debug) |
| 489 | onChangedByDebug(); |
| 490 | } |
| 491 | |
| 492 | bool wasFlagCopied(const sead::SafeString& name); |
| 493 | bool wasFlagNotCopied(const sead::SafeString& name); |
| 494 | |
| 495 | void copyParamToParam1(); |
| 496 | void allocParam1(); |
| 497 | |
| 498 | FlagHandle getRevivalFlagHandle(const sead::SafeString& object_name, |
| 499 | const map::MubinIter& iter); |
| 500 | static bool getShopInfoIter(u32 hash, al::ByamlIter* out, const al::ByamlIter& iter, |
| 501 | const u32* hashes); |
| 502 | bool getShopSoldOutInfo(u32 hash, al::ByamlIter* out) const { |
| 503 | return getShopInfoIter(hash, out, getShopSoldOutInfoValues(), getShopSoldOutInfoHashes()); |
| 504 | } |
| 505 | void resetBoolFlagForRadarMgr(FlagBool& flag); |
| 506 | |
| 507 | void allocRetryBuffer(sead::Heap* heap); |
| 508 | void destroyRetryBuffer(); |
| 509 | |
| 510 | void startSyncOnLoadEnd(); |
| 511 | |
| 512 | const al::ByamlIter& getShopAreaInfoValues() const { return mShopAreaInfoValues; } |
| 513 | const u32* getShopAreaInfoHashes() const { return mShopAreaInfoHashes; } |
| 514 | const al::ByamlIter& getShopSoldOutInfoValues() const { return mShopSoldOutInfoValues; } |
| 515 | const u32* getShopSoldOutInfoHashes() const { return mShopSoldOutInfoHashes; } |
| 516 | |
| 517 | void onAnimalMasterAppearance() { |
| 518 | mBitFlags.set(BitFlag::_8); |
| 519 | mResetFlags.set(ResetFlag::AnimalMaster); |
| 520 | } |
| 521 | |
| 522 | private: |
| 523 | enum class BitFlag { |
| 524 | _1 = 0x1, |
| 525 | _2 = 0x2, |
| 526 | RequestResetAllFlagsToInitial = 0x4, |
| 527 | _8 = 0x8, |
| 528 | _10 = 0x10, |
| 529 | _20 = 0x20, |
| 530 | _40 = 0x40, |
| 531 | _80 = 0x80, |
| 532 | _100 = 0x100, |
| 533 | _200 = 0x200, |
| 534 | SyncFlags = _100 | _200, |
| 535 | _400 = 0x400, |
| 536 | _800 = 0x800, |
| 537 | _1000 = 0x1000, |
| 538 | _2000 = 0x2000, |
| 539 | _4000 = 0x4000, |
| 540 | _8000 = 0x8000, |
| 541 | _10000 = 0x10000, |
| 542 | _20000 = 0x20000, |
| 543 | _40000 = 0x40000, |
| 544 | _80000 = 0x80000, |
| 545 | }; |
| 546 | |
| 547 | enum class ResetFlag { |
| 548 | AnimalMaster = 0x10, |
| 549 | }; |
| 550 | |
| 551 | struct MethodTreeNode { |
| 552 | virtual ~MethodTreeNode() = default; |
| 553 | sead::MethodTreeNode node{nullptr}; |
| 554 | sead::MethodTreeMgr* method_tree_mgr = nullptr; |
| 555 | }; |
| 556 | |
| 557 | struct IncreaseLogger { |
| 558 | struct Record { |
| 559 | bool debug = false; |
| 560 | u32 name_hash = 0; |
| 561 | s32 sub_idx = -1; |
| 562 | s32 value = 0; |
| 563 | }; |
| 564 | KSYS_CHECK_SIZE_NX150(Record, 0x10); |
| 565 | |
| 566 | void addRecord(s32 value, const sead::SafeString& name, s32 sub_idx, bool debug); |
| 567 | |
| 568 | u64 _0 = 0; |
| 569 | sead::SafeArray<sead::FixedRingBuffer<Record, 64>, NumCores> ring_buffers[2]; |
| 570 | sead::SafeArray<Record, 0xc0> arrays[2]{}; |
| 571 | }; |
| 572 | |
| 573 | static FlagHandle makeFlagHandle(u32 prefix, s32 idx) { |
| 574 | return FlagHandle(idx | (prefix << 24)); |
| 575 | } |
| 576 | |
| 577 | /// Extracts a flag index out of a FlagHandle and passes it to the specified callable. |
| 578 | /// fn must be callable with a u32 + TriggerParamRef& |
| 579 | template <bool Write, bool BypassPerm, typename Fn> |
| 580 | KSYS_ALWAYS_INLINE bool unwrapHandle(FlagHandle handle, const Fn& fn) { |
| 581 | const u32 idx = static_cast<u32>(handle); |
| 582 | auto& ref = BypassPerm ? getParamBypassPerm() : getParam(); |
| 583 | const auto check = [&] { return !Write || !ref.shouldChangeOnlyOnce(); }; |
| 584 | |
| 585 | if (mBitFlags.isOff(BitFlag::_8000) && handle != InvalidHandle) |
| 586 | return check() && fn(idx, ref); |
| 587 | |
| 588 | return idx >> 24 == mCurrentFlagHandlePrefix && check() && fn(idx & 0xFFFFFF, ref); |
| 589 | } |
| 590 | |
| 591 | /// Extracts a flag index out of a FlagHandle and passes it to the specified callable. |
| 592 | /// fn must be callable with a u32 + TriggerParamRef& |
| 593 | template <bool Write, typename Fn> |
| 594 | KSYS_ALWAYS_INLINE bool unwrapHandle(FlagHandle handle, bool debug, const Fn& fn) { |
| 595 | return debug ? unwrapHandle<Write, true>(handle, fn) : |
| 596 | unwrapHandle<Write, false>(handle, fn); |
| 597 | } |
| 598 | |
| 599 | void onChangedByDebug() { |
| 600 | setBool(true, "IsChangedByDebug" ); |
| 601 | mBitFlags.set(BitFlag::_800); |
| 602 | } |
| 603 | |
| 604 | void loadGameData(const sead::SafeString& path); |
| 605 | void loadShopGameDataInfo(const sead::SafeString& path); |
| 606 | void unloadResources(); |
| 607 | |
| 608 | void syncStart(); |
| 609 | void syncUpdate(const char* data); |
| 610 | static void parseFloats(const sead::SafeString& str, f32* values, u32 n); |
| 611 | static inline void recordFlagChange(u32 platform_core_id, TriggerParam* tparam, u8 type, |
| 612 | const s32& idx, const s32& sub_idx = -1); |
| 613 | |
| 614 | template <typename T> |
| 615 | void doSyncArray(const sead::PtrArray<FlagBase>& array, u8* buffer, const char* description); |
| 616 | template <int N> |
| 617 | void doSyncArrayStr(const sead::PtrArray<FlagBase>& array, u8* buffer, const char* description, |
| 618 | u32 n = N); |
| 619 | template <typename T> |
| 620 | void doSyncArrayVec(const sead::PtrArray<FlagBase>& array, u8* buffer, const char* description, |
| 621 | u32 n); |
| 622 | |
| 623 | template <typename T> |
| 624 | void doSyncArray(const sead::PtrArray<sead::PtrArray<FlagBase>>& array, u8* buffer, |
| 625 | const char* description); |
| 626 | template <int N> |
| 627 | void doSyncArrayStr(const sead::PtrArray<sead::PtrArray<FlagBase>>& array, u8* buffer, |
| 628 | const char* description, u32 n = N); |
| 629 | template <typename T> |
| 630 | void doSyncArrayVec(const sead::PtrArray<sead::PtrArray<FlagBase>>& array, u8* buffer, |
| 631 | const char* description, u32 n); |
| 632 | |
| 633 | sead::Heap* mGameDataHeap = nullptr; |
| 634 | sead::Heap* mSaveAreaHeap = nullptr; |
| 635 | sead::Heap* mGameDataComHeap = nullptr; |
| 636 | res::Handle mGameDataArcHandle; |
| 637 | sead::SafeArray<res::Handle, 32> mBgdataHandles; |
| 638 | sead::ArchiveFileDevice mGameDataArc{nullptr}; |
| 639 | |
| 640 | res::Handle mShopGameDataInfoHandle; |
| 641 | al::ByamlIter mShopAreaInfoValues; |
| 642 | const u32* mShopAreaInfoHashes = nullptr; |
| 643 | al::ByamlIter mShopSoldOutInfoValues; |
| 644 | const u32* mShopSoldOutInfoHashes = nullptr; |
| 645 | |
| 646 | TriggerParamRef mParamBypassPerm{&mFlagBuffer1, &mFlagBuffer, false, false, false}; |
| 647 | TriggerParamRef mParam{&mFlagBuffer1, &mFlagBuffer, true, false, false}; |
| 648 | |
| 649 | IncreaseLogger* mIncreaseLogger = nullptr; |
| 650 | |
| 651 | TriggerParam* mFlagBuffer1; |
| 652 | TriggerParam* mFlagBuffer; |
| 653 | TriggerParam* mRetryBuffer; |
| 654 | TriggerParam* mGimmickResetBuffer; |
| 655 | |
| 656 | sead::TypedBitFlag<BitFlag> mBitFlags; |
| 657 | sead::TypedBitFlag<ResetFlag> mResetFlags; |
| 658 | u32 _c20 = 0; |
| 659 | u32 mNumFlagsToReset = 0; |
| 660 | u32 mCurrentFlagHandlePrefix = 0; |
| 661 | |
| 662 | ReinitSignal mReinitSignal; |
| 663 | ResetSignal mResetSignal; |
| 664 | |
| 665 | MethodTreeNode mMethodTreeNode; |
| 666 | |
| 667 | void* mDelegate1 = nullptr; // FIXME: figure out what this is |
| 668 | sead::IDelegateR<const sead::SafeString&>* mGetMapNameDelegate = nullptr; |
| 669 | |
| 670 | sead::FixedSafeString<64> mStr; // TODO: rename |
| 671 | u32 mTrackerBlockSaveNumberFlagCrc32 = 0; |
| 672 | u32 mSyncStep = 0; |
| 673 | sead::Mutex mMutex; |
| 674 | }; |
| 675 | KSYS_CHECK_SIZE_NX150(Manager, 0xdc8); |
| 676 | |
| 677 | } // namespace ksys::gdt |
| 678 | |