From 08ce522edb39f477bb085d9bdc4d759608bb3281 Mon Sep 17 00:00:00 2001 From: gymnast86 Date: Fri, 22 May 2026 19:58:05 -0700 Subject: [PATCH] add flag checking for more intuitve location marking --- src/d/actor/d_a_npc_aru.cpp | 1 + src/d/actor/d_a_npc_ashB.cpp | 1 + src/d/actor/d_a_npc_chin.cpp | 7 +- src/d/actor/d_a_npc_fairy.cpp | 1 + src/d/actor/d_a_npc_gro.cpp | 1 + src/d/actor/d_a_npc_grr.cpp | 1 + src/d/actor/d_a_npc_grs.cpp | 1 + src/d/actor/d_a_npc_impal.cpp | 2 + src/d/actor/d_a_npc_kkri.cpp | 1 + src/d/actor/d_a_npc_len.cpp | 1 + src/d/actor/d_a_npc_pouya.cpp | 7 +- src/d/actor/d_a_npc_rafrel.cpp | 8 +-- src/d/actor/d_a_npc_uri.cpp | 1 + src/d/actor/d_a_npc_ykw.cpp | 1 + src/d/actor/d_a_npc_zra.inc | 8 ++- src/d/actor/d_a_npc_zrc.cpp | 1 + src/d/actor/d_a_npc_zrz.cpp | 1 + src/d/actor/d_a_obj_shield.cpp | 5 ++ src/d/actor/d_a_obj_sword.cpp | 5 ++ src/d/d_msg_flow.cpp | 4 +- src/d/d_msg_object.cpp | 8 ++- src/d/d_shop_system.cpp | 10 +-- src/dusk/imgui/ImGuiMenuRandomizer.cpp | 7 +- .../randomizer/game/randomizer_context.cpp | 66 +++++++++++++++---- .../randomizer/game/randomizer_context.hpp | 28 +++++++- src/dusk/randomizer/game/tools.cpp | 13 ++++ src/dusk/randomizer/game/tools.h | 5 +- .../randomizer/generator/data/locations.yaml | 2 +- 28 files changed, 157 insertions(+), 40 deletions(-) diff --git a/src/d/actor/d_a_npc_aru.cpp b/src/d/actor/d_a_npc_aru.cpp index 6d735c87d1..98fae72c28 100644 --- a/src/d/actor/d_a_npc_aru.cpp +++ b/src/d/actor/d_a_npc_aru.cpp @@ -1747,6 +1747,7 @@ int daNpc_Aru_c::cutSpeakTo(int i_staffID) { #if TARGET_PC if (randomizer_IsActive()) { itemNo = randomizer_getItemAtLocation("Herding Goats Reward"); + randomizer_setTempFlagForLocation("Herding Goats Reward"); } #endif mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, itemNo, 0, -1, -1, NULL, NULL); diff --git a/src/d/actor/d_a_npc_ashB.cpp b/src/d/actor/d_a_npc_ashB.cpp index eeb4eb341c..0a98132a5f 100644 --- a/src/d/actor/d_a_npc_ashB.cpp +++ b/src/d/actor/d_a_npc_ashB.cpp @@ -1008,6 +1008,7 @@ BOOL daNpcAshB_c::EvCut_Appear(int i_staffID) { #if TARGET_PC if (randomizer_IsActive()) { local_30[0] = verifyProgressiveItem(randomizer_getItemAtLocation("Ashei Sketch")); + randomizer_setTempFlagForLocation("Ashei Sketch"); } #endif mItemPartnerId = diff --git a/src/d/actor/d_a_npc_chin.cpp b/src/d/actor/d_a_npc_chin.cpp index 6b8042c299..6024f748e2 100644 --- a/src/d/actor/d_a_npc_chin.cpp +++ b/src/d/actor/d_a_npc_chin.cpp @@ -1806,10 +1806,13 @@ int daNpcChin_c::_Evt_GameSucceed_CutMain(const int& param_0) { #if TARGET_PC if (randomizer_IsActive()) { - if (itemId1 == dItemNo_ARROW_LV2_e) + if (itemId1 == dItemNo_ARROW_LV2_e) { itemId1 = randomizer_getItemAtLocation("STAR Prize 1"); - else if (itemId1 == dItemNo_ARROW_LV3_e) + randomizer_setTempFlagForLocation("STAR Prize 1"); + } else if (itemId1 == dItemNo_ARROW_LV3_e) { itemId1 = randomizer_getItemAtLocation("STAR Prize 2"); + randomizer_setTempFlagForLocation("STAR Prize 2"); + } } #endif fpc_ProcID itemId2 = fopAcM_createItemForPresentDemo(¤t.pos, itemId1, 0, -1, -1, diff --git a/src/d/actor/d_a_npc_fairy.cpp b/src/d/actor/d_a_npc_fairy.cpp index b70d85866c..cd4d799e4c 100644 --- a/src/d/actor/d_a_npc_fairy.cpp +++ b/src/d/actor/d_a_npc_fairy.cpp @@ -1341,6 +1341,7 @@ void daNpc_Fairy_c::PresentDemoCall() { // If we haven't visted this great fairy before, give the random item if (randomizer_IsActive() && !daNpcT_chkEvtBit(505)) { item_no = verifyProgressiveItem(randomizer_getItemAtLocation("Cave of Ordeals Great Fairy Reward")); + randomizer_setTempFlagForLocation("Cave of Ordeals Great Fairy Reward"); } #endif diff --git a/src/d/actor/d_a_npc_gro.cpp b/src/d/actor/d_a_npc_gro.cpp index d3ec51180a..dbd8b9893b 100644 --- a/src/d/actor/d_a_npc_gro.cpp +++ b/src/d/actor/d_a_npc_gro.cpp @@ -1688,6 +1688,7 @@ int daNpc_grO_c::talk(void* param_1) { #if TARGET_PC if (randomizer_IsActive()) { itemId = verifyProgressiveItem(randomizer_getItemAtLocation("Goron Mines Gor Ebizo Key Shard")); + randomizer_setTempFlagForLocation("Goron Mines Gor Ebizo Key Shard"); } #endif mItemID = fopAcM_createItemForPresentDemo(¤t.pos, itemId, 0, -1, -1, NULL, NULL); diff --git a/src/d/actor/d_a_npc_grr.cpp b/src/d/actor/d_a_npc_grr.cpp index 96e243c140..b62f57abed 100644 --- a/src/d/actor/d_a_npc_grr.cpp +++ b/src/d/actor/d_a_npc_grr.cpp @@ -1345,6 +1345,7 @@ int daNpc_grR_c::talk(void* param_1) { #if TARGET_PC if (randomizer_IsActive()) { i_itemNo = verifyProgressiveItem(randomizer_getItemAtLocation("Goron Mines Gor Liggs Key Shard")); + randomizer_setTempFlagForLocation("Goron Mines Gor Liggs Key Shard"); } #endif mItemID = fopAcM_createItemForPresentDemo(¤t.pos, i_itemNo, 0, -1, -1, NULL, NULL); diff --git a/src/d/actor/d_a_npc_grs.cpp b/src/d/actor/d_a_npc_grs.cpp index a2a271de89..b119a8f96b 100644 --- a/src/d/actor/d_a_npc_grs.cpp +++ b/src/d/actor/d_a_npc_grs.cpp @@ -1191,6 +1191,7 @@ int daNpc_grS_c::talk(void* param_0) { #if TARGET_PC if (randomizer_IsActive()) { unkInt2 = verifyProgressiveItem(randomizer_getItemAtLocation("Goron Mines Gor Amato Key Shard")); + randomizer_setTempFlagForLocation("Goron Mines Gor Amato Key Shard"); } #endif mPresentItemId = diff --git a/src/d/actor/d_a_npc_impal.cpp b/src/d/actor/d_a_npc_impal.cpp index f3c8bc5d6b..5c4069bce7 100644 --- a/src/d/actor/d_a_npc_impal.cpp +++ b/src/d/actor/d_a_npc_impal.cpp @@ -978,6 +978,7 @@ BOOL daNpcImpal_c::EvCut_ImpalAppear1(int i_cut_index) { #if TARGET_PC if (randomizer_IsActive()) { evt_id = verifyProgressiveItem(randomizer_getItemAtLocation("Ilia Charm")); + randomizer_setTempFlagForLocation("Ilia Charm"); } #endif mItemPartnerId = @@ -1072,6 +1073,7 @@ BOOL daNpcImpal_c::EvCut_CopyRod(int i_cut_index) { #if TARGET_PC if (randomizer_IsActive()) { evt_id = verifyProgressiveItem(randomizer_getItemAtLocation("Skybook From Impaz")); + randomizer_setTempFlagForLocation("Skybook From Impaz"); } #endif mItemPartnerId = diff --git a/src/d/actor/d_a_npc_kkri.cpp b/src/d/actor/d_a_npc_kkri.cpp index ff80ad4abf..8ee5a6e0a4 100644 --- a/src/d/actor/d_a_npc_kkri.cpp +++ b/src/d/actor/d_a_npc_kkri.cpp @@ -1187,6 +1187,7 @@ int daNpc_Kkri_c::talk(void*) { if (randomizer_IsActive()) { if (item_no == dItemNo_OIL_BOTTLE3_e) { item_no = verifyProgressiveItem(randomizer_getItemAtLocation("Coro Bottle")); + randomizer_setTempFlagForLocation("Coro Bottle"); } /*else if (item_no == dItemNo_SMALL_KEY_e) { // Might be Small Key 2 item_no = verifyProgressiveItem(randomizer_getItemAtLocation("Coro Gate Key")); }*/ diff --git a/src/d/actor/d_a_npc_len.cpp b/src/d/actor/d_a_npc_len.cpp index b15ca760c5..9a7e3df17b 100644 --- a/src/d/actor/d_a_npc_len.cpp +++ b/src/d/actor/d_a_npc_len.cpp @@ -1243,6 +1243,7 @@ int daNpc_Len_c::talk(void* param_0) { #if TARGET_PC if (randomizer_IsActive()) { local_18 = verifyProgressiveItem(randomizer_getItemAtLocation("Renados Letter")); + randomizer_setTempFlagForLocation("Renados Letter"); } #endif mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, local_18, diff --git a/src/d/actor/d_a_npc_pouya.cpp b/src/d/actor/d_a_npc_pouya.cpp index 22e103da24..e74e884952 100644 --- a/src/d/actor/d_a_npc_pouya.cpp +++ b/src/d/actor/d_a_npc_pouya.cpp @@ -967,10 +967,13 @@ int daNpc_Pouya_c::cutHaveFavorToAsk(int param_0) { if (mItemPartnerId == fpcM_ERROR_PROCESS_ID_e) { #if TARGET_PC if (randomizer_IsActive()) { - if (local_64 == dItemNo_Randomizer_DROP_BOTTLE_e) + if (local_64 == dItemNo_Randomizer_DROP_BOTTLE_e) { local_64 = verifyProgressiveItem(randomizer_getItemAtLocation("Jovani 20 Poe Soul Reward")); - else if (local_64 == dItemNo_Randomizer_SILVER_RUPEE_e) + randomizer_setTempFlagForLocation("Jovani 20 Poe Soul Reward"); + } else if (local_64 == dItemNo_Randomizer_SILVER_RUPEE_e) { local_64 = verifyProgressiveItem(randomizer_getItemAtLocation("Jovani 60 Poe Soul Reward")); + randomizer_setTempFlagForLocation("Jovani 60 Poe Soul Reward"); + } } #endif mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, local_64, 0, diff --git a/src/d/actor/d_a_npc_rafrel.cpp b/src/d/actor/d_a_npc_rafrel.cpp index 23f96ecc6f..657960f637 100644 --- a/src/d/actor/d_a_npc_rafrel.cpp +++ b/src/d/actor/d_a_npc_rafrel.cpp @@ -1322,8 +1322,8 @@ bool daNpcRafrel_c::talk(void* param_0) { if (eventId == 1) { #if TARGET_PC if (randomizer_IsActive()) { - u8 itemId = randomizer_getItemAtLocation("Auru Gift To Fyer"); - itemNo = verifyProgressiveItem(itemId); + itemNo = verifyProgressiveItem(randomizer_getItemAtLocation("Auru Gift To Fyer")); + randomizer_setTempFlagForLocation("Auru Gift To Fyer"); } #endif field_0xe00 = fopAcM_createItemForPresentDemo(¤t.pos, itemNo, 0, -1, -1, NULL, NULL); @@ -1580,8 +1580,8 @@ int daNpcRafrel_c::EvCut_Appear(int i_staffId) { if (eventId == 1) { #if TARGET_PC if (randomizer_IsActive()) { - u8 itemId = randomizer_getItemAtLocation("Auru Gift To Fyer"); - itemNo = verifyProgressiveItem(itemId); + itemNo = verifyProgressiveItem(randomizer_getItemAtLocation("Auru Gift To Fyer")); + randomizer_setTempFlagForLocation("Auru Gift To Fyer"); } #endif field_0xe00 = fopAcM_createItemForPresentDemo(¤t.pos, itemNo, 0, -1, -1, NULL, NULL); diff --git a/src/d/actor/d_a_npc_uri.cpp b/src/d/actor/d_a_npc_uri.cpp index 7dc9eda11a..a245a62006 100644 --- a/src/d/actor/d_a_npc_uri.cpp +++ b/src/d/actor/d_a_npc_uri.cpp @@ -1168,6 +1168,7 @@ int daNpc_Uri_c::cutEndCarryTutorial(int param_1) { #if TARGET_PC if (randomizer_IsActive()) { local_48 = randomizer_getItemAtLocation("Uli Cradle Delivery"); + randomizer_setTempFlagForLocation("Uli Cradle Delivery"); } #endif mItemPartnerId = diff --git a/src/d/actor/d_a_npc_ykw.cpp b/src/d/actor/d_a_npc_ykw.cpp index 14846c70a3..5ebf7a81ed 100644 --- a/src/d/actor/d_a_npc_ykw.cpp +++ b/src/d/actor/d_a_npc_ykw.cpp @@ -2924,6 +2924,7 @@ int daNpc_ykW_c::talk(void* param_0) { #if TARGET_PC if (randomizer_IsActive()) { itemNo = verifyProgressiveItem(randomizer_getItemAtLocation("Snowpeak Ruins Mansion Map")); + randomizer_setTempFlagForLocation("Snowpeak Ruins Mansion Map"); } #endif mItemPartnerId = diff --git a/src/d/actor/d_a_npc_zra.inc b/src/d/actor/d_a_npc_zra.inc index 7f4e36ca5d..0dea40529e 100644 --- a/src/d/actor/d_a_npc_zra.inc +++ b/src/d/actor/d_a_npc_zra.inc @@ -2611,10 +2611,14 @@ BOOL daNpc_zrA_c::ECut_thanksBlast(int i_staffID) { if (mFlow.getEventId(&item_id) == 1) { #if TARGET_PC if (randomizer_IsActive()) { - if (item_id == dItemNo_Randomizer_BOMB_IN_BAG_e) + if (item_id == dItemNo_Randomizer_BOMB_IN_BAG_e) { item_id = verifyProgressiveItem(randomizer_getItemAtLocation("Iza Helping Hand")); - else if (item_id == dItemNo_Randomizer_BOMB_BAG_LV2_e) + randomizer_setTempFlagForLocation("Iza Helping Hand"); + } else if (item_id == dItemNo_Randomizer_BOMB_BAG_LV2_e) { item_id = verifyProgressiveItem(randomizer_getItemAtLocation("Iza Raging Rapids Minigame")); + randomizer_setTempFlagForLocation("Iza Raging Rapids Minigame"); + } + } #endif mItemID = fopAcM_createItemForPresentDemo(¤t.pos, item_id, diff --git a/src/d/actor/d_a_npc_zrc.cpp b/src/d/actor/d_a_npc_zrc.cpp index 477464d10e..e1349fe10e 100644 --- a/src/d/actor/d_a_npc_zrc.cpp +++ b/src/d/actor/d_a_npc_zrc.cpp @@ -1691,6 +1691,7 @@ BOOL daNpc_zrC_c::ECut_earringGet(int i_staffID) { #if TARGET_PC if (randomizer_IsActive()) { item_no = verifyProgressiveItem(randomizer_getItemAtLocation("Gift From Ralis")); + randomizer_setTempFlagForLocation("Gift From Ralis"); } #endif mItemID = fopAcM_createItemForPresentDemo(¤t.pos, item_no, diff --git a/src/d/actor/d_a_npc_zrz.cpp b/src/d/actor/d_a_npc_zrz.cpp index 90d86d8aae..e98b423886 100644 --- a/src/d/actor/d_a_npc_zrz.cpp +++ b/src/d/actor/d_a_npc_zrz.cpp @@ -1742,6 +1742,7 @@ BOOL daNpc_zrZ_c::ECut_clothesGet(int i_staffID) { #if TARGET_PC if (randomizer_IsActive()) { item_no = verifyProgressiveItem(randomizer_getItemAtLocation("Rutelas Blessing")); + randomizer_setTempFlagForLocation("Rutelas Blessing"); } #endif mItemID = fopAcM_createItemForPresentDemo(¤t.pos, item_no, diff --git a/src/d/actor/d_a_obj_shield.cpp b/src/d/actor/d_a_obj_shield.cpp index 420a478b56..39b831f274 100644 --- a/src/d/actor/d_a_obj_shield.cpp +++ b/src/d/actor/d_a_obj_shield.cpp @@ -248,6 +248,11 @@ int daItemShield_c::initActionOrderGetDemo() { daItemBase_c::hide(); fopAcM_orderItemEvent(this, 0, 0); eventInfo.onCondition(dEvtCnd_CANGETITEM_e); +#if TARGET_PC + if (randomizer_IsActive()) { + randomizer_setTempFlagForLocation("Ordon Shield"); + } +#endif mItemId = fopAcM_createItemForTrBoxDemo(¤t.pos, m_itemNo, -1, fopAcM_GetRoomNo(this), 0, 0); JUT_ASSERT(682, mItemId != fpcM_ERROR_PROCESS_ID_e) diff --git a/src/d/actor/d_a_obj_sword.cpp b/src/d/actor/d_a_obj_sword.cpp index 32f9d2b47d..d8376bc675 100644 --- a/src/d/actor/d_a_obj_sword.cpp +++ b/src/d/actor/d_a_obj_sword.cpp @@ -82,6 +82,11 @@ int daObjSword_c::initActionOrderGetDemo() { hide(); fopAcM_orderItemEvent(this, 0, 0); eventInfo.onCondition(8); +#if TARGET_PC + if (randomizer_IsActive()) { + randomizer_setTempFlagForLocation("Ordon Sword"); + } +#endif mProcID = fopAcM_createItemForTrBoxDemo(¤t.pos, m_itemNo, -1, fopAcM_GetRoomNo(this), NULL, NULL); setStatus(1); diff --git a/src/d/d_msg_flow.cpp b/src/d/d_msg_flow.cpp index db245f3c1c..c69e8d85e9 100644 --- a/src/d/d_msg_flow.cpp +++ b/src/d/d_msg_flow.cpp @@ -521,10 +521,12 @@ int dMsgFlow_c::setNormalMsg(mesg_flow_node* i_flowNode_p, fopAc_ac_c* i_speaker } auto& flowItemOverrides = randomizer_GetContext().mFlowItemMessageOverrides; if (flowItemOverrides.contains(key)) { - u8 itemId = verifyProgressiveItem(flowItemOverrides[key]); + u8 itemId = verifyProgressiveItem(flowItemOverrides[key].itemId); msg_no = getItemMessageID(itemId); // Store this itemId so that we can give the item when the textbox closes g_randomizerState.mFlowMessageItemId = itemId; + // Set flag for tracker/AP + randomizer_setTempFlagForFLWOverride(key); } } #endif diff --git a/src/d/d_msg_object.cpp b/src/d/d_msg_object.cpp index 77f55cef28..b0cc6aa756 100644 --- a/src/d/d_msg_object.cpp +++ b/src/d/d_msg_object.cpp @@ -711,21 +711,25 @@ u32 dMsgObject_c::getRevoMessageIndex(u32 param_1) { if (randomizer_IsActive()) { // Special case for Ilia Memory Reward Text (param_1 is msgId) // If we're in the sanctuary cutscene where we get the reward, override the text. - // Otherwise the regular item text for the horse call would be overriden if we find it + // Otherwise, the regular item text for the horse call would be overridden if we find it if (param_1 == 233 && playerIsInRoomStage(0, "R_SP109") && dComIfGp_getLayerNo() == 9) { u8 itemId = verifyProgressiveItem(randomizer_getItemAtLocation("Ilia Memory Reward")); param_1 = getItemMessageID(itemId); // Store this itemId so that we can give the item when the textbox closes g_randomizerState.mFlowMessageItemId = itemId; + // Set flag for tracker/AP + randomizer_setTempFlagForLocation("Ilia Memory Reward"); } else { // Else override the text if we have an override u32 key = (dMsgObject_getGroupID() << 16) | param_1; auto& flowItemOverrides = randomizer_GetContext().mFlowItemMessageOverrides; if (flowItemOverrides.contains(key)) { - u8 itemId = verifyProgressiveItem(flowItemOverrides[key]); + u8 itemId = verifyProgressiveItem(flowItemOverrides[key].itemId); param_1 = getItemMessageID(itemId); // Store this itemId so that we can give the item when the textbox closes g_randomizerState.mFlowMessageItemId = itemId; + // Set flag for tracker/AP + randomizer_setTempFlagForFLWOverride(key); } } } diff --git a/src/d/d_shop_system.cpp b/src/d/d_shop_system.cpp index 530d732484..196385870a 100644 --- a/src/d/d_shop_system.cpp +++ b/src/d/d_shop_system.cpp @@ -911,13 +911,9 @@ int dShopSystem_c::seq_start(fopAc_ac_c* actor, dMsgFlow_c* i_flow) { if (mFlow.getEventId(&itemNo) == 1) { if (mItemPartnerId == fpcM_ERROR_PROCESS_ID_e) { #if TARGET_PC - // In rando, override the item if it's one of our unique shop checks - if (randomizer_IsActive()) { - switch (itemNo) { - case dItemNo_Randomizer_HALF_MILK_BOTTLE_e: - itemNo = randomizer_getItemAtLocation("Ordon Cat Rescue"); - break; - } + // In rando, override the cat rescue item + if (randomizer_IsActive() && itemNo == dItemNo_Randomizer_HALF_MILK_BOTTLE_e) { + itemNo = randomizer_getItemAtLocation("Ordon Cat Rescue"); } #endif mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, itemNo, 0, -1, diff --git a/src/dusk/imgui/ImGuiMenuRandomizer.cpp b/src/dusk/imgui/ImGuiMenuRandomizer.cpp index 9b9328223b..3070bbfc0e 100644 --- a/src/dusk/imgui/ImGuiMenuRandomizer.cpp +++ b/src/dusk/imgui/ImGuiMenuRandomizer.cpp @@ -6,6 +6,7 @@ #include "dusk/logging.h" #include "dusk/data.hpp" #include "dusk/randomizer/generator/logic/search.hpp" +#include "dusk/randomizer/generator/utility/string.hpp" #include "dusk/randomizer/game/randomizer_context.hpp" #include "dusk/randomizer/game/tools.h" @@ -13,8 +14,6 @@ #include #include -#include "dusk/randomizer/generator/utility/string.hpp" - namespace dusk { static bool generatingSeed = false; @@ -354,11 +353,11 @@ namespace dusk { info.collected = dComIfGs_isStageSwitch(stageId, flag); } else if (auto& eventFlagNode = locationMeta["Event Flag"]) { auto flag = eventFlagNode.as(); - info.collected = dComIfGs_isEventBit(flag); + info.collected = tracker_isEventBit(flag); } else if (auto& switchFlagNode = locationMeta["Switch Flag"]) { auto flag = switchFlagNode["Flag"].as(); auto stageId = getStageSaveId(switchFlagNode["Stage"].as()); - info.collected = dComIfGs_isStageSwitch(stageId, flag); + info.collected = tracker_isStageSwitch(stageId, flag); } else { info.collected = false; } diff --git a/src/dusk/randomizer/game/randomizer_context.cpp b/src/dusk/randomizer/game/randomizer_context.cpp index 09e05f5b55..50dca25973 100644 --- a/src/dusk/randomizer/game/randomizer_context.cpp +++ b/src/dusk/randomizer/game/randomizer_context.cpp @@ -71,10 +71,19 @@ std::optional RandomizerContext::WriteToFile() { const std::unordered_map u16ShopOverrides(this->mShopOverrides.begin(), this->mShopOverrides.end()); out["mShopOverrides"] = u16ShopOverrides; - const std::unordered_map u32FlowItemMessageOverrides(this->mFlowItemMessageOverrides.begin(), this->mFlowItemMessageOverrides.end()); - out["mFlowItemMessageOverrides"] = u32FlowItemMessageOverrides; + for (const auto& [key, data] : this->mFlowItemMessageOverrides) { + auto node = out["mFlowItemMessageOverrides"][key]; + node["itemId"] = data.itemId; + node["stage"] = data.stage; + node["flag"] = data.flag; + } - out["mItemLocations"] = this->mItemLocations; + for (const auto& [name, data] : this->mItemLocations) { + auto node = out["mItemLocations"][name]; + node["itemId"] = data.itemId; + node["stage"] = data.stage; + node["flag"] = data.flag; + } out["mStartHour"] = static_cast(this->mStartHour); out["mMapBits"] = static_cast(this->mMapBits); @@ -197,18 +206,23 @@ std::optional RandomizerContext::LoadFromHash(const std::string& ha this->mShopOverrides[key] = itemId; } + // Helper function for getting the item data out of a YAML node + auto retrieveItemData = [](auto& itemData, auto& node) { + itemData.itemId = node["itemId"].as(); + itemData.stage = node["stage"].as(); + itemData.flag = node["flag"].as(); + }; + // FLW Override items for (const auto& flwNode : in["mFlowItemMessageOverrides"]) { u32 key = flwNode.first.as(); - u8 itemId = flwNode.second.as(); - this->mFlowItemMessageOverrides[key] = itemId; + retrieveItemData(this->mFlowItemMessageOverrides[key], flwNode.second); } // Items we call by location name for (const auto& locationNode : in["mItemLocations"]) { const auto& locationName = locationNode.first.as(); - int itemId = locationNode.second.as(); - this->mItemLocations[locationName] = itemId; + retrieveItemData(this->mItemLocations[locationName], locationNode.second); } // Starting hour @@ -761,7 +775,25 @@ std::vector HexToBytes(std::string hex) { } int randomizer_getItemAtLocation(const std::string& locationName) { - return randomizer_GetContext().mItemLocations[locationName]; + return randomizer_GetContext().mItemLocations[locationName].itemId; +} + +static void randomizer_setTempFlag(RandomizerContext::itemLocationData data) { + // If stage is 0xFF, then this is an event flag + if (data.stage == 0xFF) { + g_randomizerState.mTrackerTempEventFlag = data.flag; + } else { + g_randomizerState.mTrackerTempSwitchFlag.stage = getStageSaveId(data.stage); + g_randomizerState.mTrackerTempSwitchFlag.flag = data.flag; + } +} + +void randomizer_setTempFlagForLocation(const std::string& locationName) { + randomizer_setTempFlag(randomizer_GetContext().mItemLocations[locationName]); +} + +void randomizer_setTempFlagForFLWOverride(u32 key) { + randomizer_setTempFlag(randomizer_GetContext().mFlowItemMessageOverrides[key]); } bool randomizer_checkTempleOfTimeRequirement() { @@ -806,7 +838,7 @@ u8 randomizer_getRandomFoolishItemModelID() { static constexpr auto foolishItemModels = std::to_array({ dItemNo_Randomizer_ARMOR_e, dItemNo_Randomizer_WOOD_STICK_e, - dItemNo_Randomizer_SHIELD_e, + dItemNo_Randomizer_WOOD_SHIELD_e, dItemNo_Randomizer_HYLIA_SHIELD_e, dItemNo_Randomizer_MAGIC_LV1_e, dItemNo_Randomizer_FISHING_ROD_1_e, @@ -1023,13 +1055,24 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) { } } + // Helper function for getting flag values + auto getNodeFlags = [](auto& itemData, auto& metaData) { + if (metaData["Event Flag"]) { + itemData.flag = metaData["Event Flag"].as(); + } else if (metaData["Switch Flag"]) { + itemData.stage = metaData["Switch Flag"]["Stage"].as(); + itemData.flag = metaData["Switch Flag"]["Flag"].as(); + } + }; + // Items that we determine the text of and then give during a FLW message if (location->HasCategories("FLW Message")) { for (const auto& flwMessageNode : metaData["FLW Message"]) { u8 group = flwMessageNode["Group"].as(); u16 messageId = flwMessageNode["Message Id"].as(); u32 key = (group << 16) | messageId; - randoData.mFlowItemMessageOverrides[key] = location->GetCurrentItem()->GetID(); + randoData.mFlowItemMessageOverrides[key].itemId = location->GetCurrentItem()->GetID(); + getNodeFlags(randoData.mFlowItemMessageOverrides[key], metaData); } } @@ -1038,7 +1081,8 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) { for (const auto& locationNameNode : metaData["Name Lookup"]) { const auto& locationName = locationNameNode.as(); const int itemId = location->GetCurrentItem()->GetID(); - randoData.mItemLocations[locationName] = itemId; + randoData.mItemLocations[locationName].itemId = itemId; + getNodeFlags(randoData.mItemLocations[locationName], metaData); } } } diff --git a/src/dusk/randomizer/game/randomizer_context.hpp b/src/dusk/randomizer/game/randomizer_context.hpp index e6d3383c52..86427d6740 100644 --- a/src/dusk/randomizer/game/randomizer_context.hpp +++ b/src/dusk/randomizer/game/randomizer_context.hpp @@ -37,6 +37,13 @@ public: std::list mStartEventFlags{}; std::unordered_map> mStartRegionFlags{}; std::list mStartingInventory{}; + + struct itemLocationData{ + int itemId{0xFF}; + int stage{0xFF}; + u16 flag{0xFFFF}; + }; + std::unordered_map mTreasureChestOverrides{}; std::unordered_map mPoeOverrides{}; std::unordered_map mFreestandingItemOverrides{}; @@ -44,8 +51,9 @@ public: std::unordered_map mSkyCharacterOverrides{}; std::unordered_map mGoldenWolfOverrides{}; std::unordered_map mShopOverrides{}; - std::unordered_map mFlowItemMessageOverrides{}; - std::unordered_map mItemLocations{}; + std::unordered_map mFlowItemMessageOverrides{}; + std::unordered_map mItemLocations{}; + u8 mStartHour{0}; u8 mMapBits{}; @@ -116,7 +124,7 @@ public: /* * Class holding seed-agnostic dynamic information about current randomizer play. - * This gets reset when reseting to the title screen. + * This gets reset when resetting to the title screen. */ class RandomizerState { public: @@ -174,6 +182,11 @@ public: int mFoolishItemCount{0}; bool mUpdateTracker{false}; + u16 mTrackerTempEventFlag{0}; + struct { + int stage{-1}; + int flag{-1}; + } mTrackerTempSwitchFlag; }; extern RandomizerState g_randomizerState; @@ -184,6 +197,15 @@ bool randomizer_IsActive(); int randomizer_getItemAtLocation(const std::string& locationName); +/* + * @brief Puts the associated flag into the randomizer state's temporary flag + * variable. This allows the tracker/Archipelago to know a location has been checked + * when the item is received instead of some indeterminate amount of time afterward. + */ +void randomizer_setTempFlagForLocation(const std::string& locationName); + +void randomizer_setTempFlagForFLWOverride(u32 key); + bool randomizer_checkTempleOfTimeRequirement(); u8 randomizer_getRandomFoolishItemModelID(); diff --git a/src/dusk/randomizer/game/tools.cpp b/src/dusk/randomizer/game/tools.cpp index 90892bb4df..eb75ae521b 100644 --- a/src/dusk/randomizer/game/tools.cpp +++ b/src/dusk/randomizer/game/tools.cpp @@ -238,6 +238,9 @@ randomizer::logic::item_pool::ItemPool getSaveItemPool(randomizer::logic::world: pool.push_back(world->GetItem("Slingshot", true)); break; case dItemNo_Randomizer_BOMB_BAG_LV1_e: + case dItemNo_Randomizer_NORMAL_BOMB_e: + case dItemNo_Randomizer_WATER_BOMB_e: + case dItemNo_Randomizer_POKE_BOMB_e: pool.push_back(world->GetItem("Bomb Bag", true)); break; case dItemNo_Randomizer_RAFRELS_MEMO_e: @@ -577,4 +580,14 @@ int getStageSaveId(int id) { int getStageSaveId(const char* stage) { int id = getStageID(stage); return getStageSaveId(id); +} + +bool tracker_isEventBit(u16 flag) { + return g_randomizerState.mTrackerTempEventFlag == flag || dComIfGs_isEventBit(flag); +} + +bool tracker_isStageSwitch(int stage, int flag) { + return dComIfGs_isStageSwitch(stage, flag) || + (g_randomizerState.mTrackerTempSwitchFlag.flag == flag && + g_randomizerState.mTrackerTempSwitchFlag.stage == stage); } \ No newline at end of file diff --git a/src/dusk/randomizer/game/tools.h b/src/dusk/randomizer/game/tools.h index 30982f9b0d..a19215fff4 100644 --- a/src/dusk/randomizer/game/tools.h +++ b/src/dusk/randomizer/game/tools.h @@ -26,4 +26,7 @@ randomizer::logic::item_pool::ItemPool getSaveItemPool(randomizer::logic::world: // Used to get a stage's Area ID used for save flags int getStageSaveId(int id); -int getStageSaveId(const char* stage); \ No newline at end of file +int getStageSaveId(const char* stage); + +bool tracker_isEventBit(u16 flag); +bool tracker_isStageSwitch(int stage, int flag); \ No newline at end of file diff --git a/src/dusk/randomizer/generator/data/locations.yaml b/src/dusk/randomizer/generator/data/locations.yaml index 93dc8d4384..62624a3de3 100644 --- a/src/dusk/randomizer/generator/data/locations.yaml +++ b/src/dusk/randomizer/generator/data/locations.yaml @@ -1444,7 +1444,7 @@ Metadata: Name Lookup: - Ilia Memory Reward - Event Flag: 0x2320 # (Maybe use 0x5E04?) + Event Flag: 0x5E04 - Name: Rutelas Blessing Original Item: Zora Armor