diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp index 25947aa0e..1dee72669 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp @@ -11,6 +11,7 @@ //Location definitions static std::array locationTable; +static std::unordered_map locationLookupTable; void LocationTable_Init() { locationTable[NONE] = ItemLocation::Base (RC_UNKNOWN_CHECK, 0xFF, 0xFF, "Invalid Location", NONE, NONE, {}, SpoilerCollectionCheck::None()); @@ -917,6 +918,10 @@ void LocationTable_Init() { locationTable[DMC_UPPER_GROTTO_GOSSIP_STONE] = ItemLocation::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, 0x00, 0x3A, "DMC Upper Grotto Gossip Stone", {}); locationTable[GANONDORF_HINT] = ItemLocation::OtherHint(RC_GANONDORF_HINT, 0x00, 0x00, "Ganondorf Hint", {}); + + // TODO also update the Add/Remove/Etc functions + for (int i = NONE; i != KEY_ENUM_MAX; i++) + locationLookupTable.insert(std::make_pair(locationTable[i].GetRandomizerCheck(), static_cast(i))); } std::vector KF_ShopLocations = { @@ -1484,6 +1489,10 @@ ItemLocation* Location(uint32_t locKey) { return &(locationTable[locKey]); } +ItemLocation* Location(RandomizerCheck rc) { + return &(locationTable[locationLookupTable[rc]]); +} + std::vector allLocations = {}; std::vector everyPossibleLocation = {}; diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.hpp b/soh/soh/Enhancements/randomizer/3drando/item_location.hpp index eaa6e39de..baff41ae5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.hpp @@ -475,6 +475,124 @@ public: void LocationTable_Init(); ItemLocation* Location(uint32_t locKey); +ItemLocation* Location(RandomizerCheck rc); + + +static std::unordered_map randomizerFlagLookup = { + { RC_KF_LINKS_HOUSE_COW, RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW }, + { RC_HF_COW_GROTTO_COW, RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW }, + { RC_LLR_STABLES_LEFT_COW, RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW }, + { RC_LLR_STABLES_RIGHT_COW, RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW }, + { RC_LLR_TOWER_LEFT_COW, RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW }, + { RC_LLR_TOWER_RIGHT_COW, RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW }, + { RC_KAK_IMPAS_HOUSE_COW, RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW }, + { RC_DMT_COW_GROTTO_COW, RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW }, + { RC_GV_COW, RAND_INF_COWS_MILKED_GV_COW }, + { RC_JABU_JABUS_BELLY_MQ_COW, RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW }, + + { RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT }, + { RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS }, + { RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT }, + { RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY }, + { RC_JABU_JABUS_BELLY_DEKU_SCRUB, RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB }, + { RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT }, + { RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT }, + { RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT }, + { RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT }, + { RC_HF_DEKU_SCRUB_GROTTO, RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO }, + { RC_ZR_DEKU_SCRUB_GROTTO_REAR, RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR }, + { RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT }, + { RC_SFM_DEKU_SCRUB_GROTTO_REAR, RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR }, + { RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT }, + { RC_LH_DEKU_SCRUB_GROTTO_LEFT, RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT }, + { RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT }, + { RC_LH_DEKU_SCRUB_GROTTO_CENTER, RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER }, + { RC_GV_DEKU_SCRUB_GROTTO_REAR, RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR }, + { RC_GV_DEKU_SCRUB_GROTTO_FRONT, RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT }, + { RC_LW_DEKU_SCRUB_GROTTO_REAR, RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR }, + { RC_LW_DEKU_SCRUB_GROTTO_FRONT, RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT }, + { RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT }, + { RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT }, + { RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER }, + { RC_GC_DEKU_SCRUB_GROTTO_LEFT, RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT }, + { RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT }, + { RC_GC_DEKU_SCRUB_GROTTO_CENTER, RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER }, + { RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT }, + { RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT }, + { RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER }, + { RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR }, + { RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT }, + { RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT }, + { RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT }, + { RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE }, + { RC_DMC_DEKU_SCRUB, RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB }, + + { RC_KF_SHOP_ITEM_1, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1 }, + { RC_KF_SHOP_ITEM_2, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_2 }, + { RC_KF_SHOP_ITEM_3, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_3 }, + { RC_KF_SHOP_ITEM_4, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_4 }, + { RC_KF_SHOP_ITEM_5, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_5 }, + { RC_KF_SHOP_ITEM_6, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_6 }, + { RC_KF_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_7 }, + { RC_KF_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_8 }, + { RC_GC_SHOP_ITEM_1, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_1 }, + { RC_GC_SHOP_ITEM_2, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_2 }, + { RC_GC_SHOP_ITEM_3, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_3 }, + { RC_GC_SHOP_ITEM_4, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_4 }, + { RC_GC_SHOP_ITEM_5, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_5 }, + { RC_GC_SHOP_ITEM_6, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_6 }, + { RC_GC_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_7 }, + { RC_GC_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_GC_SHOP_ITEM_8 }, + { RC_ZD_SHOP_ITEM_1, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_1 }, + { RC_ZD_SHOP_ITEM_2, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_2 }, + { RC_ZD_SHOP_ITEM_3, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_3 }, + { RC_ZD_SHOP_ITEM_4, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_4 }, + { RC_ZD_SHOP_ITEM_5, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_5 }, + { RC_ZD_SHOP_ITEM_6, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_6 }, + { RC_ZD_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_7 }, + { RC_ZD_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_ZD_SHOP_ITEM_8 }, + { RC_KAK_BAZAAR_ITEM_1, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_1 }, + { RC_KAK_BAZAAR_ITEM_2, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_2 }, + { RC_KAK_BAZAAR_ITEM_3, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_3 }, + { RC_KAK_BAZAAR_ITEM_4, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_4 }, + { RC_KAK_BAZAAR_ITEM_5, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_5 }, + { RC_KAK_BAZAAR_ITEM_6, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_6 }, + { RC_KAK_BAZAAR_ITEM_7, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_7 }, + { RC_KAK_BAZAAR_ITEM_8, RAND_INF_SHOP_ITEMS_KAK_BAZAAR_ITEM_8 }, + { RC_KAK_POTION_SHOP_ITEM_1, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_1 }, + { RC_KAK_POTION_SHOP_ITEM_2, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_2 }, + { RC_KAK_POTION_SHOP_ITEM_3, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_3 }, + { RC_KAK_POTION_SHOP_ITEM_4, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_4 }, + { RC_KAK_POTION_SHOP_ITEM_5, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_5 }, + { RC_KAK_POTION_SHOP_ITEM_6, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_6 }, + { RC_KAK_POTION_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_7 }, + { RC_KAK_POTION_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_KAK_POTION_SHOP_ITEM_8 }, + { RC_MARKET_BAZAAR_ITEM_1, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_1 }, + { RC_MARKET_BAZAAR_ITEM_2, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_2 }, + { RC_MARKET_BAZAAR_ITEM_3, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_3 }, + { RC_MARKET_BAZAAR_ITEM_4, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_4 }, + { RC_MARKET_BAZAAR_ITEM_5, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_5 }, + { RC_MARKET_BAZAAR_ITEM_6, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_6 }, + { RC_MARKET_BAZAAR_ITEM_7, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_7 }, + { RC_MARKET_BAZAAR_ITEM_8, RAND_INF_SHOP_ITEMS_MARKET_BAZAAR_ITEM_8 }, + { RC_MARKET_POTION_SHOP_ITEM_1, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_1 }, + { RC_MARKET_POTION_SHOP_ITEM_2, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_2 }, + { RC_MARKET_POTION_SHOP_ITEM_3, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_3 }, + { RC_MARKET_POTION_SHOP_ITEM_4, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_4 }, + { RC_MARKET_POTION_SHOP_ITEM_5, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_5 }, + { RC_MARKET_POTION_SHOP_ITEM_6, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_6 }, + { RC_MARKET_POTION_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_7 }, + { RC_MARKET_POTION_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_MARKET_POTION_SHOP_ITEM_8 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_1, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_1 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_2, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_2 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_3, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_3 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_4, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_4 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_5, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_5 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_6, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_6 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7 }, + { RC_MARKET_BOMBCHU_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8 }, +}; + extern std::vector> ShopLocationLists; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 739f991df..835f00328 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -34,7 +34,6 @@ using namespace std::literals::string_literals; std::unordered_map SpoilerfileCheckNameToEnum; std::unordered_map SpoilerfileGetNameToEnum; -std::unordered_map> EnumToSpoilerfileGetName; std::multimap, RandomizerCheckObject> checkFromActorMultimap; std::set excludedLocations; diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index a4e3873f8..de053abcc 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -46,6 +46,7 @@ class Randomizer { std::unordered_map trialsRequired; std::unordered_set masterQuestDungeons; std::unordered_map merchantPrices; + std::unordered_map> EnumToSpoilerfileGetName; static Sprite* GetSeedTexture(uint8_t index); s16 GetItemModelFromId(s16 itemId); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index 5ffe00e84..2a7a08e80 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -898,7 +898,7 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { for (auto& [randomizerCheck, locationIt] : rcObjects) { locationIt.visibleInImgui = ( (locationIt.vOrMQ != RCVORMQ_MQ) && // don't show MQ checks until we support MQ - (locationIt.rcType != RCTYPE_SHOP) && // don't show shop items until we have shopsanity + //(locationIt.rcType != RCTYPE_SHOP) && // don't show shop items until we have shopsanity (locationIt.rcType != RCTYPE_GOSSIP_STONE) && // don't show gossip stones (maybe gossipsanity will be a thing eventually?) (locationIt.rcType != RCTYPE_LINKS_POCKET) && (locationIt.rcType != RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we support shuffling them diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index d46faf286..7b366fe05 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include "3drando/item_location.hpp" extern "C" { #include @@ -30,6 +32,9 @@ void DrawQuest(ItemTrackerItem item); void DrawSong(ItemTrackerItem item); OSContPad* buttonsPressed; +std::set checkedLocations; +std::set prevCheckedLocations; +RandomizerCheck lastLocationChecked; bool shouldUpdateVectors = true; @@ -633,6 +638,205 @@ void DrawNotes(bool resizeable = false) { ImGui::EndGroup(); } + +bool HasItemBeenCollected(RandomizerCheckObject obj) { + // TODO doesn't consider vanilla/MQ? + + // return Location(obj.rc)->GetCollectionCheck().IsChecked(gSaveContext); //TODO move all the code to a static + // function in item_location + + ItemLocation* x = Location(obj.rc); + SpoilerCollectionCheck check = x->GetCollectionCheck(); + auto flag = check.flag; + auto scene = check.scene; + auto type = check.type; + + int shift; + int mask; + + switch (type) { + case SpoilerCollectionCheckType::SPOILER_CHK_ALWAYS_COLLECTED: + return true; + case SpoilerCollectionCheckType::SPOILER_CHK_BIGGORON: + return gSaveContext.bgsFlag & flag; + case SpoilerCollectionCheckType::SPOILER_CHK_CHEST: + return gSaveContext.sceneFlags[scene].chest & (1 << flag); + case SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE: + return gSaveContext.sceneFlags[scene].collect & (1 << flag); + case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM: + case SpoilerCollectionCheckType::SPOILER_CHK_COW: + case SpoilerCollectionCheckType::SPOILER_CHK_SCRUB: + return Flags_GetRandomizerInf(randomizerFlagLookup[obj.rc]); + case SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF: + // Magic to flip an index `flag` to a lookup for 16bit little endian integers. Probably an easier way..... + shift = 7 - (flag % 8) + (1 - ((flag % 16) / 8) * 8); + mask = 0x8000 >> shift; + return gSaveContext.eventChkInf[flag / 16] & mask; + case SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD: + return CHECK_FLAG_ALL(gSaveContext.eventChkInf[0x09], 0x0F); + case SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA: + return GET_GS_FLAGS(scene) & flag; + case SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE: + return gSaveContext.infTable[scene] & (0x01 << flag); + case SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF: + // Magic to flip an index `flag` to a lookup for 16bit big endian integers. Probably an easier way..... + shift = 7 - (flag % 8) + ((flag % 16) / 8) * 8; + mask = 0x8000 >> shift; + return gSaveContext.itemGetInf[flag / 16] & mask; + case SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS: + return BEANS_BOUGHT >= 10; + case SpoilerCollectionCheckType::SPOILER_CHK_MINIGAME: + if (obj.rc == RC_LH_CHILD_FISHING) + return HIGH_SCORE(HS_FISHING) & 0x400; + if (obj.rc == RC_LH_ADULT_FISHING) + return HIGH_SCORE(HS_FISHING) & 0x800; + case SpoilerCollectionCheckType::SPOILER_CHK_NONE: + return false; + case SpoilerCollectionCheckType::SPOILER_CHK_POE_POINTS: + return gSaveContext.highScores[HS_POE_POINTS] >= 1000; + default: + return false; + } + return false; +} + +void DrawLocations() { + RandomizerCheckObjects::UpdateImGuiVisibility(); + + if (ImGui::BeginTable("tableRandoChecks", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { + ImGui::TableSetupColumn("To Check", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Checked", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableHeadersRow(); + ImGui::TableNextRow(); + + // COLUMN 1 - TO CHECK LOCATIONS + ImGui::TableNextColumn(); + + static ImGuiTextFilter locationSearch; + locationSearch.Draw(); + + bool lastItemFound = false; + + ImGui::BeginChild("ChildToCheckLocations", ImVec2(0, -8)); + for (auto [rcArea, rcObjects] : RandomizerCheckObjects::GetAllRCObjectsByArea()) { + bool hasItems = false; + for (auto locationIt : rcObjects) { + if (locationIt.second.visibleInImgui && !checkedLocations.count(locationIt.second.rc) && + locationSearch.PassFilter(locationIt.second.rcSpoilerName.c_str())) { + + hasItems = true; + break; + } + } + + if (hasItems) { + ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (ImGui::TreeNode(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) { + for (auto locationIt : rcObjects) { + // If the location has its scene flag set + if (HasItemBeenCollected(locationIt.second)) { // && checkedLocations.find(locationIt.rc) != checkedLocations.end()) { + // show it as checked + checkedLocations.insert(locationIt.second.rc); + + if (!lastItemFound && + prevCheckedLocations.find(locationIt.second.rc) == prevCheckedLocations.end()) { + lastItemFound = true; + prevCheckedLocations.insert(locationIt.second.rc); + lastLocationChecked = locationIt.second.rc; + } + } + + // TODO remove the arrows? Or make it so they can be skipped or something + if (locationIt.second.visibleInImgui && !checkedLocations.count(locationIt.second.rc) && + locationSearch.PassFilter(locationIt.second.rcSpoilerName.c_str())) { + + if (ImGui::ArrowButton(std::to_string(locationIt.second.rc).c_str(), ImGuiDir_Right)) { + checkedLocations.insert(locationIt.second.rc); + } + + ImGui::SameLine(); + ImGui::Text(locationIt.second.rcShortName.c_str()); + // TODO if the check has been hinted, show the hint's value beside the check + // TODO if the check has been rendered, show its (fake) name beside the check + + // gSaveContext.itemLocations[0].get.rgID; + // Show the name of the check and the item gotten + // ImGui::Text(ItemTable(gSaveContext.itemLocations[locationIt.rc].get.rgID).GetName().english.c_str()); + // //TODO This is hardcoded english + // ImGui::Text(ItemTableManager::Instance->RetrieveItemEntry(MOD_RANDOMIZER, + // gSaveContext.itemLocations[locationIt.rc].get.rgID). + + // ImGui::Text( + // OTRGlobals::Instance->gRandomizer->getItemMessageTableID(gSaveContext.itemLocations[locationIt.rc].get.rgID) + // .GetName() + // .english.c_str()); // TODO This is hardcoded english + // gSaveContext.itemLocations[locationIt.rc].get).GetName().english.c_str() + + // name of the check is locationIt.rcShortName.c_str() + // ImGui::Text(locationIt.rcShortName.c_str()); + + // ImGui::Text(gSaveContext.itemLocations[locationIt.rc].check); + // OTRGlobals::Instance->gRandomizer->GetRandomizerGetDataFromKnownCheck(locationIt.rc)); + } + } + ImGui::TreePop(); + } + } + } + ImGui::EndChild(); + + // COLUMN 2 - CHECKED LOCATIONS + ImGui::TableNextColumn(); + ImGui::BeginChild("ChildCheckedLocations", ImVec2(0, -8)); + for (auto areaIt : RandomizerCheckObjects::GetAllRCObjectsByArea()) { + bool hasItems = false; + for (auto locationIt : areaIt.second) { + if (locationIt.second.visibleInImgui && checkedLocations.count(locationIt.second.rc)) { + hasItems = true; + break; + } + } + + if (hasItems) { + ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (ImGui::TreeNode(RandomizerCheckObjects::GetRCAreaName(areaIt.first).c_str())) { + for (auto locationIt : areaIt.second) { + auto elfound = checkedLocations.find(locationIt.second.rc); + if (locationIt.second.visibleInImgui && elfound != checkedLocations.end()) { + // If the location has its scene flag set + if (!HasItemBeenCollected(locationIt.second)) { + // show it as checked + checkedLocations.erase(locationIt.second.rc); + } else if (ImGui::ArrowButton(std::to_string(locationIt.second.rc).c_str(), + ImGuiDir_Left)) { + checkedLocations.erase(elfound); + } + ImGui::SameLine(); + std::string txt = + (lastLocationChecked == locationIt.second.rc + ? "* " + : "") + // Indicate the last location checked (before app reset at least) + locationIt.second.rcShortName + + " - "; + txt += OTRGlobals::Instance->gRandomizer + ->EnumToSpoilerfileGetName[gSaveContext.itemLocations[locationIt.second.rc] + .get.rgID] + [LANGUAGE_ENG]; // TODO Language + ImGui::Text(txt.c_str()); + // TODO GetItemObtainabilityFromRandomizerGet(rgData.rgID).CAN_OBTAIN or something to + // determine if it should say blue rupee + } + } + ImGui::TreePop(); + } + } + } + ImGui::EndChild(); + ImGui::EndTable(); + } +} + + // Windowing stuff ImVec4 ChromaKeyBackground = { 0, 0, 0, 0 }; // Float value, 1 = 255 in rgb value. void BeginFloatingWindows(std::string UniqueName, ImGuiWindowFlags flags = 0) { @@ -797,6 +1001,7 @@ void UpdateVectors() { return; } + LocationTable_Init(); dungeonRewards.clear(); dungeonRewards.insert(dungeonRewards.end(), dungeonRewardStones.begin(), dungeonRewardStones.end()); dungeonRewards.insert(dungeonRewards.end(), dungeonRewardMedallions.begin(), dungeonRewardMedallions.end()); @@ -942,6 +1147,15 @@ void DrawItemTracker(bool& open) { DrawNotes(true); EndFloatingWindows(); } + + if (CVar_GetS32("gItemTrackerLocationDisplayType", 0) == 2 && CVar_GetS32("gItemTrackerDisplayType", 0) == 0) { + if (!ImGui::Begin("Location Checklist", &open, ImGuiWindowFlags_NoFocusOnAppearing)) { + ImGui::End(); + } + ImGui::SetNextWindowSize(ImVec2(400, 1000), ImGuiCond_FirstUseEver); + DrawLocations(); + ImGui::End(); + } } } @@ -1027,6 +1241,7 @@ void DrawItemTrackerOptions(bool& open) { if (CVar_GetS32("gItemTrackerDisplayType", 0) != 1) { LabeledComboBoxRightAligned("Personal notes", "gItemTrackerNotesDisplayType", { "Hidden", "Main Window", "Seperate" }, 0); } + LabeledComboBoxRightAligned("Location Tracker", "gItemTrackerLocationDisplayType", { "Hidden", "Main Window", "Seperate" }, 1); ImGui::PopStyleVar(1); ImGui::EndTable();