#include "KingSystem/GameData/gdtTriggerParam.h" #include #include #include #include "KingSystem/GameData/gdtFlagProxy.h" #include "KingSystem/Resource/resResourceGameData.h" #include "KingSystem/System/PlayReportMgr.h" #include "KingSystem/Utils/Debug.h" #include "KingSystem/Utils/InitTimeInfo.h" #include "KingSystem/Utils/SafeDelete.h" namespace ksys::gdt { TriggerParam::TriggerParam() { for (auto& buffer : mFlagChangeRecords) buffer.constructDefault(); for (auto& cs : mCriticalSections) cs.constructDefault(); mBitFlags.constructDefault(); mFlagChangeRecordIndices.fill(0); mNumBoolFlagsPerCategory0.fill(0); mNumBoolFlagsPerCategory.fill(0); } namespace { struct TriggerParamConfig { bool shouldLog(const sead::SafeString& flag_name, u8 event_type) const { if (enabled_events.isOffBit(event_type)) return false; return flag_to_log.isEmpty() || flag_name.include(flag_to_log); } bool shouldPrintStackTrace(const sead::SafeString& flag_name) const { return !flag_to_log.isEmpty() && flag_name.include(flag_to_log) && enabled_events.isOnBit(5); } sead::SafeString& getCurrentRupeeFlagName() { return current_rupee_flag_name; } sead::BitFlag8 enabled_events; s32 foo = 90; s32 index = 32; sead::FixedSafeString<128> flag_to_log{""}; s32 num_current_rupee_flag_name_changes = 0; sead::SafeString current_rupee_flag_name; }; KSYS_CHECK_SIZE_NX150(TriggerParamConfig, 0xc0); util::InitTimeInfoEx sInitTimeInfo; TriggerParamConfig sConfig; // TODO (low-priority): implement this without using to match the original code // The original code appears to perform a heapsort. [[gnu::noinline]] void sortFlagPtrArray(sead::PtrArray& array) { std::sort(array.dataBegin(), array.dataEnd(), [](const FlagBase* a, const FlagBase* b) { return a->getHash() < b->getHash(); }); } inline s32 getFlagIndex(const sead::PtrArray& flags, u32 name_hash) { s32 a = 0; s32 b = flags.size() - 1; while (a < b) { const s32 m = (a + b) / 2; if (flags[m]->getHash() == name_hash) return m; if (flags[m]->getHash() < name_hash) a = m + 1; else b = m; } if (flags[a]->getHash() == name_hash) return a; return -1; } inline s32 getFlagIndex(const sead::PtrArray>& flags, u32 name_hash) { for (s32 i = 0; i < flags.size(); ++i) { const auto& array = *flags[i]; if (array.size() > 0 && array[0]->getHash() == name_hash) return i; } return -1; } inline FlagBase* getFlagByIndexBase(const sead::PtrArray& flags, s32 index) { if (index < 0 || index >= flags.size()) return nullptr; return flags[index]; } template inline Flag* getFlagByIndex(const sead::PtrArray& flags, s32 index) { return static_cast*>(getFlagByIndexBase(flags, index)); } template inline Flag* getFlag(const sead::PtrArray& flags, u32 name_hash) { return getFlagByIndex(flags, getFlagIndex(flags, name_hash)); } template inline Flag* getFlag(const sead::PtrArray& flags, const sead::SafeString& name) { if (name.isEmpty()) return nullptr; return getFlag(flags, sead::HashCRC32::calcStringHash(name)); } template inline bool getFlagValue(const sead::PtrArray& array, T* out_value, s32 index, bool check_permissions) { static_assert(isValidFlagValueType()); const auto* flag = getFlagByIndex(array, index); if (!flag) return false; if (check_permissions && !flag->isProgramReadable()) return false; if constexpr (std::is_same()) *out_value = flag->getValueRef().cstr(); else *out_value = flag->getValue(); return true; } template inline bool getFlagValue(const sead::PtrArray>& arrays, T* out_value, s32 array_index, s32 flag_index, bool check_permissions) { static_assert(isValidFlagValueType()); if (array_index < 0 || array_index >= arrays.size()) return false; const auto* array = arrays[array_index]; if (!array) return false; const auto* flag = getFlagByIndex(*array, flag_index); if (!flag) return false; if (check_permissions && !flag->isProgramReadable()) return false; if constexpr (std::is_same()) *out_value = flag->getValueRef().cstr(); else *out_value = flag->getValue(); return true; } /// Modifies the value of a flag. /// @param success A non-null pointer to a boolean that is set to true if an attempt was made to /// change the value. /// @return whether the flag contains the specified value at the end of this function. template bool doSetFlagValue(bool* success, const T& value, const sead::PtrArray& flags, s32 idx, bool check_permissions, bool bypass_one_trigger_check) { *success = false; auto* flag = getFlagByIndex(flags, idx); if (!flag) return false; if (check_permissions && !flags[idx]->isProgramWritable()) return false; if constexpr (IsAnyOfType()) { if (!flags[idx]->isOneTrigger() || bypass_one_trigger_check || flag->isInitialValue()) *success = flag->setValue(value); else if (!flag->hasValue(value)) return false; return true; } else { bool can_set_value = false; if (!flags[idx]->isOneTrigger() || bypass_one_trigger_check || flag->isInitialValue()) { can_set_value = true; *success = flag->setValue(value); } else if (flag->hasValue(value)) { return true; } return can_set_value; } } void sendFlagChangePlayReport(const sead::SafeString& name, const FlagBase* flag) { if (!PlayReportMgr::instance()) return; for (s32 i = 0; i < sConfig.num_current_rupee_flag_name_changes; ++i) { if (name == sConfig.current_rupee_flag_name) { sead::FixedSafeString<64> value_str; switch (s32(flag->getType())) { case FlagType::Bool: case FlagType::BoolArray: if (static_cast(flag)->getValue()) value_str.format("true"); else value_str.format("false"); break; case FlagType::S32: case FlagType::S32Array: value_str.format("%d", static_cast(flag)->getValue()); break; case FlagType::F32: case FlagType::F32Array: value_str.format("%f", static_cast(flag)->getValue()); break; case FlagType::String: case FlagType::StringArray: value_str.format("%s", static_cast(flag)->getValueRef().cstr()); break; case FlagType::String64: case FlagType::String64Array: value_str.format("%s", static_cast(flag)->getValueRef().cstr()); break; case FlagType::String256: case FlagType::String256Array: value_str.format("%s", static_cast(flag)->getValueRef().cstr()); break; case FlagType::Vector2f: case FlagType::Vector2fArray: { const auto& vector = static_cast(flag)->getValueRef(); value_str.format("%f %f", vector.x, vector.y); break; } case FlagType::Vector3f: case FlagType::Vector3fArray: { const auto& vector = static_cast(flag)->getValueRef(); value_str.format("%f %f %f", vector.x, vector.y, vector.z); break; } case FlagType::Vector4f: case FlagType::Vector4fArray: { const auto& vector = static_cast(flag)->getValueRef(); value_str.format("%f %f %f %f", vector.x, vector.y, vector.z, vector.w); break; } default: break; } PlayReportMgr::instance()->reportDebug(name, value_str); break; } } } template void reportFlagChange(const FlagBase* flag, s32 sub_idx = -1) { auto* flag_ = static_cast*>(flag); const sead::SafeString& name = flag->getName(); const FlagType type = flag->getType(); if constexpr (std::is_same()) { if ((s32(type) == FlagType::Bool || s32(type) == FlagType::BoolArray) && PlayReportMgr::instance()) { if (flag_->getValue()) PlayReportMgr::instance()->reportDebug("FlagOn", name); else PlayReportMgr::instance()->reportDebug("FlagOff", name); } } else { sendFlagChangePlayReport(name, flag); } if (sConfig.shouldPrintStackTrace(name)) { sead::StackTrace<50> stack_trace; stack_trace.trace(nullptr); } if (!shouldLogFlagChange(name, type)) return; if constexpr (std::is_same()) { sead::FixedSafeString<128> message; const char* name_cstr = flag->getName().cstr(); const auto type_ = flag->getType(); if (sub_idx < 0 || type_ != FlagType::BoolArray) message.format("%s", name_cstr); else message.format("%s [%3d]", name_cstr, sub_idx); switch (s32(flag->getType())) { case FlagType::Bool: case FlagType::BoolArray: if (flag_->getValue()) message.append(" : true"); else message.append(" : false"); break; default: break; } util::PrintDebug(message); } else { const char* name_cstr = flag->getName().cstr(); sead::FixedSafeString<128> message; const s32 type_ = flag->getType(); if (sub_idx >= 0 && type_ >= FlagType::BoolArray) message.format("%s [%3d] :", name_cstr, sub_idx); else message.format("%s :", name_cstr); sead::FixedSafeString<64> value_str; switch (s32(flag->getType())) { case FlagType::Bool: case FlagType::BoolArray: if (static_cast(flag)->getValue()) value_str.format("true"); else value_str.format("false"); break; case FlagType::S32: case FlagType::S32Array: value_str.format("%d", static_cast(flag)->getValue()); break; case FlagType::F32: case FlagType::F32Array: value_str.format("%f", static_cast(flag)->getValue()); break; case FlagType::String: case FlagType::StringArray: value_str.format("%s", static_cast(flag)->getValueRef().cstr()); break; case FlagType::String64: case FlagType::String64Array: value_str.format("%s", static_cast(flag)->getValueRef().cstr()); break; case FlagType::String256: case FlagType::String256Array: value_str.format("%s", static_cast(flag)->getValueRef().cstr()); break; case FlagType::Vector2f: case FlagType::Vector2fArray: { const auto& vector = static_cast(flag)->getValueRef(); value_str.format("%f %f", vector.x, vector.y); break; } case FlagType::Vector3f: case FlagType::Vector3fArray: { const auto& vector = static_cast(flag)->getValueRef(); value_str.format("%f %f %f", vector.x, vector.y, vector.z); break; } case FlagType::Vector4f: case FlagType::Vector4fArray: { const auto& vector = static_cast(flag)->getValueRef(); value_str.format("%f %f %f %f", vector.x, vector.y, vector.z, vector.w); break; } default: break; } message.append(value_str); util::PrintDebug(message); } static_cast(getFlagColor(type)); sConfig.index = sConfig.index >= 32 ? 0 : sConfig.index + 1; } bool getFlagArraySize(const sead::PtrArray>& arrays, s32 index, s32* out) { if (index < 0 || index >= arrays.size()) return false; *out = arrays[index]->size(); return true; } template inline void copyGameDataResBuffer(sead::Buffer& source, sead::PtrArray& dest, sead::Heap* heap) { if (source.size() == 0) return; if (!dest.isBufferReady()) dest.allocBuffer(source.size(), heap); for (auto& flag : source) dest.pushBack(&flag); } template inline void copyGameDataResBuffer(sead::PtrArray>& source, sead::PtrArray>& dest, sead::Heap* heap) { const auto n = source.capacity(); if (n < 1) return; if (!dest.isBufferReady()) dest.allocBuffer(n, heap); for (s32 i = 0; i < n; ++i) { dest.pushBack(new (heap) sead::PtrArray); const auto num_flags = source[i]->size(); if (!dest[i]->isBufferReady()) dest[i]->allocBuffer(num_flags, heap); for (s32 j = 0; j < num_flags; ++j) dest[i]->pushBack(std::addressof((*source[i])[j])); } } template void makeFlagProxies(sead::PtrArray& dest, const sead::PtrArray& src, s32 count, sead::Heap* heap, bool permanent_flags_only) { for (s32 i = 0; i < count; ++i) { auto* flag = static_cast*>(src[i]); if (!permanent_flags_only) { auto* proxy = new (heap) FlagProxy; proxy->setFlag(flag); proxy->setValue(flag->getValue()); proxy->setCategory(flag->getCategory()); dest.pushBack(proxy); } else if (flag->isPermanent()) { auto* proxy = new (heap) FlagProxy; proxy->setFlag(flag); proxy->setValue(flag->getValue()); proxy->setCategory(flag->getCategory()); dest.pushBack(proxy); } } } template void addFlagCopyRecord(sead::ObjArray& records, Flag* flag, s32 sub_index, bool find_existing_record) { if (records.isFull()) return; TriggerParam::FlagCopyRecord* record; s32 record_idx = -1; if (find_existing_record) { const u32 hash = flag->getHash(); for (s32 i = 0; i < records.size(); ++i) { if (records[i]->name_hash == hash && records[i]->sub_index == s16(sub_index)) { record_idx = i; break; } } } if (record_idx != -1) { record = records[record_idx]; } else { record = records.emplaceBack(); record->name_hash = flag->getHash(); record->sub_index = sub_index; } record->bf.makeAllZero(); } constexpr bool IsString256ArrayType(FlagType::ValueType type) { return type == FlagType::String256Array; } } // namespace /** * @param dest Destination flag array * @param src Source flag array * @param records Copy records (only used if add_records is true) * @param counts Boolean flag counts per category (only used if T = bool) * @param record_copies Whether copies should be recorded * @param ignore_temp_flags Whether temporary flags (i.e. flags that aren't saved) * should be ignored * @param find_existing_record See addFlagCopyRecord. * @param is_array Whether the flag arrays are associated with an array-type flag (e.g. bool array) */ template void copyFlags(sead::PtrArray& dest, const sead::PtrArray& src, sead::ObjArray& records, sead::SafeArray& counts, bool record_copies, bool ignore_temp_flags, bool find_existing_record, bool is_array) { // This function only handles two cases: // // 1. If both the source and destination have the same number of flags, we assume that // both arrays store the same flags in the exact same order. // // 2. If the source has fewer flags than the destination, it is assumed that src is a subset of // dest (i.e. every flag that is in src is also in dest) and src forms a subsequence of dest. // Any flag in dest that isn't in src will be reset to its initial value. const auto update_records = [&](Flag* flag, const Flag* flag_src, s32 i) { flag->setValue(flag_src->getValue()); s32 category, category_idx; if constexpr (std::is_same()) { category = flag->getCategory(); category_idx = category - 1; } if (record_copies) { addFlagCopyRecord(records, flag, is_array ? i : -1, find_existing_record); if constexpr (std::is_same()) { if (category > 0) { if (flag->getValue()) ++counts[category_idx]; else if (counts[category_idx] > 0) --counts[category_idx]; } } } else { if constexpr (std::is_same()) { if (category > 0 && flag->getValue()) ++counts[category_idx]; } } }; const auto dest_size = dest.size(); const auto src_size = src.size(); if (dest_size == src_size) { for (s32 i = 0; i < dest_size; ++i) { if (!dest[i]) continue; if (ignore_temp_flags && !dest[i]->isSave()) continue; if (record_copies && dest[i]->isSave()) continue; if (!src[i]) { if (!dest[i]->isSave()) dest[i]->resetToInitialValue(); } else { auto* flag = static_cast*>(dest[i]); auto* flag_src = static_cast*>(src[i]); update_records(flag, flag_src, i); } } } else if (src_size < dest_size) { s32 j = 0; for (s32 i = 0; i < dest_size; ++i) { if (ignore_temp_flags && !dest[i]->isSave()) continue; if (record_copies && dest[i]->isSave()) continue; if (j >= src_size || src[j]->getHash() != dest[i]->getHash()) { if (!dest[i]->isSave()) dest[i]->resetToInitialValue(); } else if (src[j]->getHash() == dest[i]->getHash()) { auto* flag = static_cast*>(dest[i]); auto* flag_src = static_cast*>(src[j]); update_records(flag, flag_src, i); ++j; } } } } template void copyFlagArrays(sead::PtrArray>& dest, const sead::PtrArray>& src, sead::ObjArray& records, sead::SafeArray& counts, bool record_copies, bool ignore_temp_flags, bool find_existing_record) { const auto dest_size = dest.size(); const auto src_size = src.size(); if (src_size == dest_size) { for (s32 i = 0; i < dest_size; ++i) { if (!src[i]) { const auto n = dest[i]->size(); if (!dest[i]->at(0)->isSave()) { for (s32 j = 0; j < n; ++j) dest[i]->at(j)->resetToInitialValue(); } } else { copyFlags(*dest[i], *src[i], records, counts, record_copies, ignore_temp_flags, find_existing_record, true); } } } else { s32 j = 0; for (s32 i = 0; i < dest_size; ++i) { if (j >= src_size) { const auto n = dest[i]->size(); if (!dest[i]->at(0)->isSave()) { for (s32 k = 0; k < n; ++k) dest[i]->at(k)->resetToInitialValue(); } } else if (src[j]->at(0)->getHash() != dest[i]->at(0)->getHash()) { const auto n = dest[i]->size(); if (!dest[i]->at(0)->isSave()) { for (s32 k = 0; k < n; ++k) dest[i]->at(k)->resetToInitialValue(); } } else { copyFlags(*dest[i], *src[j], records, counts, record_copies, ignore_temp_flags, find_existing_record, true); ++j; } } } } void TriggerParam::copyFromGameDataRes(res::GameData* gdata, sead::Heap* heap) { if (!gdata) return; copyGameDataResBuffer(gdata->getBoolFlags(), mBoolFlags, heap); copyGameDataResBuffer(gdata->getS32Flags(), mS32Flags, heap); copyGameDataResBuffer(gdata->getF32Flags(), mF32Flags, heap); copyGameDataResBuffer(gdata->getStringFlags(), mStringFlags, heap); copyGameDataResBuffer(gdata->getString64Flags(), mString64Flags, heap); copyGameDataResBuffer(gdata->getString256Flags(), mString256Flags, heap); copyGameDataResBuffer(gdata->getVector2fFlags(), mVector2fFlags, heap); copyGameDataResBuffer(gdata->getVector3fFlags(), mVector3fFlags, heap); copyGameDataResBuffer(gdata->getVector4fFlags(), mVector4fFlags, heap); copyGameDataResBuffer(gdata->getBoolArrayFlags(), mBoolArrayFlags, heap); copyGameDataResBuffer(gdata->getS32ArrayFlags(), mS32ArrayFlags, heap); copyGameDataResBuffer(gdata->getF32ArrayFlags(), mF32ArrayFlags, heap); copyGameDataResBuffer(gdata->getStringArrayFlags(), mStringArrayFlags, heap); copyGameDataResBuffer(gdata->getString64ArrayFlags(), mString64ArrayFlags, heap); copyGameDataResBuffer(gdata->getString256ArrayFlags(), mString256ArrayFlags, heap); copyGameDataResBuffer(gdata->getVector2fArrayFlags(), mVector2fArrayFlags, heap); copyGameDataResBuffer(gdata->getVector3fArrayFlags(), mVector3fArrayFlags, heap); copyGameDataResBuffer(gdata->getVector4fArrayFlags(), mVector4fArrayFlags, heap); mResourceFlags = gdata->getField14(); } void TriggerParam::init(sead::Heap* heap) { sortFlagPtrArray(mBoolFlags); sortFlagPtrArray(mS32Flags); sortFlagPtrArray(mF32Flags); sortFlagPtrArray(mStringFlags); sortFlagPtrArray(mString64Flags); sortFlagPtrArray(mString256Flags); sortFlagPtrArray(mVector2fFlags); sortFlagPtrArray(mVector3fFlags); sortFlagPtrArray(mVector4fFlags); allocCopyRecordArrays(heap); updateBoolFlagCounts(); mHeap = heap; } void TriggerParam::allocCopyRecordArrays(sead::Heap* heap) { #define ALLOC_ARRAY_(FLAGS, FLAG_ARRAYS, DEST) \ { \ s32 size = FLAGS.size(); \ for (s32 i = 0; i < FLAG_ARRAYS.size(); ++i) \ size += FLAG_ARRAYS[i]->size(); \ \ DEST.allocBuffer(size, heap); \ } ALLOC_ARRAY_(mBoolFlags, mBoolArrayFlags, mCopiedBoolFlags); ALLOC_ARRAY_(mS32Flags, mS32ArrayFlags, mCopiedS32Flags); ALLOC_ARRAY_(mF32Flags, mF32ArrayFlags, mCopiedF32Flags); ALLOC_ARRAY_(mStringFlags, mStringArrayFlags, mCopiedStringFlags); ALLOC_ARRAY_(mString64Flags, mString64ArrayFlags, mCopiedString64Flags); ALLOC_ARRAY_(mString256Flags, mString256ArrayFlags, mCopiedString256Flags); ALLOC_ARRAY_(mVector2fFlags, mVector2fArrayFlags, mCopiedVector2fFlags); ALLOC_ARRAY_(mVector3fFlags, mVector3fArrayFlags, mCopiedVector3fFlags); ALLOC_ARRAY_(mVector4fFlags, mVector4fArrayFlags, mCopiedVector4fFlags); #undef ALLOC_ARRAY_ } void TriggerParam::updateBoolFlagCounts() { for (s32 i = 0; i < mBoolFlags.size(); ++i) { const s32 category = mBoolFlags[i]->getCategory(); if (category > 0) ++mNumBoolFlagsPerCategory[category - 1]; } for (s32 array_i = 0; array_i < mBoolArrayFlags.size(); ++array_i) { for (s32 i = 0; i < mBoolArrayFlags[array_i]->size(); ++i) { const s32 category = (*mBoolArrayFlags[array_i])[i]->getCategory(); if (category > 0) ++mNumBoolFlagsPerCategory[category - 1]; } } } void TriggerParam::destroyHeap() { util::safeDeleteHeap(mHeap); } void TriggerParam::allocBools(s32 size, sead::Heap* heap) { mBoolFlags.allocBuffer(size, heap); } void TriggerParam::allocS32s(s32 size, sead::Heap* heap) { mS32Flags.allocBuffer(size, heap); } void TriggerParam::initResetData(sead::Heap* heap) { s32 num_reset_entries = 0; #define COUNT_FLAGS_(FLAGS) \ do { \ for (s32 i = 0; i < FLAGS.size(); ++i) { \ if (FLAGS[i]->isResettable()) \ ++num_reset_entries; \ } \ } while (0) #define COUNT_FLAGS_ARRAY_(ARRAYS) \ do { \ for (s32 i = 0; i < ARRAYS.size(); ++i) { \ if ((*ARRAYS[i])[0]->isResettable()) \ ++num_reset_entries; \ } \ } while (0) COUNT_FLAGS_(mBoolFlags); COUNT_FLAGS_(mS32Flags); COUNT_FLAGS_(mF32Flags); COUNT_FLAGS_(mStringFlags); COUNT_FLAGS_(mString64Flags); COUNT_FLAGS_(mString256Flags); COUNT_FLAGS_(mVector2fFlags); COUNT_FLAGS_(mVector3fFlags); COUNT_FLAGS_(mVector4fFlags); COUNT_FLAGS_ARRAY_(mBoolArrayFlags); COUNT_FLAGS_ARRAY_(mS32ArrayFlags); COUNT_FLAGS_ARRAY_(mF32ArrayFlags); COUNT_FLAGS_ARRAY_(mStringArrayFlags); COUNT_FLAGS_ARRAY_(mString64ArrayFlags); COUNT_FLAGS_ARRAY_(mString256ArrayFlags); COUNT_FLAGS_ARRAY_(mVector2fArrayFlags); COUNT_FLAGS_ARRAY_(mVector3fArrayFlags); COUNT_FLAGS_ARRAY_(mVector4fArrayFlags); #undef COUNT_FLAGS_ #undef COUNT_FLAGS_ARRAY_ if (num_reset_entries == 0) return; mResetEntries.allocBufferAssert(num_reset_entries, heap); s32 reset_entry_idx = 0; #define ADD_ENTRIES_(TYPE, FLAGS) \ do { \ for (s32 i = 0; i < FLAGS.size(); ++i) { \ if (!FLAGS[i]->isResettable()) \ continue; \ mResetEntries[reset_entry_idx].type = TYPE; \ mResetEntries[reset_entry_idx].index = i; \ mResetEntries[reset_entry_idx].reset_type = FLAGS[i]->getProperties().getResetType(); \ ++reset_entry_idx; \ if (reset_entry_idx == num_reset_entries) \ return; \ } \ } while (0) #define ADD_ENTRIES_ARRAY_(TYPE, ARRAYS) \ do { \ for (s32 i = 0; i < ARRAYS.size(); ++i) { \ if (!(*ARRAYS[i])[0]->isResettable()) \ continue; \ \ mResetEntries[reset_entry_idx].type = TYPE; \ \ /* ??? */ \ if constexpr (IsString256ArrayType(TYPE)) \ mResetEntries[reset_entry_idx].index = s16(i); \ else \ mResetEntries[reset_entry_idx].index = i; \ \ mResetEntries[reset_entry_idx].reset_type = (*ARRAYS[i])[0]->getResetType(); \ \ ++reset_entry_idx; \ if (reset_entry_idx == num_reset_entries) \ return; \ } \ } while (0) ADD_ENTRIES_(FlagType::Bool, mBoolFlags); ADD_ENTRIES_(FlagType::S32, mS32Flags); ADD_ENTRIES_(FlagType::F32, mF32Flags); ADD_ENTRIES_(FlagType::String, mStringFlags); ADD_ENTRIES_(FlagType::String64, mString64Flags); ADD_ENTRIES_(FlagType::String256, mString256Flags); ADD_ENTRIES_(FlagType::Vector2f, mVector2fFlags); ADD_ENTRIES_(FlagType::Vector3f, mVector3fFlags); ADD_ENTRIES_(FlagType::Vector4f, mVector4fFlags); ADD_ENTRIES_ARRAY_(FlagType::BoolArray, mBoolArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::S32Array, mS32ArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::F32Array, mF32ArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::StringArray, mStringArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::String64Array, mString64ArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::String256Array, mString256ArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::Vector2fArray, mVector2fArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::Vector3fArray, mVector3fArrayFlags); ADD_ENTRIES_ARRAY_(FlagType::Vector4fArray, mVector4fArrayFlags); #undef ADD_ENTRIES_ #undef ADD_ENTRIES_ARRAY_ } void TriggerParam::initRevivalRandomBools(sead::Heap* heap) { s32 count = 0; for (s32 i = 0; i < mBoolFlags.size(); ++i) { if (static_cast(mBoolFlags[i])->getRandomResetData()) ++count; } if (count == 0) return; mRevivalRandomBools.allocBuffer(count, heap); for (s32 i = 0; i < mBoolFlags.size(); ++i) { if (static_cast(mBoolFlags[i])->getRandomResetData()) mRevivalRandomBools.pushBack(static_cast(mBoolFlags[i])); } } void TriggerParam::copyAllFlags(const TriggerParam& src, sead::Heap* heap, bool init_reset_data) { mResourceFlags = src.mResourceFlags; s32 num_flags = 0; #define COPY_(MEMBER, T) \ do { \ const auto size = src.MEMBER.size(); \ if (size > 0) { \ MEMBER.allocBuffer(size, heap); \ makeFlagProxies(MEMBER, src.MEMBER, size, heap, false); \ num_flags += size; \ } \ } while (0) COPY_(mBoolFlags, bool); COPY_(mS32Flags, s32); COPY_(mF32Flags, f32); COPY_(mStringFlags, sead::FixedSafeString<32>); COPY_(mString64Flags, sead::FixedSafeString<64>); COPY_(mString256Flags, sead::FixedSafeString<256>); COPY_(mVector2fFlags, sead::Vector2f); COPY_(mVector3fFlags, sead::Vector3f); COPY_(mVector4fFlags, sead::Vector4f); #undef COPY_ #define COPY_ARRAY_(MEMBER, T) \ do { \ const auto size = src.MEMBER.size(); \ if (size > 0) { \ MEMBER.allocBuffer(size, heap); \ for (s32 i = 0; i < size; ++i) { \ const auto array_size = src.MEMBER[i]->size(); \ if (array_size > 0) { \ MEMBER.pushBack(new (heap) sead::PtrArray); \ MEMBER[i]->allocBuffer(std::max(1, array_size), heap); \ makeFlagProxies(*MEMBER[i], *src.MEMBER[i], array_size, heap, false); \ num_flags += size; \ } \ } \ } \ } while (0) COPY_ARRAY_(mBoolArrayFlags, bool); COPY_ARRAY_(mS32ArrayFlags, s32); COPY_ARRAY_(mF32ArrayFlags, f32); COPY_ARRAY_(mStringArrayFlags, sead::FixedSafeString<32>); COPY_ARRAY_(mString64ArrayFlags, sead::FixedSafeString<64>); COPY_ARRAY_(mString256ArrayFlags, sead::FixedSafeString<256>); COPY_ARRAY_(mVector2fArrayFlags, sead::Vector2f); COPY_ARRAY_(mVector3fArrayFlags, sead::Vector3f); COPY_ARRAY_(mVector4fArrayFlags, sead::Vector4f); #undef COPY_ #undef COPY_ARRAY_ if (init_reset_data) { for (auto& array : mFlagChangeRecords) array.ref().allocBufferAssert(num_flags, heap); initResetData(heap); initRevivalRandomBools(heap); } mHeap = heap; } void TriggerParam::copyPermanentFlags(const TriggerParam& src, sead::Heap* heap) { #define COPY_(MEMBER, T) \ do { \ const auto size = src.MEMBER.size(); \ if (size > 0) { \ s32 num_permanent_flags = 0; \ for (s32 i = 0; i < size; ++i) { \ if (src.MEMBER[i]->isPermanent()) \ ++num_permanent_flags; \ } \ MEMBER.allocBuffer(std::max(1, num_permanent_flags), heap); \ makeFlagProxies(MEMBER, src.MEMBER, size, heap, true); \ } \ } while (0) COPY_(mBoolFlags, bool); COPY_(mS32Flags, s32); COPY_(mF32Flags, f32); COPY_(mStringFlags, sead::FixedSafeString<32>); COPY_(mString64Flags, sead::FixedSafeString<64>); COPY_(mString256Flags, sead::FixedSafeString<256>); COPY_(mVector2fFlags, sead::Vector2f); COPY_(mVector3fFlags, sead::Vector3f); COPY_(mVector4fFlags, sead::Vector4f); #undef COPY_ #define COPY_ARRAY_(MEMBER, T) \ do { \ const auto size = src.MEMBER.size(); \ if (size > 0) { \ MEMBER.allocBuffer(size, heap); \ for (s32 i = 0; i < size; ++i) { \ const auto array_size = src.MEMBER[i]->size(); \ if (array_size > 0) { \ auto* array = new (heap) sead::PtrArray; \ MEMBER.pushBack(array); \ MEMBER[i]->allocBuffer(std::max(1, array_size), heap); \ makeFlagProxies(*MEMBER[i], *src.MEMBER[i], array_size, heap, true); \ } \ } \ } \ } while (0) COPY_ARRAY_(mBoolArrayFlags, bool); COPY_ARRAY_(mS32ArrayFlags, s32); COPY_ARRAY_(mF32ArrayFlags, f32); COPY_ARRAY_(mStringArrayFlags, sead::FixedSafeString<32>); COPY_ARRAY_(mString64ArrayFlags, sead::FixedSafeString<64>); COPY_ARRAY_(mString256ArrayFlags, sead::FixedSafeString<256>); COPY_ARRAY_(mVector2fArrayFlags, sead::Vector2f); COPY_ARRAY_(mVector3fArrayFlags, sead::Vector3f); COPY_ARRAY_(mVector4fArrayFlags, sead::Vector4f); #undef COPY_ #undef COPY_ARRAY_ mHeap = heap; } FlagType TriggerParam::getFlagType(const sead::SafeString& name) const { if (getBoolIdx(name) != -1) return FlagType::Bool; if (getBoolArrayIdx(name) != -1) return FlagType::BoolArray; if (getS32Idx(name) != -1) return FlagType::S32; if (getS32ArrayIdx(name) != -1) return FlagType::S32Array; if (getStrIdx(name) != -1) return FlagType::String; if (getStrArrayIdx(name) != -1) return FlagType::StringArray; if (getF32Idx(name) != -1) return FlagType::F32; if (getF32ArrayIdx(name) != -1) return FlagType::F32Array; if (getVec3fIdx(name) != -1) return FlagType::Vector3f; if (getVec3fArrayIdx(name) != -1) return FlagType::Vector3fArray; if (getStr64Idx(name) != -1) return FlagType::String64; if (getStr256ArrayIdx(name) != -1) return FlagType::String256Array; if (getStr256Idx(name) != -1) return FlagType::String256; if (getStr64ArrayIdx(name) != -1) return FlagType::String64Array; if (getVec2fIdx(name) != -1) return FlagType::Vector2f; if (getVec2fArrayIdx(name) != -1) return FlagType::Vector2fArray; if (getVec4fIdx(name) != -1) return FlagType::Vector4f; if (getVec4fArrayIdx(name) != -1) return FlagType::Vector4fArray; return FlagType::Invalid; } bool TriggerParam::getBool(bool* value, s32 index, bool check_permissions) const { return getFlagValue(mBoolFlags, value, index, check_permissions); } bool TriggerParam::getS32(s32* value, s32 index, bool check_permissions) const { return getFlagValue(mS32Flags, value, index, check_permissions); } bool TriggerParam::getF32(f32* value, s32 index, bool check_permissions) const { return getFlagValue(mF32Flags, value, index, check_permissions); } bool TriggerParam::getStr(const char** value, s32 index, bool check_permissions) const { return getFlagValue>(mStringFlags, value, index, check_permissions); } bool TriggerParam::getStr64(const char** value, s32 index, bool check_permissions) const { return getFlagValue>(mString64Flags, value, index, check_permissions); } bool TriggerParam::getStr256(const char** value, s32 index, bool check_permissions) const { return getFlagValue>(mString256Flags, value, index, check_permissions); } bool TriggerParam::getVec2f(sead::Vector2f* value, s32 index, bool check_permissions) const { return getFlagValue(mVector2fFlags, value, index, check_permissions); } bool TriggerParam::getVec3f(sead::Vector3f* value, s32 index, bool check_permissions) const { return getFlagValue(mVector3fFlags, value, index, check_permissions); } bool TriggerParam::getVec4f(sead::Vector4f* value, s32 index, bool check_permissions) const { return getFlagValue(mVector4fFlags, value, index, check_permissions); } bool TriggerParam::getBool(bool* value, const sead::SafeString& name, bool check_permissions, bool x) const { return getBool(value, getBoolIdx(name), check_permissions); } bool TriggerParam::getBool2(bool* value, const sead::SafeString& name, bool check_permissions, bool x) const { return getBool(value, getBoolIdx(name), check_permissions); } bool TriggerParam::getS32(s32* value, const sead::SafeString& name, bool check_permissions, bool x) const { return getS32(value, getS32Idx(name), check_permissions); } bool TriggerParam::getF32(f32* value, const sead::SafeString& name, bool check_permissions, bool x) const { return getF32(value, getF32Idx(name), check_permissions); } bool TriggerParam::getStr(const char** value, const sead::SafeString& name, bool check_permissions, bool x) const { return getStr(value, getStrIdx(name), check_permissions); } bool TriggerParam::getStr64(const char** value, const sead::SafeString& name, bool check_permissions, bool x) const { return getStr64(value, getStr64Idx(name), check_permissions); } bool TriggerParam::getStr256(const char** value, const sead::SafeString& name, bool check_permissions, bool x) const { return getStr256(value, getStr256Idx(name), check_permissions); } bool TriggerParam::getVec2f(sead::Vector2f* value, const sead::SafeString& name, bool check_permissions, bool x) const { return getVec2f(value, getVec2fIdx(name), check_permissions); } bool TriggerParam::getVec3f(sead::Vector3f* value, const sead::SafeString& name, bool check_permissions, bool x) const { return getVec3f(value, getVec3fIdx(name), check_permissions); } bool TriggerParam::getVec4f(sead::Vector4f* value, const sead::SafeString& name, bool check_permissions, bool x) const { return getVec4f(value, getVec4fIdx(name), check_permissions); } bool TriggerParam::getBool(bool* value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue(mBoolArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getS32(s32* value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue(mS32ArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getF32(f32* value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue(mF32ArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getStr(const char** value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue>( mStringArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getStr64(const char** value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue>( mString64ArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getStr256(const char** value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue>( mString256ArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getVec2f(sead::Vector2f* value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue(mVector2fArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getVec3f(sead::Vector3f* value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue(mVector3fArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getVec4f(sead::Vector4f* value, s32 array_index, s32 index, bool check_permissions) const { return getFlagValue(mVector4fArrayFlags, value, array_index, index, check_permissions); } bool TriggerParam::getBool(bool* value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getBool(value, getBoolArrayIdx(name), index, check_permissions); } bool TriggerParam::getS32(s32* value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getS32(value, getS32ArrayIdx(name), index, check_permissions); } bool TriggerParam::getF32(f32* value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getF32(value, getF32ArrayIdx(name), index, check_permissions); } bool TriggerParam::getStr(const char** value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getStr(value, getStrArrayIdx(name), index, check_permissions); } bool TriggerParam::getStr64(const char** value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getStr64(value, getStr64ArrayIdx(name), index, check_permissions); } bool TriggerParam::getStr256(const char** value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getStr256(value, getStr256ArrayIdx(name), index, check_permissions); } bool TriggerParam::getVec2f(sead::Vector2f* value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getVec2f(value, getVec2fArrayIdx(name), index, check_permissions); } bool TriggerParam::getVec3f(sead::Vector3f* value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getVec3f(value, getVec3fArrayIdx(name), index, check_permissions); } bool TriggerParam::getVec4f(sead::Vector4f* value, const sead::SafeString& name, s32 index, bool check_permissions, bool x) const { return getVec4f(value, getVec4fArrayIdx(name), index, check_permissions); } bool TriggerParam::getBoolArraySize(s32* size, s32 index) const { return getFlagArraySize(mBoolArrayFlags, index, size); } bool TriggerParam::getS32ArraySize(s32* size, s32 index) const { return getFlagArraySize(mS32ArrayFlags, index, size); } bool TriggerParam::getF32ArraySize(s32* size, s32 index) const { return getFlagArraySize(mF32ArrayFlags, index, size); } bool TriggerParam::getStrArraySize(s32* size, s32 index) const { return getFlagArraySize(mStringArrayFlags, index, size); } bool TriggerParam::getStr64ArraySize(s32* size, s32 index) const { return getFlagArraySize(mString64ArrayFlags, index, size); } bool TriggerParam::getStr256ArraySize(s32* size, s32 index) const { return getFlagArraySize(mString256ArrayFlags, index, size); } bool TriggerParam::getVec2fArraySize(s32* size, s32 index) const { return getFlagArraySize(mVector2fArrayFlags, index, size); } bool TriggerParam::getVec3fArraySize(s32* size, s32 index) const { return getFlagArraySize(mVector3fArrayFlags, index, size); } bool TriggerParam::getVec4fArraySize(s32* size, s32 index) const { return getFlagArraySize(mVector4fArrayFlags, index, size); } bool TriggerParam::getBoolArraySizeByHash(s32* size, u32 name) const { return getBoolArraySize(size, getBoolArrayIdx(name)); } bool TriggerParam::getS32ArraySizeByHash(s32* size, u32 name) const { return getS32ArraySize(size, getS32ArrayIdx(name)); } bool TriggerParam::getF32ArraySizeByHash(s32* size, u32 name) const { return getF32ArraySize(size, getF32ArrayIdx(name)); } bool TriggerParam::getStrArraySizeByHash(s32* size, u32 name) const { return getStrArraySize(size, getStrArrayIdx(name)); } bool TriggerParam::getStr64ArraySizeByHash(s32* size, u32 name) const { return getStr64ArraySize(size, getStr64ArrayIdx(name)); } bool TriggerParam::getStr256ArraySizeByHash(s32* size, u32 name) const { return getStr256ArraySize(size, getStr256ArrayIdx(name)); } bool TriggerParam::getVec2fArraySizeByHash(s32* size, u32 name) const { return getVec2fArraySize(size, getVec2fArrayIdx(name)); } bool TriggerParam::getVec3fArraySizeByHash(s32* size, u32 name) const { return getVec3fArraySize(size, getVec3fArrayIdx(name)); } bool TriggerParam::getVec4fArraySizeByHash(s32* size, u32 name) const { return getVec4fArraySize(size, getVec4fArrayIdx(name)); } bool TriggerParam::getS32ArraySize(s32* size, const sead::SafeString& name) const { return getS32ArraySize(size, getS32ArrayIdx(name)); } bool TriggerParam::getStr64ArraySize(s32* size, const sead::SafeString& name) const { return getStr64ArraySize(size, getStr64ArrayIdx(name)); } bool TriggerParam::getVec3fArraySize(s32* size, const sead::SafeString& name) const { return getVec3fArraySize(size, getVec3fArrayIdx(name)); } bool TriggerParam::getMinValueForS32(s32* min, const sead::SafeString& name) const { const auto* flag = getFlag(mS32Flags, name); if (!flag) return false; *min = flag->getConfig().min_value; return true; } bool TriggerParam::getMaxValueForS32(s32* max, const sead::SafeString& name) const { const auto* flag = getFlag(mS32Flags, name); if (!flag) return false; *max = flag->getConfig().max_value; return true; } #define SET_FLAG_VALUE_IMPL_(FUNCTION_NAME, ARG_VALUE_TYPE, FLAGS, T, VALUE) \ bool FUNCTION_NAME(ARG_VALUE_TYPE value, s32 idx, bool check_permissions, \ bool bypass_one_trigger_check) { \ bool success = false; \ const bool ret = doSetFlagValue(&success, VALUE, FLAGS, idx, check_permissions, \ bypass_one_trigger_check); \ if (!success) \ return ret; \ \ recordFlagChange(FLAGS[idx], idx); \ reportFlagChange(FLAGS[idx]); \ \ if constexpr (std::is_same()) { \ if (FLAGS[idx]->getProperties().isEventAssociated()) \ mBitFlags.ref().set(BitFlag::EventAssociatedFlagModified); \ } \ \ return ret; \ } #define SET_FLAG_VALUE_BY_KEY_IMPL_(FUNCTION_NAME, GET_INDEX_FN, ARG_VALUE_TYPE) \ bool FUNCTION_NAME(ARG_VALUE_TYPE value, const sead::SafeString& name, bool check_permissions, \ bool, bool bypass_one_trigger_check) { \ return FUNCTION_NAME(value, GET_INDEX_FN(name), check_permissions, \ bypass_one_trigger_check); \ } #define SET_ARRAY_FLAG_VALUE_IMPL_(FUNCTION_NAME, ARG_VALUE_TYPE, FLAGS, T, VALUE) \ bool FUNCTION_NAME(ARG_VALUE_TYPE value, s32 idx, s32 sub_idx, bool check_permissions, \ bool bypass_one_trigger_check) { \ bool success = false; \ \ if (idx < 0 || idx >= FLAGS.size()) \ return false; \ \ const auto* array = FLAGS[idx]; \ if (!array) \ return false; \ \ const bool ret = doSetFlagValue(&success, VALUE, *array, sub_idx, check_permissions, \ bypass_one_trigger_check); \ if (!success) \ return ret; \ \ const auto* flag = (*FLAGS[idx])[sub_idx]; \ recordFlagChange(flag, idx, sub_idx); \ reportFlagChange(flag, sub_idx); \ \ return ret; \ } #define SET_STRING_ARRAY_FLAG_VALUE_IMPL_(FUNCTION_NAME, FLAGS, T) \ bool FUNCTION_NAME(const char* value, s32 idx, s32 sub_idx, bool check_permissions, \ bool bypass_one_trigger_check) { \ bool success = false; \ T value_{value}; \ success = false; \ \ if (idx < 0 || idx >= FLAGS.size()) \ return false; \ \ const auto* array = FLAGS[idx]; \ if (!array) \ return false; \ \ const bool ret = doSetFlagValue(&success, value_, *array, sub_idx, check_permissions, \ bypass_one_trigger_check); \ if (!success) \ return ret; \ \ const auto* flag = (*FLAGS[idx])[sub_idx]; \ recordFlagChange(flag, idx, sub_idx); \ reportFlagChange(flag, sub_idx); \ \ return ret; \ } #define SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(FUNCTION_NAME, GET_INDEX_FN, ARG_VALUE_TYPE) \ bool FUNCTION_NAME(ARG_VALUE_TYPE value, const sead::SafeString& name, s32 sub_idx, \ bool check_permissions, bool, bool bypass_one_trigger_check) { \ return FUNCTION_NAME(value, GET_INDEX_FN(name), sub_idx, check_permissions, \ bypass_one_trigger_check); \ } SET_FLAG_VALUE_IMPL_(TriggerParam::setBool, bool, mBoolFlags, bool, value) void TriggerParam::recordFlagChange(const FlagBase* flag, s32 idx, s32 sub_idx) { const auto core = sead::CoreInfo::getCurrentCoreId(); const u32 platform_core_id = sead::CoreInfo::getPlatformCoreId(core); auto& buffer = mFlagChangeRecords[platform_core_id].ref(); if (buffer.size() < 1) return; auto lock = sead::makeScopedLock(mCriticalSections[platform_core_id].ref()); buffer[mFlagChangeRecordIndices[platform_core_id]].type.mValue = u8(flag->getType()); buffer[mFlagChangeRecordIndices[platform_core_id]].index = idx; buffer[mFlagChangeRecordIndices[platform_core_id]].sub_index = sub_idx; ++mFlagChangeRecordIndices[platform_core_id]; if (flag->getType() == FlagType::Bool) mBitFlags.ref().set(BitFlag::_8); } SET_FLAG_VALUE_IMPL_(TriggerParam::setS32, s32, mS32Flags, s32, value) SET_FLAG_VALUE_IMPL_(TriggerParam::setF32, f32, mF32Flags, f32, value) SET_FLAG_VALUE_IMPL_(TriggerParam::setStr, const char*, mStringFlags, sead::FixedSafeString<32>, sead::FixedSafeString<32>(value)) SET_FLAG_VALUE_IMPL_(TriggerParam::setStr64, const char*, mString64Flags, sead::FixedSafeString<64>, sead::FixedSafeString<64>(value)) SET_FLAG_VALUE_IMPL_(TriggerParam::setStr256, const char*, mString256Flags, sead::FixedSafeString<256>, sead::FixedSafeString<256>(value)) SET_FLAG_VALUE_IMPL_(TriggerParam::setVec2f, const sead::Vector2f&, mVector2fFlags, sead::Vector2f, value) SET_FLAG_VALUE_IMPL_(TriggerParam::setVec3f, const sead::Vector3f&, mVector3fFlags, sead::Vector3f, value) SET_FLAG_VALUE_IMPL_(TriggerParam::setVec4f, const sead::Vector4f&, mVector4fFlags, sead::Vector4f, value) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setBool, getBoolIdx, bool) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setS32, getS32Idx, s32) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setF32, getF32Idx, f32) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setStr, getStrIdx, const char*) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setStr64, getStr64Idx, const char*) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setStr256, getStr256Idx, const char*) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setVec2f, getVec2fIdx, const sead::Vector2f&) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setVec3f, getVec3fIdx, const sead::Vector3f&) SET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setVec4f, getVec4fIdx, const sead::Vector4f&) SET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setBool, bool, mBoolArrayFlags, bool, value) SET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setS32, s32, mS32ArrayFlags, s32, value) SET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setF32, f32, mF32ArrayFlags, f32, value) SET_STRING_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setStr, mStringArrayFlags, sead::FixedSafeString<32>) SET_STRING_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setStr64, mString64ArrayFlags, sead::FixedSafeString<64>) SET_STRING_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setStr256, mString256ArrayFlags, sead::FixedSafeString<256>) SET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setVec2f, const sead::Vector2f&, mVector2fArrayFlags, sead::Vector2f, value) SET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setVec3f, const sead::Vector3f&, mVector3fArrayFlags, sead::Vector3f, value) SET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::setVec4f, const sead::Vector4f&, mVector4fArrayFlags, sead::Vector4f, value) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setBool, getBoolArrayIdx, bool) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setS32, getS32ArrayIdx, s32) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setF32, getF32ArrayIdx, f32) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setStr, getStrArrayIdx, const char*) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setStr64, getStr64ArrayIdx, const char*) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setStr256, getStr256ArrayIdx, const char*) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setVec2f, getVec2fArrayIdx, const sead::Vector2f&) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setVec3f, getVec3fArrayIdx, const sead::Vector3f&) SET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::setVec4f, getVec4fArrayIdx, const sead::Vector4f&) #define RESET_FLAG_VALUE_IMPL_(FUNCTION_NAME, FLAGS, T) \ bool FUNCTION_NAME(s32 idx, bool check_permissions) { \ auto* flag = getFlagByIndexBase(FLAGS, idx); \ if (!flag) \ return false; \ \ if (check_permissions && !flag->isProgramWritable()) \ return false; \ \ if (flag->isInitialValue()) \ return true; \ \ flag->resetToInitialValue(); \ recordFlagChange(FLAGS[idx], idx); \ reportFlagChange(FLAGS[idx]); \ \ return true; \ } #define RESET_FLAG_VALUE_BY_KEY_IMPL_(FUNCTION_NAME, FLAGS, GET_IDX_FN) \ bool FUNCTION_NAME(const sead::SafeString& name, bool check_permissions, bool) { \ return FUNCTION_NAME(GET_IDX_FN(name), check_permissions); \ } #define RESET_ARRAY_FLAG_VALUE_IMPL_(FUNCTION_NAME, ARRAYS, T) \ bool FUNCTION_NAME(s32 idx, s32 sub_idx, bool check_permissions) { \ if (idx < 0 || idx >= ARRAYS.size()) \ return false; \ \ const auto* array = ARRAYS[idx]; \ if (!array) \ return false; \ \ auto* flag = getFlagByIndexBase(*array, sub_idx); \ if (!flag) \ return false; \ \ if (check_permissions && !flag->isProgramWritable()) \ return false; \ \ if (flag->isInitialValue()) \ return true; \ \ flag->resetToInitialValue(); \ const auto* flag_ = [&] { return ARRAYS.at(idx)->at(sub_idx); }(); \ recordFlagChange(flag_, idx, sub_idx); \ reportFlagChange(flag_, sub_idx); \ \ return true; \ } #define RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(FUNCTION_NAME, FLAGS, GET_IDX_FN) \ bool FUNCTION_NAME(const sead::SafeString& name, s32 sub_idx, bool check_permissions, bool) { \ return FUNCTION_NAME(GET_IDX_FN(name), sub_idx, check_permissions); \ } RESET_FLAG_VALUE_IMPL_(TriggerParam::resetBool, mBoolFlags, bool) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetS32, mS32Flags, s32) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetF32, mF32Flags, f32) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetStr, mStringFlags, sead::FixedSafeString<32>) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetStr64, mString64Flags, sead::FixedSafeString<64>) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetStr256, mString256Flags, sead::FixedSafeString<256>) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetVec2f, mVector2fFlags, sead::Vector2f) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetVec3f, mVector3fFlags, sead::Vector3f) RESET_FLAG_VALUE_IMPL_(TriggerParam::resetVec4f, mVector4fFlags, sead::Vector4f) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetBool, mBoolFlags, getBoolIdx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetS32, mS32Flags, getS32Idx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetF32, mF32Flags, getF32Idx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetStr, mStringFlags, getStrIdx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetStr64, mString64Flags, getStr64Idx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetStr256, mString256Flags, getStr256Idx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetVec2f, mVector2fFlags, getVec2fIdx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetVec3f, mVector3fFlags, getVec3fIdx) RESET_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetVec4f, mVector4fFlags, getVec4fIdx) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetBool, mBoolArrayFlags, bool) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetS32, mS32ArrayFlags, s32) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetF32, mF32ArrayFlags, f32) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetStr, mStringArrayFlags, sead::FixedSafeString<32>) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetStr64, mString64ArrayFlags, sead::FixedSafeString<64>) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetStr256, mString256ArrayFlags, sead::FixedSafeString<256>) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetVec2f, mVector2fArrayFlags, sead::Vector2f) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetVec3f, mVector3fArrayFlags, sead::Vector3f) RESET_ARRAY_FLAG_VALUE_IMPL_(TriggerParam::resetVec4f, mVector4fArrayFlags, sead::Vector4f) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetBool, mBoolArrayFlags, getBoolArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetS32, mS32ArrayFlags, getS32ArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetF32, mF32ArrayFlags, getF32ArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetStr, mStringArrayFlags, getStrArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetStr64, mString64ArrayFlags, getStr64ArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetStr256, mString256ArrayFlags, getStr256ArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetVec2f, mVector2fArrayFlags, getVec2fArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetVec3f, mVector3fArrayFlags, getVec3fArrayIdx) RESET_ARRAY_FLAG_VALUE_BY_KEY_IMPL_(TriggerParam::resetVec4f, mVector4fArrayFlags, getVec4fArrayIdx) void TriggerParam::resetAllFlagsToInitialValues() { for (s32 i = 0; i < mBoolFlags.size(); ++i) resetBool(i, false); for (s32 i = 0; i < mS32Flags.size(); ++i) resetS32(i, false); for (s32 i = 0; i < mF32Flags.size(); ++i) resetF32(i, false); for (s32 i = 0; i < mStringFlags.size(); ++i) resetStr(i, false); for (s32 i = 0; i < mString64Flags.size(); ++i) resetStr64(i, false); for (s32 i = 0; i < mString256Flags.size(); ++i) resetStr256(i, false); for (s32 i = 0; i < mVector2fFlags.size(); ++i) resetVec2f(i, false); for (s32 i = 0; i < mVector3fFlags.size(); ++i) resetVec3f(i, false); for (s32 i = 0; i < mVector4fFlags.size(); ++i) resetVec4f(i, false); for (s32 i = 0; i < mBoolArrayFlags.size(); ++i) { for (s32 j = 0; j < mBoolArrayFlags[i]->size(); ++j) resetBool(i, j, false); } for (s32 i = 0; i < mS32ArrayFlags.size(); ++i) { for (s32 j = 0; j < mS32ArrayFlags[i]->size(); ++j) resetS32(i, j, false); } for (s32 i = 0; i < mF32ArrayFlags.size(); ++i) { for (s32 j = 0; j < mF32ArrayFlags[i]->size(); ++j) resetF32(i, j, false); } for (s32 i = 0; i < mStringArrayFlags.size(); ++i) { for (s32 j = 0; j < mStringArrayFlags[i]->size(); ++j) resetStr(i, j, false); } for (s32 i = 0; i < mString64ArrayFlags.size(); ++i) { for (s32 j = 0; j < mString64ArrayFlags[i]->size(); ++j) resetStr64(i, j, false); } for (s32 i = 0; i < mString256ArrayFlags.size(); ++i) { for (s32 j = 0; j < mString256ArrayFlags[i]->size(); ++j) resetStr256(i, j, false); } for (s32 i = 0; i < mVector2fArrayFlags.size(); ++i) { for (s32 j = 0; j < mVector2fArrayFlags[i]->size(); ++j) resetVec2f(i, j, false); } for (s32 i = 0; i < mVector3fArrayFlags.size(); ++i) { for (s32 j = 0; j < mVector3fArrayFlags[i]->size(); ++j) resetVec3f(i, j, false); } for (s32 i = 0; i < mVector4fArrayFlags.size(); ++i) { for (s32 j = 0; j < mVector4fArrayFlags[i]->size(); ++j) resetVec4f(i, j, false); } } bool TriggerParam::getBoolIfCopied(bool* value, const sead::SafeString& name, bool x, bool y) const { if (mCopiedBoolFlags.isEmpty()) return false; const u32 hash = sead::HashCRC32::calcStringHash(name); for (s32 i = 0; i < mCopiedBoolFlags.size(); ++i) { if (mCopiedBoolFlags[i]->name_hash == hash) { if (!mCopiedBoolFlags[i]->checkBitFlags(x, y)) return false; *value = static_cast(mBoolFlags[getFlagIndex(mBoolFlags, hash)])->getValue(); return true; } } return false; } bool TriggerParam::getS32IfCopied(s32* value, const sead::SafeString& name, bool x, bool y) const { if (mCopiedS32Flags.isEmpty()) return false; const u32 hash = sead::HashCRC32::calcStringHash(name); for (s32 i = 0; i < mCopiedS32Flags.size(); ++i) { if (mCopiedS32Flags[i]->name_hash == hash) { if (!mCopiedS32Flags[i]->checkBitFlags(x, y)) return false; *value = static_cast(mS32Flags[getFlagIndex(mS32Flags, hash)])->getValue(); return true; } } return false; } bool TriggerParam::getF32IfCopied(f32* value, const sead::SafeString& name, bool x, bool y) const { if (mCopiedF32Flags.isEmpty()) return false; const u32 hash = sead::HashCRC32::calcStringHash(name); for (s32 i = 0; i < mCopiedF32Flags.size(); ++i) { if (mCopiedF32Flags[i]->name_hash == hash) { if (!mCopiedF32Flags[i]->checkBitFlags(x, y)) return false; *value = static_cast(mF32Flags[getFlagIndex(mF32Flags, hash)])->getValue(); return true; } } return false; } // FIXME: very incomplete void TriggerParam::copyChangedFlags(TriggerParam& other, bool set_all_flags, bool record_copies, bool ignore_temp_flags) { if (!set_all_flags) { for (s32 i = 0; i < 3; ++i) { auto lock = sead::makeScopedLock(other.mCriticalSections[i].ref()); for (s32 j = 0; j < mFlagChangeRecordIndices[i]; ++i) { const FlagChangeRecord& record = mFlagChangeRecords[i].ref()[j]; const auto idx = record.index; const auto sub_idx = record.sub_index; switch (record.type) { case FlagType::Bool: { auto* flag = static_cast(mBoolFlags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(static_cast(other.mBoolFlags[idx])->getValue()); const auto category = flag->getCategory(); addFlagCopyRecord(mCopiedBoolFlags, flag, -1, find_existing); if (category > 0) { if (flag->getValue()) ++mNumBoolFlagsPerCategory[category - 1]; else --mNumBoolFlagsPerCategory[category - 1]; } break; } case FlagType::S32: { auto* flag = static_cast(mS32Flags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(static_cast(other.mS32Flags[idx])->getValue()); addFlagCopyRecord(mCopiedS32Flags, flag, -1, find_existing); break; } case FlagType::F32: { auto* flag = static_cast(mF32Flags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(static_cast(other.mF32Flags[idx])->getValue()); addFlagCopyRecord(mCopiedF32Flags, flag, -1, find_existing); break; } case FlagType::String: { auto* flag = static_cast(mStringFlags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(static_cast(other.mStringFlags[idx])->getValue()); addFlagCopyRecord(mCopiedStringFlags, flag, -1, find_existing); break; } case FlagType::String64: { auto* flag = static_cast(mString64Flags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue( static_cast(other.mString64Flags[idx])->getValue()); addFlagCopyRecord(mCopiedString64Flags, flag, -1, find_existing); break; } case FlagType::String256: { auto* flag = static_cast(mString256Flags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue( static_cast(other.mString256Flags[idx])->getValue()); addFlagCopyRecord(mCopiedString256Flags, flag, -1, find_existing); break; } case FlagType::Vector2f: { auto* flag = static_cast(mVector2fFlags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue( static_cast(other.mVector2fFlags[idx])->getValue()); addFlagCopyRecord(mCopiedVector2fFlags, flag, -1, find_existing); break; } case FlagType::Vector3f: { auto* flag = static_cast(mVector3fFlags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue( static_cast(other.mVector3fFlags[idx])->getValue()); addFlagCopyRecord(mCopiedVector3fFlags, flag, -1, find_existing); break; } case FlagType::Vector4f: { auto* flag = static_cast(mVector4fFlags[idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue( static_cast(other.mVector4fFlags[idx])->getValue()); addFlagCopyRecord(mCopiedVector4fFlags, flag, -1, find_existing); break; } case FlagType::BoolArray: { auto* flag = static_cast((*mBoolArrayFlags[idx])[sub_idx]); auto* flag2 = static_cast((*other.mBoolArrayFlags[idx])[sub_idx]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); const auto category = flag->getCategory(); addFlagCopyRecord(mCopiedBoolFlags, flag, sub_idx, find_existing); if (category > 0) { if (flag->getValue()) ++mNumBoolFlagsPerCategory[category - 1]; else --mNumBoolFlagsPerCategory[category - 1]; } break; } case FlagType::S32Array: { auto* flag = static_cast((*mS32ArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast((*other.mS32ArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedS32Flags, flag, sub_idx, find_existing); break; } case FlagType::F32Array: { auto* flag = static_cast((*mF32ArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast((*other.mF32ArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedF32Flags, flag, sub_idx, find_existing); break; } case FlagType::StringArray: { auto* flag = static_cast((*mStringArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast((*other.mStringArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedStringFlags, flag, sub_idx, find_existing); break; } case FlagType::String64Array: { auto* flag = static_cast((*mString64ArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast( (*other.mString64ArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedString64Flags, flag, sub_idx, find_existing); break; } case FlagType::String256Array: { auto* flag = static_cast((*mString256ArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast( (*other.mString256ArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedString256Flags, flag, sub_idx, find_existing); break; } case FlagType::Vector2fArray: { auto* flag = static_cast((*mVector2fArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast( (*other.mVector2fArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedVector2fFlags, flag, sub_idx, find_existing); break; } case FlagType::Vector3fArray: { auto* flag = static_cast((*mVector3fArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast( (*other.mVector3fArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedVector3fFlags, flag, sub_idx, find_existing); break; } case FlagType::Vector4fArray: { auto* flag = static_cast((*mVector4fArrayFlags[idx])[record.sub_index]); auto* flag2 = static_cast( (*other.mVector4fArrayFlags[idx])[record.sub_index]); const bool find_existing = shouldFindExistingCopyRecord(); flag->setValue(flag2->getValue()); addFlagCopyRecord(mCopiedVector4fFlags, flag, sub_idx, find_existing); break; } case FlagType::Invalid: break; } } mFlagChangeRecordIndices[i] = 0; other.mBitFlags.ref().reset(BitFlag::_8); } return; } copyFlags(mBoolFlags, other.mBoolFlags, mCopiedBoolFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags(mS32Flags, other.mS32Flags, mCopiedS32Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags(mF32Flags, other.mF32Flags, mCopiedF32Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags>(mStringFlags, other.mStringFlags, mCopiedStringFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags>(mString64Flags, other.mString64Flags, mCopiedString64Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags>( mString256Flags, other.mString256Flags, mCopiedString256Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags(mVector2fFlags, other.mVector2fFlags, mCopiedVector2fFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags(mVector3fFlags, other.mVector3fFlags, mCopiedVector3fFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlags(mVector4fFlags, other.mVector4fFlags, mCopiedVector4fFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord(), false); copyFlagArrays(mBoolArrayFlags, other.mBoolArrayFlags, mCopiedBoolFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays(mS32ArrayFlags, other.mS32ArrayFlags, mCopiedS32Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays(mF32ArrayFlags, other.mF32ArrayFlags, mCopiedF32Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays>( mStringArrayFlags, other.mStringArrayFlags, mCopiedStringFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays>(mString64ArrayFlags, other.mString64ArrayFlags, mCopiedString64Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays>(mString256ArrayFlags, other.mString256ArrayFlags, mCopiedString256Flags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays(mVector2fArrayFlags, other.mVector2fArrayFlags, mCopiedVector2fFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays(mVector3fArrayFlags, other.mVector3fArrayFlags, mCopiedVector3fFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); copyFlagArrays(mVector4fArrayFlags, other.mVector4fArrayFlags, mCopiedVector4fFlags, mNumBoolFlagsPerCategory0, record_copies, ignore_temp_flags, shouldFindExistingCopyRecord()); } s32 TriggerParam::getBoolIdx(u32 name) const { return getFlagIndex(mBoolFlags, name); } s32 TriggerParam::getS32Idx(u32 name) const { return getFlagIndex(mS32Flags, name); } s32 TriggerParam::getF32Idx(u32 name) const { return getFlagIndex(mF32Flags, name); } s32 TriggerParam::getStrIdx(u32 name) const { return getFlagIndex(mStringFlags, name); } s32 TriggerParam::getStr64Idx(u32 name) const { return getFlagIndex(mString64Flags, name); } s32 TriggerParam::getStr256Idx(u32 name) const { return getFlagIndex(mString256Flags, name); } s32 TriggerParam::getVec2fIdx(u32 name) const { return getFlagIndex(mVector2fFlags, name); } s32 TriggerParam::getVec3fIdx(u32 name) const { return getFlagIndex(mVector3fFlags, name); } s32 TriggerParam::getVec4fIdx(u32 name) const { return getFlagIndex(mVector4fFlags, name); } s32 TriggerParam::getBoolArrayIdx(u32 name) const { return getFlagIndex(mBoolArrayFlags, name); } s32 TriggerParam::getS32ArrayIdx(u32 name) const { return getFlagIndex(mS32ArrayFlags, name); } s32 TriggerParam::getF32ArrayIdx(u32 name) const { return getFlagIndex(mF32ArrayFlags, name); } s32 TriggerParam::getStrArrayIdx(u32 name) const { return getFlagIndex(mStringArrayFlags, name); } s32 TriggerParam::getStr64ArrayIdx(u32 name) const { return getFlagIndex(mString64ArrayFlags, name); } s32 TriggerParam::getStr256ArrayIdx(u32 name) const { return getFlagIndex(mString256ArrayFlags, name); } s32 TriggerParam::getVec2fArrayIdx(u32 name) const { return getFlagIndex(mVector2fArrayFlags, name); } s32 TriggerParam::getVec3fArrayIdx(u32 name) const { return getFlagIndex(mVector3fArrayFlags, name); } s32 TriggerParam::getVec4fArrayIdx(u32 name) const { return getFlagIndex(mVector4fArrayFlags, name); } FlagBool* TriggerParam::getBoolFlag(s32 idx) const { return static_cast(mBoolFlags[idx]); } FlagS32* TriggerParam::getS32Flag(s32 idx) const { return static_cast(mS32Flags[idx]); } FlagF32* TriggerParam::getF32Flag(s32 idx) const { return static_cast(mF32Flags[idx]); } FlagString* TriggerParam::getStrFlag(s32 idx) const { return static_cast(mStringFlags[idx]); } FlagString64* TriggerParam::getStr64Flag(s32 idx) const { return static_cast(mString64Flags[idx]); } FlagString256* TriggerParam::getStr256Flag(s32 idx) const { return static_cast(mString256Flags[idx]); } FlagVector2f* TriggerParam::getVec2fFlag(s32 idx) const { return static_cast(mVector2fFlags[idx]); } FlagVector3f* TriggerParam::getVec3fFlag(s32 idx) const { return static_cast(mVector3fFlags[idx]); } FlagVector4f* TriggerParam::getVec4fFlag(s32 idx) const { return static_cast(mVector4fFlags[idx]); } FlagBool* TriggerParam::getBoolFlagAndIdx(s32* idx, u32 name_hash) const { *idx = getBoolIdx(name_hash); if (*idx < 0 || mBoolFlags.size() <= *idx) return nullptr; return getBoolFlag(*idx); } FlagS32* TriggerParam::getS32FlagAndIdx(s32* idx, u32 name_hash) const { *idx = getS32Idx(name_hash); if (*idx < 0 || mS32Flags.size() <= *idx) return nullptr; return getS32Flag(*idx); } FlagF32* TriggerParam::getF32FlagAndIdx(s32* idx, u32 name_hash) const { *idx = getF32Idx(name_hash); if (*idx < 0 || mF32Flags.size() <= *idx) return nullptr; return getF32Flag(*idx); } FlagString* TriggerParam::getStrFlagAndIdx(s32* idx, u32 name_hash) const { *idx = getStrIdx(name_hash); if (*idx < 0 || mStringFlags.size() <= *idx) return nullptr; return getStrFlag(*idx); } FlagString64* TriggerParam::getStr64FlagAndIdx(s32* idx, u32 name_hash) const { *idx = getStr64Idx(name_hash); if (*idx < 0 || mString64Flags.size() <= *idx) return nullptr; return getStr64Flag(*idx); } FlagString256* TriggerParam::getStr256FlagAndIdx(s32* idx, u32 name_hash) const { *idx = getStr256Idx(name_hash); if (*idx < 0 || mString256Flags.size() <= *idx) return nullptr; return getStr256Flag(*idx); } FlagVector2f* TriggerParam::getVec2fFlagAndIdx(s32* idx, u32 name_hash) const { *idx = getVec2fIdx(name_hash); if (*idx < 0 || mVector2fFlags.size() <= *idx) return nullptr; return getVec2fFlag(*idx); } FlagVector3f* TriggerParam::getVec3fFlagAndIdx(s32* idx, u32 name_hash) const { *idx = getVec3fIdx(name_hash); if (*idx < 0 || mVector3fFlags.size() <= *idx) return nullptr; return getVec3fFlag(*idx); } FlagVector4f* TriggerParam::getVec4fFlagAndIdx(s32* idx, u32 name_hash) const { *idx = getVec4fIdx(name_hash); if (*idx < 0 || mVector4fFlags.size() <= *idx) return nullptr; return getVec4fFlag(*idx); } FlagS32* TriggerParam::getS32FlagByHash(u32 name_hash) const { const s32 idx = getS32Idx(name_hash); if (idx < 0 || mS32Flags.size() <= idx) return nullptr; return getS32Flag(idx); } FlagBool* TriggerParam::getBoolFlag(s32 idx, s32 sub_idx) const { return static_cast(mBoolArrayFlags[idx]->at(sub_idx)); } FlagS32* TriggerParam::getS32Flag(s32 idx, s32 sub_idx) const { return static_cast(mS32ArrayFlags[idx]->at(sub_idx)); } FlagF32* TriggerParam::getF32Flag(s32 idx, s32 sub_idx) const { return static_cast(mF32ArrayFlags[idx]->at(sub_idx)); } FlagString* TriggerParam::getStrFlag(s32 idx, s32 sub_idx) const { return static_cast(mStringArrayFlags[idx]->at(sub_idx)); } FlagString64* TriggerParam::getStr64Flag(s32 idx, s32 sub_idx) const { return static_cast(mString64ArrayFlags[idx]->at(sub_idx)); } FlagString256* TriggerParam::getStr256Flag(s32 idx, s32 sub_idx) const { return static_cast(mString256ArrayFlags[idx]->at(sub_idx)); } FlagVector2f* TriggerParam::getVec2fFlag(s32 idx, s32 sub_idx) const { return static_cast(mVector2fArrayFlags[idx]->at(sub_idx)); } FlagVector3f* TriggerParam::getVec3fFlag(s32 idx, s32 sub_idx) const { return static_cast(mVector3fArrayFlags[idx]->at(sub_idx)); } FlagVector4f* TriggerParam::getVec4fFlag(s32 idx, s32 sub_idx) const { return static_cast(mVector4fArrayFlags[idx]->at(sub_idx)); } FlagBool* TriggerParam::getBoolFlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getBoolArrayIdx(name_hash); if (*idx < 0 || mBoolArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex(*mBoolArrayFlags[*idx], sub_idx); } FlagS32* TriggerParam::getS32FlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getS32ArrayIdx(name_hash); if (*idx < 0 || mS32ArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex(*mS32ArrayFlags[*idx], sub_idx); } FlagF32* TriggerParam::getF32FlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getF32ArrayIdx(name_hash); if (*idx < 0 || mF32ArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex(*mF32ArrayFlags[*idx], sub_idx); } FlagString* TriggerParam::getStrFlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getStrArrayIdx(name_hash); if (*idx < 0 || mStringArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex>(*mStringArrayFlags[*idx], sub_idx); } FlagString64* TriggerParam::getStr64FlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getStr64ArrayIdx(name_hash); if (*idx < 0 || mString64ArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex>(*mString64ArrayFlags[*idx], sub_idx); } FlagString256* TriggerParam::getStr256FlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getStr256ArrayIdx(name_hash); if (*idx < 0 || mString256ArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex>(*mString256ArrayFlags[*idx], sub_idx); } FlagVector2f* TriggerParam::getVec2fFlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getVec2fArrayIdx(name_hash); if (*idx < 0 || mVector2fArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex(*mVector2fArrayFlags[*idx], sub_idx); } FlagVector3f* TriggerParam::getVec3fFlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getVec3fArrayIdx(name_hash); if (*idx < 0 || mVector3fArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex(*mVector3fArrayFlags[*idx], sub_idx); } FlagVector4f* TriggerParam::getVec4fFlagAndIdx(s32* idx, u32 name_hash, s32 sub_idx) const { *idx = getVec4fArrayIdx(name_hash); if (*idx < 0 || mVector4fArrayFlags.size() <= *idx || sub_idx < 0) return nullptr; return getFlagByIndex(*mVector4fArrayFlags[*idx], sub_idx); } void TriggerParam::onResetBoolFlagForRadarMgr(FlagBase* flag, s32 sub_idx) { reportFlagChange(flag, sub_idx); } void TriggerParam::setCurrentRupeeFlagName(const sead::SafeString& name) { if (sConfig.num_current_rupee_flag_name_changes <= 0) { sConfig.getCurrentRupeeFlagName() = name; ++sConfig.num_current_rupee_flag_name_changes; } } bool shouldLogFlagChange(const sead::SafeString& flag_name, FlagType type) { u8 event_type; if (s32(type) == FlagType::Bool || s32(type) == FlagType::BoolArray) event_type = 0; else if (s32(type) == FlagType::S32 || s32(type) == FlagType::S32Array) event_type = 1; else if (s32(type) == FlagType::F32 || s32(type) == FlagType::F32Array) event_type = 2; else if (s32(type) == FlagType::Vector2f || s32(type) == FlagType::Vector2fArray || s32(type) == FlagType::Vector3f || s32(type) == FlagType::Vector3fArray || s32(type) == FlagType::Vector4f || s32(type) == FlagType::Vector4fArray) event_type = 4; else if (s32(type) == FlagType::String || s32(type) == FlagType::StringArray || s32(type) == FlagType::String64 || s32(type) == FlagType::String64Array || s32(type) == FlagType::String256 || s32(type) == FlagType::String256Array) event_type = 3; else event_type = 7; return sConfig.shouldLog(flag_name, event_type); } // NON_MATCHING: reorderings (which result in other small differences) sead::Color4f getFlagColor(FlagType type) { if (s32(type) == FlagType::Bool || s32(type) == FlagType::BoolArray) return sead::Color4f::cRed; if (s32(type) == FlagType::F32 || s32(type) == FlagType::F32Array || s32(type) == FlagType::Vector2f || s32(type) == FlagType::Vector2fArray || s32(type) == FlagType::Vector3f || s32(type) == FlagType::Vector3fArray || s32(type) == FlagType::Vector4f || s32(type) == FlagType::Vector4fArray) return sead::Color4f::cYellow; if (s32(type) == FlagType::String || s32(type) == FlagType::StringArray || s32(type) == FlagType::String64 || s32(type) == FlagType::String64Array || s32(type) == FlagType::String256 || s32(type) == FlagType::String256Array) return sead::Color4f::cWhite; return sead::Color4f::cBlue; } } // namespace ksys::gdt