From c9bcd64beb16e4aae8c8b70cd5b74d377d9726af Mon Sep 17 00:00:00 2001 From: Malkierian Date: Fri, 2 Jun 2023 09:10:25 -0700 Subject: [PATCH] Improvement: Additional Spoiler Hint Info (#2727) * First attempt at tracking hinted locations. Not looking promising for more than a hint tracker. * Spoiler log now generates with human-readable hinted area, type, and item for gossip stone hints. * Hints now only output location if their hint text specifically states the check. Any overworld or dungeon region hint no longer does. * Expanded gossip stone hints to include item, hinted location and area, and `RandomizerGet` names. Currently only English names. Part of this required changing `HintType` into a `typedef enum` instead of an `enum class` to allow usage in a .c filespace, and consolidating types from `randomizer_check_objects.h` to `randomizerTypes.h`. * Beginning of alter rewards information. * Step 2 of altar reward info. * Altar reward info (location and area) now writes to and reads from the spoiler log. Added a few entries to `SpoilerfileAreaNameToEnum` to accommodate area name variants from region hint names. * Streamlined altar data (only needed location name for `RandomizerCheck` translation. `RandomizerCheck` provides access to `RandomizerCheckArea` via `RandomizerCheckObject`). Added Light Arrows, Greg, and Dampe's Hookshot hint locations to write and read of the spoiler. * Fix attempts to lookup values in `hintTypeNames` as array, now uses map's `find()`. --- soh/include/z64save.h | 8 + .../Enhancements/randomizer/3drando/hints.cpp | 209 ++++++++++-------- .../Enhancements/randomizer/3drando/hints.hpp | 22 +- .../randomizer/3drando/item_location.hpp | 27 +++ .../randomizer/3drando/spoiler_log.cpp | 76 ++++++- .../Enhancements/randomizer/randomizer.cpp | 55 ++++- .../Enhancements/randomizer/randomizerTypes.h | 80 +++++++ .../randomizer/randomizer_check_objects.h | 67 ------ 8 files changed, 356 insertions(+), 188 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 041bd7027..c4ab0a681 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -155,6 +155,10 @@ typedef struct { typedef struct { RandomizerCheck check; + RandomizerCheck hintedCheck; + RandomizerGet rGet; + RandomizerCheckArea area; + HintType type; char hintText[200]; } HintLocationRando; @@ -298,6 +302,7 @@ typedef struct { /* */ EntranceOverride entranceOverrides[ENTRANCE_OVERRIDES_MAX_COUNT]; /* */ char childAltarText[250]; /* */ char adultAltarText[750]; + /* */ RandomizerCheck rewardCheck[9]; /* */ char ganonHintText[150]; /* */ char gregHintText[250]; /* */ char ganonText[250]; @@ -308,6 +313,9 @@ typedef struct { /* */ char warpRequiemText[100]; /* */ char warpNocturneText[100]; /* */ char warpPreludeText[100]; + /* */ RandomizerCheck ganonHintCheck; + /* */ RandomizerCheck gregCheck; + /* */ RandomizerCheck dampeCheck; /* */ u8 seedIcons[5]; /* */ u16 randomizerInf[9]; /* */ u16 adultTradeItems; diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 68454769a..8d6af5556 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -20,6 +20,22 @@ using namespace Logic; using namespace Settings; using namespace Trial; +std::unordered_map hintTypeNames = { + { HINT_TYPE_TRIAL, "Trial" }, + { HINT_TYPE_ALWAYS, "Always" }, + { HINT_TYPE_WOTH, "WotH" }, + { HINT_TYPE_BARREN, "Barren" }, + { HINT_TYPE_ENTRANCE, "Entrance" }, + { HINT_TYPE_SOMETIMES, "Sometimes" }, + { HINT_TYPE_RANDOM, "Random"}, + { HINT_TYPE_ITEM, "Item" }, + { HINT_TYPE_SONG, "Song" }, + { HINT_TYPE_OVERWORLD, "Overworld" }, + { HINT_TYPE_DUNGEON, "Dungeon" }, + { HINT_TYPE_JUNK, "Junk" }, + { HINT_TYPE_NAMED_ITEM, "NamedItem" }, +}; + constexpr std::array hintSettingTable{{ // Useless hints { @@ -27,19 +43,19 @@ constexpr std::array hintSettingTable{{ .dungeonsBarrenLimit = 1, .namedItemsRequired = false, .distTable = {{ - {.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Woth, .order = 3, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Barren, .order = 4, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Entrance, .order = 5, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Random, .order = 7, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Item, .order = 8, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Song, .order = 9, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Overworld, .order = 10, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Dungeon, .order = 11, .weight = 0, .fixed = 0, .copies = 0}, - {.type = HintType::Junk, .order = 12, .weight = 99, .fixed = 0, .copies = 0}, - {.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_TRIAL, .order = 1, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_ALWAYS, .order = 2, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_WOTH, .order = 3, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_BARREN, .order = 4, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_ENTRANCE, .order = 5, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_SOMETIMES, .order = 6, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_RANDOM, .order = 7, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_ITEM, .order = 8, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_SONG, .order = 9, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_OVERWORLD, .order = 10, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_DUNGEON, .order = 11, .weight = 0, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_JUNK, .order = 12, .weight = 99, .fixed = 0, .copies = 0}, + {.type = HINT_TYPE_NAMED_ITEM, .order = 13, .weight = 0, .fixed = 0, .copies = 0}, }}, }, @@ -49,19 +65,19 @@ constexpr std::array hintSettingTable{{ .dungeonsBarrenLimit = 1, .namedItemsRequired = true, .distTable = {{ - {.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Woth, .order = 3, .weight = 7, .fixed = 0, .copies = 1}, - {.type = HintType::Barren, .order = 4, .weight = 4, .fixed = 0, .copies = 1}, - {.type = HintType::Entrance, .order = 5, .weight = 6, .fixed = 0, .copies = 1}, - {.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Random, .order = 7, .weight = 12, .fixed = 0, .copies = 1}, - {.type = HintType::Item, .order = 8, .weight = 10, .fixed = 0, .copies = 1}, - {.type = HintType::Song, .order = 9, .weight = 2, .fixed = 0, .copies = 1}, - {.type = HintType::Overworld, .order = 10, .weight = 4, .fixed = 0, .copies = 1}, - {.type = HintType::Dungeon, .order = 11, .weight = 3, .fixed = 0, .copies = 1}, - {.type = HintType::Junk, .order = 12, .weight = 6, .fixed = 0, .copies = 1}, - {.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_TRIAL, .order = 1, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ALWAYS, .order = 2, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_WOTH, .order = 3, .weight = 7, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_BARREN, .order = 4, .weight = 4, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ENTRANCE, .order = 5, .weight = 6, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_SOMETIMES, .order = 6, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_RANDOM, .order = 7, .weight = 12, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ITEM, .order = 8, .weight = 10, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_SONG, .order = 9, .weight = 2, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_OVERWORLD, .order = 10, .weight = 4, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_DUNGEON, .order = 11, .weight = 3, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_JUNK, .order = 12, .weight = 6, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_NAMED_ITEM, .order = 13, .weight = 0, .fixed = 0, .copies = 1}, }}, }, @@ -71,19 +87,19 @@ constexpr std::array hintSettingTable{{ .dungeonsBarrenLimit = 1, .namedItemsRequired = true, .distTable = {{ - {.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 2}, - {.type = HintType::Woth, .order = 3, .weight = 12, .fixed = 0, .copies = 2}, - {.type = HintType::Barren, .order = 4, .weight = 12, .fixed = 0, .copies = 1}, - {.type = HintType::Entrance, .order = 5, .weight = 4, .fixed = 0, .copies = 1}, - {.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Random, .order = 7, .weight = 8, .fixed = 0, .copies = 1}, - {.type = HintType::Item, .order = 8, .weight = 8, .fixed = 0, .copies = 1}, - {.type = HintType::Song, .order = 9, .weight = 4, .fixed = 0, .copies = 1}, - {.type = HintType::Overworld, .order = 10, .weight = 6, .fixed = 0, .copies = 1}, - {.type = HintType::Dungeon, .order = 11, .weight = 6, .fixed = 0, .copies = 1}, - {.type = HintType::Junk, .order = 12, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_TRIAL, .order = 1, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ALWAYS, .order = 2, .weight = 0, .fixed = 0, .copies = 2}, + {.type = HINT_TYPE_WOTH, .order = 3, .weight = 12, .fixed = 0, .copies = 2}, + {.type = HINT_TYPE_BARREN, .order = 4, .weight = 12, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ENTRANCE, .order = 5, .weight = 4, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_SOMETIMES, .order = 6, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_RANDOM, .order = 7, .weight = 8, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ITEM, .order = 8, .weight = 8, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_SONG, .order = 9, .weight = 4, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_OVERWORLD, .order = 10, .weight = 6, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_DUNGEON, .order = 11, .weight = 6, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_JUNK, .order = 12, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_NAMED_ITEM, .order = 13, .weight = 0, .fixed = 0, .copies = 1}, }}, }, @@ -93,19 +109,19 @@ constexpr std::array hintSettingTable{{ .dungeonsBarrenLimit = 40, .namedItemsRequired = true, .distTable = {{ - {.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 2}, - {.type = HintType::Woth, .order = 3, .weight = 15, .fixed = 0, .copies = 2}, - {.type = HintType::Barren, .order = 4, .weight = 15, .fixed = 0, .copies = 1}, - {.type = HintType::Entrance, .order = 5, .weight = 10, .fixed = 0, .copies = 1}, - {.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Random, .order = 7, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::Item, .order = 8, .weight = 5, .fixed = 0, .copies = 1}, - {.type = HintType::Song, .order = 9, .weight = 2, .fixed = 0, .copies = 1}, - {.type = HintType::Overworld, .order = 10, .weight = 7, .fixed = 0, .copies = 1}, - {.type = HintType::Dungeon, .order = 11, .weight = 7, .fixed = 0, .copies = 1}, - {.type = HintType::Junk, .order = 12, .weight = 0, .fixed = 0, .copies = 1}, - {.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_TRIAL, .order = 1, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ALWAYS, .order = 2, .weight = 0, .fixed = 0, .copies = 2}, + {.type = HINT_TYPE_WOTH, .order = 3, .weight = 15, .fixed = 0, .copies = 2}, + {.type = HINT_TYPE_BARREN, .order = 4, .weight = 15, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ENTRANCE, .order = 5, .weight = 10, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_SOMETIMES, .order = 6, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_RANDOM, .order = 7, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_ITEM, .order = 8, .weight = 5, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_SONG, .order = 9, .weight = 2, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_OVERWORLD, .order = 10, .weight = 7, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_DUNGEON, .order = 11, .weight = 7, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_JUNK, .order = 12, .weight = 0, .fixed = 0, .copies = 1}, + {.type = HINT_TYPE_NAMED_ITEM, .order = 13, .weight = 0, .fixed = 0, .copies = 1}, }}, }, }}; @@ -125,6 +141,9 @@ Text warpRequiemText; Text warpNocturneText; Text warpPreludeText; +std::string ganonHintLoc; +std::string dampeHintLoc; + Text& GetChildAltarText() { return childAltarText; } @@ -173,7 +192,15 @@ Text& GetWarpPreludeText() { return warpPreludeText; } -static Area* GetHintRegion(const uint32_t area) { +std::string GetGanonHintLoc() { + return ganonHintLoc; +} + +std::string GetDampeHintLoc() { + return dampeHintLoc; +} + +Area* GetHintRegion(const uint32_t area) { std::vector alreadyChecked = {}; std::vector spotQueue = {area}; @@ -232,10 +259,13 @@ static std::vector GetAccessibleGossipStones(const uint32_t hintedLoca return accessibleGossipStones; } -static void AddHint(Text hint, const uint32_t gossipStone, const std::vector& colors = {}) { +static void AddHint(Text hint, const uint32_t gossipStone, const std::vector& colors = {}, HintType hintType = HINT_TYPE_ITEM, const uint32_t hintedLocation = NONE) { //save hints as dummy items for writing to the spoiler log NewItem(gossipStone, Item{RG_HINT, hint, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE}); Location(gossipStone)->SetPlacedItem(gossipStone); + Location(gossipStone)->SetHintedLocation(hintedLocation); + Location(gossipStone)->SetHintType(hintType); + Location(gossipStone)->SetHintedRegion(GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText().GetEnglish()); //create the in game message // uint32_t messageId = 0x400 + Location(gossipStone)->GetFlag(); @@ -274,13 +304,13 @@ static void CreateLocationHint(const std::vector& possibleHintLocation Text locationHintText = Location(hintedLocation)->GetHint().GetText(); Text itemHintText = Location(hintedLocation)->GetPlacedItem().GetHint().GetText(); Text prefix = Hint(PREFIX).GetText(); - + Text finalHint = prefix + locationHintText + " #"+itemHintText+"#."; SPDLOG_DEBUG("\tMessage: "); SPDLOG_DEBUG(finalHint.english); SPDLOG_DEBUG("\n\n"); - AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED}); + AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED}, HINT_TYPE_ITEM, hintedLocation); } static void CreateWothHint(uint8_t* remainingDungeonWothHints) { @@ -332,7 +362,7 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) { SPDLOG_DEBUG("\tMessage: "); SPDLOG_DEBUG(finalWothHint.english); SPDLOG_DEBUG("\n\n"); - AddHint(finalWothHint, gossipStone, { QM_LBLUE }); + AddHint(finalWothHint, gossipStone, { QM_LBLUE }, HINT_TYPE_WOTH, hintedLocation); } static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vector& barrenLocations) { @@ -376,7 +406,7 @@ static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vector CalculateBarrenRegions() { @@ -495,7 +525,7 @@ static void CreateTrialHints() { //make hint auto hint = Hint(PREFIX).GetText() + Hint(SIX_TRIALS).GetText(); - AddHint(hint, gossipStone, {QM_PINK}); + AddHint(hint, gossipStone, { QM_PINK }, HINT_TYPE_TRIAL); //zero trials } else if (RandomGanonsTrials && GanonsTrialsCount.Is(0)) { @@ -506,7 +536,7 @@ static void CreateTrialHints() { //make hint auto hint = Hint(PREFIX).GetText() + Hint(ZERO_TRIALS).GetText(); - AddHint(hint, gossipStone, {QM_YELLOW}); + AddHint(hint, gossipStone, { QM_YELLOW }, HINT_TYPE_TRIAL); //4 or 5 required trials } else if (GanonsTrialsCount.Is(5) || GanonsTrialsCount.Is(4)) { @@ -524,7 +554,7 @@ static void CreateTrialHints() { //make hint auto hint = Hint(PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(FOUR_TO_FIVE_TRIALS).GetText(); - AddHint(hint, gossipStone, {QM_YELLOW}); + AddHint(hint, gossipStone, { QM_YELLOW }, HINT_TYPE_TRIAL); } //1 to 3 trials } else if (GanonsTrialsCount.Value() >= 1 && GanonsTrialsCount.Value() <= 3) { @@ -541,7 +571,7 @@ static void CreateTrialHints() { //make hint auto hint = Hint(PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(ONE_TO_THREE_TRIALS).GetText(); - AddHint(hint, gossipStone, {QM_PINK}); + AddHint(hint, gossipStone, { QM_PINK }, HINT_TYPE_TRIAL); } } } @@ -556,10 +586,13 @@ void CreateGanonText() { auto lightArrowLocation = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == LIGHT_ARROWS;}); //If there is no light arrow location, it was in the player's inventory at the start + auto hint = Hint(LIGHT_ARROW_LOCATION_HINT); if (lightArrowLocation.empty()) { - ganonHintText = Hint(LIGHT_ARROW_LOCATION_HINT).GetText()+Hint(YOUR_POCKET).GetText(); + ganonHintText = hint.GetText()+Hint(YOUR_POCKET).GetText(); + ganonHintLoc = "Link's Pocket"; } else { - ganonHintText = Hint(LIGHT_ARROW_LOCATION_HINT).GetText()+GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText(); + ganonHintText = hint.GetText()+GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText(); + ganonHintLoc = Location(lightArrowLocation[0])->GetName(); } ganonHintText = ganonHintText + "!"; @@ -759,6 +792,7 @@ void CreateMerchantsHints() { void CreateDampesDiaryText() { if (!DampeHintText) { dampesText = Text(); + dampeHintLoc = ""; return; } @@ -778,6 +812,7 @@ void CreateDampesDiaryText() { }; dampesText = temp1 + area + temp2; + dampeHintLoc = Location(location)->GetName(); } void CreateGregRupeeHint() { @@ -861,7 +896,7 @@ void CreateAllHints() { uint8_t remainingDungeonBarrenHints = hintSetting.dungeonsBarrenLimit; // Add 'always' location hints - if (hintSetting.distTable[static_cast(HintType::Always)].copies > 0) { + if (hintSetting.distTable[static_cast(HINT_TYPE_ALWAYS)].copies > 0) { // Only filter locations that had a random item placed at them (e.g. don't get cow locations if shuffle cows is off) auto alwaysHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){ return ((Location(loc)->GetHint().GetType() == HintCategory::Always) || @@ -883,7 +918,7 @@ void CreateAllHints() { } //Add 'trial' location hints - if (hintSetting.distTable[static_cast(HintType::Trial)].copies > 0) { + if (hintSetting.distTable[static_cast(HINT_TYPE_TRIAL)].copies > 0) { CreateTrialHints(); } @@ -945,22 +980,6 @@ void CreateAllHints() { } } - std::array hintTypeNames = { - "Trial", - "Always", - "WotH", - "Barren", - "Entrance", - "Sometimes", - "Random", - "Item", - "Song", - "Overworld", - "Dungeon", - "Junk", - "NamedItem", - }; - //while there are still gossip stones remaining while (FilterFromPool(gossipStoneLocations, [](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == NONE;}).size() != 0) { //TODO: fixed hint types @@ -973,39 +992,39 @@ void CreateAllHints() { HintType type = RandomElement(remainingHintTypes, true); SPDLOG_DEBUG("Attempting to make hint of type: "); - SPDLOG_DEBUG(hintTypeNames[static_cast(type)]); + SPDLOG_DEBUG(hintTypeNames.find(type)->second); SPDLOG_DEBUG("\n"); //create the appropriate hint for the type - if (type == HintType::Woth) { + if (type == HINT_TYPE_WOTH) { CreateWothHint(&remainingDungeonWothHints); - } else if (type == HintType::Barren) { + } else if (type == HINT_TYPE_BARREN) { CreateBarrenHint(&remainingDungeonBarrenHints, barrenLocations); - } else if (type == HintType::Sometimes){ + } else if (type == HINT_TYPE_SOMETIMES){ std::vector sometimesHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetHint().GetType() == HintCategory::Sometimes && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());}); CreateLocationHint(sometimesHintLocations); - } else if (type == HintType::Random) { + } else if (type == HINT_TYPE_RANDOM) { CreateRandomLocationHint(); - } else if (type == HintType::Item) { + } else if (type == HINT_TYPE_ITEM) { CreateGoodItemHint(); - } else if (type == HintType::Song){ + } else if (type == HINT_TYPE_SONG){ std::vector songHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->IsCategory(Category::cSong) && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());}); CreateLocationHint(songHintLocations); - } else if (type == HintType::Overworld){ + } else if (type == HINT_TYPE_OVERWORLD){ std::vector overworldHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->IsOverworld() && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());}); CreateLocationHint(overworldHintLocations); - } else if (type == HintType::Dungeon){ + } else if (type == HINT_TYPE_DUNGEON){ std::vector dungeonHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->IsDungeon() && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());}); CreateLocationHint(dungeonHintLocations); - } else if (type == HintType::Junk) { + } else if (type == HINT_TYPE_JUNK) { CreateJunkHint(); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp index fe5a29805..ccf949975 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp @@ -10,23 +10,6 @@ #include "settings.hpp" #include -enum class HintType { - Trial, - Always, - Woth, //Way of the Hero - Barren, - Entrance, - Sometimes, - Random, - Item, - Song, - Overworld, - Dungeon, - Junk, - NamedItem, - MaxCount, -}; - struct HintDistributionSetting { HintType type; uint8_t order; @@ -36,7 +19,7 @@ struct HintDistributionSetting { }; struct HintSetting { - using DistributionTable = std::array(HintType::MaxCount)>; + using DistributionTable = std::array(HINT_TYPE_MAX)>; uint8_t dungeonsWothLimit; uint8_t dungeonsBarrenLimit; @@ -239,3 +222,6 @@ Text& GetWarpSerenadeText(); Text& GetWarpRequiemText(); Text& GetWarpNocturneText(); Text& GetWarpPreludeText(); + +std::string GetDampeHintLoc(); +std::string GetGanonHintLoc(); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.hpp b/soh/soh/Enhancements/randomizer/3drando/item_location.hpp index 8d9c576d7..3d6858e50 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.hpp @@ -347,6 +347,30 @@ public: return isHintable; } + void SetHintedLocation(uint32_t location) { + hintedLocation = location; + } + + uint32_t GetHintedLocation() { + return hintedLocation; + } + + void SetHintType(HintType type) { + hintType = type; + } + + HintType GetHintType() { + return hintType; + } + + void SetHintedRegion (std::string region) { + hintedRegion = region; + } + + std::string GetHintedRegion() { + return hintedRegion; + } + void SetAsHintable() { isHintable = true; } @@ -465,6 +489,9 @@ private: std::vector categories; bool addedToPool = false; uint32_t placedItem = NONE; + uint32_t hintedLocation = NONE; + HintType hintType; + std::string hintedRegion; uint32_t delayedItem = NONE; Option excludedOption = Option::Bool(name, {"Include", "Exclude"}, {"", ""}); uint16_t price = 0; diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index bebddfd97..9b0112559 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -11,6 +11,8 @@ #include "utils.hpp" #include "shops.hpp" #include "hints.hpp" +#include "pool_functions.hpp" +#include "soh/Enhancements/randomizer/randomizer_check_objects.h" #include #include @@ -32,6 +34,11 @@ using json = nlohmann::json; json jsonData; +std::map hintedLocations; + +extern std::unordered_map hintTypeNames; +extern std::array hintCategoryNames; +extern Area* GetHintRegion(uint32_t); namespace { std::string placementtxt; @@ -645,6 +652,10 @@ std::string AutoFormatHintTextString(std::string unformattedHintTextString) { return textStr; } +ItemLocation* GetItemLocation(uint32_t item) { + return Location(FilterFromPool(allLocations, [item](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == item;})[0]); +} + // Writes the hints to the spoiler log, if they are enabled. static void WriteHints(int language) { std::string unformattedGanonText; @@ -665,8 +676,8 @@ static void WriteHints(int language) { jsonData["warpRequiemText"] = GetWarpRequiemText().GetEnglish(); jsonData["warpNocturneText"] = GetWarpNocturneText().GetEnglish(); jsonData["warpPreludeText"] = GetWarpPreludeText().GetEnglish(); - jsonData["childAltarText"] = GetChildAltarText().GetEnglish(); - jsonData["adultAltarText"] = GetAdultAltarText().GetEnglish(); + jsonData["childAltar"]["hintText"] = GetChildAltarText().GetEnglish(); + jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetEnglish(); break; case 2: unformattedGanonText = GetGanonText().GetFrench(); @@ -679,11 +690,36 @@ static void WriteHints(int language) { jsonData["warpRequiemText"] = GetWarpRequiemText().GetFrench(); jsonData["warpNocturneText"] = GetWarpNocturneText().GetFrench(); jsonData["warpPreludeText"] = GetWarpPreludeText().GetFrench(); - jsonData["childAltarText"] = GetChildAltarText().GetFrench(); - jsonData["adultAltarText"] = GetAdultAltarText().GetFrench(); + jsonData["childAltar"]["hintText"] = GetChildAltarText().GetFrench(); + jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetFrench(); break; } + ItemLocation* emeraldLoc = GetItemLocation(KOKIRI_EMERALD); + ItemLocation* rubyLoc = GetItemLocation(GORON_RUBY); + ItemLocation* sapphireLoc = GetItemLocation(ZORA_SAPPHIRE); + std::string emeraldArea; + std::string erubyArea; + std::string sapphireArea; + + jsonData["childAltar"]["rewards"]["emeraldLoc"] = emeraldLoc->GetName(); + jsonData["childAltar"]["rewards"]["rubyLoc"] = rubyLoc->GetName(); + jsonData["childAltar"]["rewards"]["sapphireLoc"] = sapphireLoc->GetName(); + + ItemLocation* forestMedallionLoc = GetItemLocation(FOREST_MEDALLION); + ItemLocation* fireMedallionLoc = GetItemLocation(FIRE_MEDALLION); + ItemLocation* waterMedallionLoc = GetItemLocation(WATER_MEDALLION); + ItemLocation* shadowMedallionLoc = GetItemLocation(SHADOW_MEDALLION); + ItemLocation* spiritMedallionLoc = GetItemLocation(SPIRIT_MEDALLION); + ItemLocation* lightMedallionLoc = GetItemLocation(LIGHT_MEDALLION); + + jsonData["adultAltar"]["rewards"]["forestMedallionLoc"] = forestMedallionLoc->GetName(); + jsonData["adultAltar"]["rewards"]["fireMedallionLoc"] = fireMedallionLoc->GetName(); + jsonData["adultAltar"]["rewards"]["waterMedallionLoc"] = waterMedallionLoc->GetName(); + jsonData["adultAltar"]["rewards"]["shadowMedallionLoc"] = shadowMedallionLoc->GetName(); + jsonData["adultAltar"]["rewards"]["spiritMedallionLoc"] = spiritMedallionLoc->GetName(); + jsonData["adultAltar"]["rewards"]["lightMedallionLoc"] = lightMedallionLoc->GetName(); + std::string ganonText = AutoFormatHintTextString(unformattedGanonText); std::string ganonHintText = AutoFormatHintTextString(unformattedGanonHintText); std::string dampesText = AutoFormatHintTextString(unformattedDampesText); @@ -691,8 +727,11 @@ static void WriteHints(int language) { jsonData["ganonText"] = ganonText; jsonData["ganonHintText"] = ganonHintText; + jsonData["ganonHintLoc"] = GetGanonHintLoc(); jsonData["dampeText"] = dampesText; + jsonData["dampeHintLoc"] = GetDampeHintLoc(); jsonData["gregText"] = gregText; + jsonData["gregLoc"] = GetItemLocation(GREG_RUPEE)->GetName(); if (Settings::GossipStoneHints.Is(HINTS_NO_HINTS)) { return; @@ -700,6 +739,7 @@ static void WriteHints(int language) { for (const uint32_t key : gossipStoneLocations) { ItemLocation* location = Location(key); + ItemLocation* hintedLocation = Location(location->GetHintedLocation()); std::string unformattedHintTextString; switch (language) { case 0: @@ -711,8 +751,20 @@ static void WriteHints(int language) { break; } + HintType hintType = location->GetHintType(); + std::string textStr = AutoFormatHintTextString(unformattedHintTextString); - jsonData["hints"][location->GetName()] = textStr; + jsonData["hints"][location->GetName()]["hint"] = textStr; + jsonData["hints"][location->GetName()]["type"] = hintTypeNames.find(hintType)->second; + if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_NAMED_ITEM) { + jsonData["hints"][location->GetName()]["item"] = hintedLocation->GetPlacedItemName().GetEnglish(); + if (hintType != HINT_TYPE_NAMED_ITEM) { + jsonData["hints"][location->GetName()]["location"] = hintedLocation->GetName(); + } + } + if (hintType != HINT_TYPE_TRIAL && hintType != HINT_TYPE_JUNK) { + jsonData["hints"][location->GetName()]["area"] = location->GetHintedRegion(); + } } } @@ -747,6 +799,9 @@ static void WriteAllLocations(int language) { if (location->HasScrubsanityPrice() || location->HasShopsanityPrice()) { jsonData["locations"][location->GetName()]["price"] = location->GetPrice(); } + if (location->IsHintedAt()) { + hintedLocations.emplace(location->GetHintKey(), location); + } if (location->GetPlacedItemKey() == ICE_TRAP) { switch (language) { @@ -768,6 +823,16 @@ static void WriteAllLocations(int language) { } } +//static void WriteHintData(int language) { +// for (auto [hintKey, item_location] : hintedLocations) { +// ItemLocation *hint_location = Location(hintKey); +// jsonData["hints"][hint_location->GetName()] = { { "text", hint_location->GetPlacedItemName().GetEnglish() }, +// { "item", item_location->GetPlacedItemName().GetEnglish() }, +// { "itemLocation", item_location->GetName() }, +// { "locationArea", item_location->GetParentRegionKey() } }; +// } +//} + const char* SpoilerLog_Write(int language) { auto spoilerLog = tinyxml2::XMLDocument(false); spoilerLog.InsertEndChild(spoilerLog.NewDeclaration()); @@ -806,6 +871,7 @@ const char* SpoilerLog_Write(int language) { WriteHints(language); WriteShuffledEntrances(); WriteAllLocations(language); + //WriteHintData(language); if (!std::filesystem::exists(LUS::Context::GetPathRelativeToAppDirectory("Randomizer"))) { std::filesystem::create_directory(LUS::Context::GetPathRelativeToAppDirectory("Randomizer")); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3cb8373ed..61f6340a2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -31,11 +31,16 @@ extern "C" uint32_t ResourceMgr_IsGameMasterQuest(); extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum); +extern std::map rcAreaNames; +extern std::unordered_map hintTypeNames; + using json = nlohmann::json; using namespace std::literals::string_literals; std::unordered_map SpoilerfileCheckNameToEnum; std::unordered_map SpoilerfileGetNameToEnum; +std::unordered_map SpoilerfileAreaNameToEnum; +std::unordered_map SpoilerfileHintTypeNameToEnum; std::multimap, RandomizerCheckObject> checkFromActorMultimap; std::set excludedLocations; @@ -123,6 +128,18 @@ Randomizer::Randomizer() { item.GetName().french, }; } + for (auto area : rcAreaNames) { + SpoilerfileAreaNameToEnum[area.second] = area.first; + } + SpoilerfileAreaNameToEnum["Inside Ganon's Castle"] = RCAREA_GANONS_CASTLE; + SpoilerfileAreaNameToEnum["the Lost Woods"] = RCAREA_LOST_WOODS; + SpoilerfileAreaNameToEnum["the Market"] = RCAREA_MARKET; + SpoilerfileAreaNameToEnum["the Graveyard"] = RCAREA_GRAVEYARD; + SpoilerfileAreaNameToEnum["Haunted Wasteland"] = RCAREA_WASTELAND; + SpoilerfileAreaNameToEnum["outside Ganon's Castle"] = RCAREA_HYRULE_CASTLE; + for (auto [type, name] : hintTypeNames) { + SpoilerfileHintTypeNameToEnum[name] = type; + } } Sprite* Randomizer::GetSeedTexture(uint8_t index) { @@ -1226,20 +1243,30 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) { json spoilerFileJson; spoilerFileStream >> spoilerFileJson; - std::string childAltarJsonText = spoilerFileJson["childAltarText"].get(); + std::string childAltarJsonText = spoilerFileJson["childAltar"]["hintText"].get(); std::string formattedChildAltarText = FormatJsonHintText(childAltarJsonText); strncpy(gSaveContext.childAltarText, formattedChildAltarText.c_str(), sizeof(gSaveContext.childAltarText) - 1); gSaveContext.childAltarText[sizeof(gSaveContext.childAltarText) - 1] = 0; + gSaveContext.rewardCheck[0] = SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["emeraldLoc"]]; + gSaveContext.rewardCheck[1] = SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["rubyLoc"]]; + gSaveContext.rewardCheck[2] = SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["sapphireLoc"]]; - std::string adultAltarJsonText = spoilerFileJson["adultAltarText"].get(); + std::string adultAltarJsonText = spoilerFileJson["adultAltar"]["hintText"].get(); std::string formattedAdultAltarText = FormatJsonHintText(adultAltarJsonText); strncpy(gSaveContext.adultAltarText, formattedAdultAltarText.c_str(), sizeof(gSaveContext.adultAltarText) - 1); gSaveContext.adultAltarText[sizeof(gSaveContext.adultAltarText) - 1] = 0; + gSaveContext.rewardCheck[3] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["forestMedallionLoc"]]; + gSaveContext.rewardCheck[4] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["fireMedallionLoc"]]; + gSaveContext.rewardCheck[5] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["waterMedallionLoc"]]; + gSaveContext.rewardCheck[6] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["shadowMedallionLoc"]]; + gSaveContext.rewardCheck[7] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"]]; + gSaveContext.rewardCheck[8] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"]]; std::string ganonHintJsonText = spoilerFileJson["ganonHintText"].get(); std::string formattedGanonHintJsonText = FormatJsonHintText(ganonHintJsonText); strncpy(gSaveContext.ganonHintText, formattedGanonHintJsonText.c_str(), sizeof(gSaveContext.ganonHintText) - 1); gSaveContext.ganonHintText[sizeof(gSaveContext.ganonHintText) - 1] = 0; + gSaveContext.ganonHintCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["ganonHintLoc"]]; std::string ganonJsonText = spoilerFileJson["ganonText"].get(); std::string formattedGanonJsonText = FormatJsonHintText(ganonJsonText); @@ -1250,11 +1277,13 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) { std::string formattedDampeJsonText = FormatJsonHintText(dampeJsonText); strncpy(gSaveContext.dampeText, formattedDampeJsonText.c_str(), sizeof(gSaveContext.dampeText) - 1); gSaveContext.dampeText[sizeof(gSaveContext.dampeText) - 1] = 0; + gSaveContext.dampeCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"]]; std::string gregJsonText = spoilerFileJson["gregText"].get(); std::string formattedGregJsonText = FormatJsonHintText(gregJsonText); strncpy(gSaveContext.gregHintText, formattedGregJsonText.c_str(), sizeof(gSaveContext.gregHintText) - 1); gSaveContext.gregHintText[sizeof(gSaveContext.gregHintText) - 1] = 0; + gSaveContext.gregCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["gregLoc"]]; std::string warpMinuetJsonText = spoilerFileJson["warpMinuetText"].get(); strncpy(gSaveContext.warpMinuetText, warpMinuetJsonText.c_str(), sizeof(gSaveContext.warpMinuetText) - 1); @@ -1284,8 +1313,28 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) { int index = 0; for (auto it = hintsJson.begin(); it != hintsJson.end(); ++it) { gSaveContext.hintLocations[index].check = SpoilerfileCheckNameToEnum[it.key()]; + auto hintInfo = it.value(); + if (hintInfo["location"].is_null()) { + gSaveContext.hintLocations[index].hintedCheck = RC_UNKNOWN_CHECK; + } else { + gSaveContext.hintLocations[index].hintedCheck = SpoilerfileCheckNameToEnum[hintInfo["location"]]; + } + if (hintInfo["item"].is_null()) { + gSaveContext.hintLocations[index].rGet = RG_NONE; + } else { + gSaveContext.hintLocations[index].rGet = SpoilerfileGetNameToEnum[hintInfo["item"]]; + } + gSaveContext.hintLocations[index].type = SpoilerfileHintTypeNameToEnum[hintInfo["type"]]; - std::string hintMessage = FormatJsonHintText(it.value()); + if (gSaveContext.hintLocations[index].type == HINT_TYPE_TRIAL) { + gSaveContext.hintLocations[index].area = RCAREA_GANONS_CASTLE; + } else if (gSaveContext.hintLocations[index].type == HINT_TYPE_JUNK) { + gSaveContext.hintLocations[index].area = RCAREA_INVALID; + } else { + gSaveContext.hintLocations[index].area = SpoilerfileAreaNameToEnum[hintInfo["area"]]; + } + + std::string hintMessage = FormatJsonHintText(hintInfo["hint"]); size_t maxHintTextSize = sizeof(gSaveContext.hintLocations[index].hintText); strncpy(gSaveContext.hintLocations[index].hintText, hintMessage.c_str(), maxHintTextSize - 1); gSaveContext.hintLocations[index].hintText[maxHintTextSize - 1] = 0; diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index f15978392..1f5dbf2e9 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -20,6 +20,86 @@ typedef struct { uint8_t id; } Sprite; +typedef enum { + HINT_TYPE_TRIAL, + HINT_TYPE_ALWAYS, + HINT_TYPE_WOTH, // Way of the Hero + HINT_TYPE_BARREN, + HINT_TYPE_ENTRANCE, + HINT_TYPE_SOMETIMES, + HINT_TYPE_RANDOM, + HINT_TYPE_ITEM, + HINT_TYPE_SONG, + HINT_TYPE_OVERWORLD, + HINT_TYPE_DUNGEON, + HINT_TYPE_JUNK, + HINT_TYPE_NAMED_ITEM, + HINT_TYPE_MAX +} HintType; + +// Check types based on main settings +typedef enum { + RCTYPE_STANDARD, // Base set of rando checks + RCTYPE_SKULL_TOKEN, // Gold Skulltulas + RCTYPE_COW, // Cows + RCTYPE_ADULT_TRADE, // Adult trade quest checks + RCTYPE_FROG_SONG, // Frog song purple rupee checks + RCTYPE_MAP_COMPASS, // Maps/Compasses + RCTYPE_SMALL_KEY, // Small Keys + RCTYPE_GF_KEY, // Gerudo Fortress Keys + RCTYPE_BOSS_KEY, // Boss Keys + RCTYPE_GANON_BOSS_KEY, // Ganon's boss key + RCTYPE_SHOP, // shops + RCTYPE_SCRUB, // scrubs + RCTYPE_MERCHANT, // merchants + RCTYPE_CHEST_GAME, // todo replace this once we implement it, just using it to exclude for now + RCTYPE_LINKS_POCKET, // todo this feels hacky + RCTYPE_GOSSIP_STONE, + RCTYPE_SONG_LOCATION, // Song locations + RCTYPE_BOSS_HEART_OR_OTHER_REWARD, // Boss heart container or lesser dungeon rewards (lens, ice arrow) + RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps) + RCTYPE_OCARINA, // Ocarina locations +} RandomizerCheckType; + +typedef enum { RCVORMQ_VANILLA, RCVORMQ_MQ, RCVORMQ_BOTH } RandomizerCheckVanillaOrMQ; + +typedef enum { + RCAREA_KOKIRI_FOREST, + RCAREA_LOST_WOODS, + RCAREA_SACRED_FOREST_MEADOW, + RCAREA_HYRULE_FIELD, + RCAREA_LAKE_HYLIA, + RCAREA_GERUDO_VALLEY, + RCAREA_GERUDO_FORTRESS, + RCAREA_WASTELAND, + RCAREA_DESERT_COLOSSUS, + RCAREA_MARKET, + RCAREA_HYRULE_CASTLE, + RCAREA_KAKARIKO_VILLAGE, + RCAREA_GRAVEYARD, + RCAREA_DEATH_MOUNTAIN_TRAIL, + RCAREA_GORON_CITY, + RCAREA_DEATH_MOUNTAIN_CRATER, + RCAREA_ZORAS_RIVER, + RCAREA_ZORAS_DOMAIN, + RCAREA_ZORAS_FOUNTAIN, + RCAREA_LON_LON_RANCH, + RCAREA_DEKU_TREE, + RCAREA_DODONGOS_CAVERN, + RCAREA_JABU_JABUS_BELLY, + RCAREA_FOREST_TEMPLE, + RCAREA_FIRE_TEMPLE, + RCAREA_WATER_TEMPLE, + RCAREA_SPIRIT_TEMPLE, + RCAREA_SHADOW_TEMPLE, + RCAREA_BOTTOM_OF_THE_WELL, + RCAREA_ICE_CAVERN, + RCAREA_GERUDO_TRAINING_GROUND, + RCAREA_GANONS_CASTLE, + // If adding any more areas, Check Tracker will need a refactor + RCAREA_INVALID +} RandomizerCheckArea; + typedef enum { RC_UNKNOWN_CHECK, RC_LINKS_POCKET, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h index 428751c0a..c35017162 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h @@ -7,73 +7,6 @@ enum ActorID : int; enum SceneID : int; -// Check types based on main settings -typedef enum { - RCTYPE_STANDARD, // Base set of rando checks - RCTYPE_SKULL_TOKEN, // Gold Skulltulas - RCTYPE_COW, // Cows - RCTYPE_ADULT_TRADE, // Adult trade quest checks - RCTYPE_FROG_SONG, // Frog song purple rupee checks - RCTYPE_MAP_COMPASS, // Maps/Compasses - RCTYPE_SMALL_KEY, // Small Keys - RCTYPE_GF_KEY, // Gerudo Fortress Keys - RCTYPE_BOSS_KEY, // Boss Keys - RCTYPE_GANON_BOSS_KEY, // Ganon's boss key - RCTYPE_SHOP, // shops - RCTYPE_SCRUB, // scrubs - RCTYPE_MERCHANT, // merchants - RCTYPE_CHEST_GAME, //todo replace this once we implement it, just using it to exclude for now - RCTYPE_LINKS_POCKET, //todo this feels hacky - RCTYPE_GOSSIP_STONE, - RCTYPE_SONG_LOCATION, // Song locations - RCTYPE_BOSS_HEART_OR_OTHER_REWARD, // Boss heart container or lesser dungeon rewards (lens, ice arrow) - RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps) - RCTYPE_OCARINA, // Ocarina locations -} RandomizerCheckType; - -typedef enum { - RCVORMQ_VANILLA, - RCVORMQ_MQ, - RCVORMQ_BOTH -} RandomizerCheckVanillaOrMQ; - -typedef enum { - RCAREA_KOKIRI_FOREST, - RCAREA_LOST_WOODS, - RCAREA_SACRED_FOREST_MEADOW, - RCAREA_HYRULE_FIELD, - RCAREA_LAKE_HYLIA, - RCAREA_GERUDO_VALLEY, - RCAREA_GERUDO_FORTRESS, - RCAREA_WASTELAND, - RCAREA_DESERT_COLOSSUS, - RCAREA_MARKET, - RCAREA_HYRULE_CASTLE, - RCAREA_KAKARIKO_VILLAGE, - RCAREA_GRAVEYARD, - RCAREA_DEATH_MOUNTAIN_TRAIL, - RCAREA_GORON_CITY, - RCAREA_DEATH_MOUNTAIN_CRATER, - RCAREA_ZORAS_RIVER, - RCAREA_ZORAS_DOMAIN, - RCAREA_ZORAS_FOUNTAIN, - RCAREA_LON_LON_RANCH, - RCAREA_DEKU_TREE, - RCAREA_DODONGOS_CAVERN, - RCAREA_JABU_JABUS_BELLY, - RCAREA_FOREST_TEMPLE, - RCAREA_FIRE_TEMPLE, - RCAREA_WATER_TEMPLE, - RCAREA_SPIRIT_TEMPLE, - RCAREA_SHADOW_TEMPLE, - RCAREA_BOTTOM_OF_THE_WELL, - RCAREA_ICE_CAVERN, - RCAREA_GERUDO_TRAINING_GROUND, - RCAREA_GANONS_CASTLE, - //If adding any more areas, Check Tracker will need a refactor - RCAREA_INVALID -} RandomizerCheckArea; - #define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) #define RC_OBJECT(rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, rc_shortname, rc_spoilername) \