diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 377ea2e75..92c13e85f 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -42,6 +42,11 @@ CustomMessage::CustomMessage(std::string english_, std::string german_, std::str position(position_) { } +CustomMessage::CustomMessage(Text text, TextBoxType type_,TextBoxPosition position_) + : english(text.GetEnglish()), german(text.GetGerman()), french(text.GetFrench()), type(type_), + position(position_) { +} + const std::string& CustomMessage::GetEnglish() const { return english; } diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 58639e423..9c5cc92ee 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -6,6 +6,7 @@ #include "../../../include/z64item.h" #include "../../../include/message_data_textbox_types.h" +#include "../randomizer/3drando/text.hpp" #undef MESSAGE_END @@ -29,6 +30,7 @@ class CustomMessage { CustomMessage() = default; CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); + CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); static std::string MESSAGE_END() ; static std::string ITEM_OBTAINED(uint8_t x) ; diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 39fa9edbc..d8c66ce7d 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -1,7 +1,15 @@ #pragma once typedef enum { - TEXT_CURSED_SKULLTULA_PEOPLE = 0x0022, + TEXT_SKULLTULA_PEOPLE_CURSE_BROKEN = 0x0021, + TEXT_SKULLTULA_PEOPLE_IM_CURSED = 0x0022, + TEXT_SKULLTULA_PEOPLE_WELL_BE_CAREFUL = 0x0023, + TEXT_SKULLTULA_PEOPLE_STARTING_TO_WEAKEN = 0x0024, + TEXT_SKULLTULA_PEOPLE_WE_LOOK_LIKE_THIS = 0x0025, + TEXT_SKULLTULA_PEOPLE_GS_TUTORIAL = 0x0026, + TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH = 0x0027, + TEXT_SKULLTULA_PEOPLE_CURSE_HAS_BEEN_BROKEN = 0x0028, + TEXT_SKULLTULA_PEOPLE_SAVING_MY_KIDS = 0x0029, TEXT_ITEM_KEY_SMALL = 0x0060, TEXT_ITEM_DUNGEON_MAP = 0x0066, TEXT_CHEST_GAME_REAL_GAMBLER = 0x006E, @@ -67,6 +75,7 @@ typedef enum { TEXT_SARIAS_SONG_CHANNELING_POWER = 0x016D, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x01B3, // 0x1yy for Navi msg range TEXT_FROGS_UNDERWATER = 0x022E, + TEXT_GF_HBA_SIGN = 0x031A, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x0346, // 0x3yy for cuttable sign range TEXT_WARP_MINUET_OF_FOREST = 0x088D, TEXT_WARP_BOLERO_OF_FIRE = 0x088E, @@ -78,9 +87,31 @@ typedef enum { TEXT_SARIA_SFM = 0x10AD, TEXT_SCRUB_STICK_UPGRADE = 0x10DC, TEXT_SCRUB_NUT_UPGRADE = 0x10DD, + TEXT_MALON_FIRST_TALK_AFTER_RESCUE = 0x2000, // RANDOTODO SKIP IN RANDO + TEXT_MALON_HOW_IS_EPONA_DOING = 0x2001, + TEXT_MALON_EPONA_LOOKS_GREAT = 0x2002, + TEXT_MALON_OBSTICLE_COURSE = 0x2003, + TEXT_MALON_EVERYONE_TURNING_EVIL = 0x204C, + TEXT_MALON_I_SING_THIS_SONG = 0x2050, + TEXT_MALON_EVERYONE_LIKED_SONG = 0x2051, + TEXT_MALON_EPONA_LIKED_SONG = 0x2052, TEXT_RANDOMIZER_GOSSIP_STONE_HINTS = 0x2053, + TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED = 0x2056, + TEXT_MALON_LINK_HAS_TIME_BUT_NO_RECORD = 0x2090, + TEXT_MALON_LINK_HAS_RECORD = 0x2091, + TEXT_MALON_FIRST_BEAT_THIS_RECORD = 0x2092, TEXT_MEDIGORON = 0x304C, TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME = 0x3052, + TEXT_BIGGORON_BETTER_AT_SMITHING = 0x3053, + TEXT_BIGGORON_BROKEN_KNIFE = 0x3054, + TEXT_BIGGORON_GET_THE_EYEDROPS = 0x3055, + TEXT_BIGGORON_IM_FINISHED_EYES_ITCHY = 0x3056, + TEXT_BIGGORON_WAITING_FOR_YOU = 0x3058, + TEXT_BIGGORON_BROUGHT_THE_EYE_DROPS = 0x3059, + TEXT_BIGGORON_THIS_IS_STIMULATING = 0x305A, + TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS = 0x305C, + TEXT_BIGGORON_YOU_ARE_IMPATIENT = 0x305D, + TEXT_BIGGORON_MY_FINEST_WORK = 0x305E, TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET = 0x3069, TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET = 0x306A, TEXT_FIRE_TEMPLE_GORON_FLAME_DANCER_SECRET = 0x306B, @@ -106,6 +137,18 @@ typedef enum { TEXT_BEAN_SALESMAN_WANT_TO_PLANT = 0x406C, TEXT_DAMPES_DIARY = 0x5003, TEXT_GRANNYS_SHOP = 0x500C, + TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK = 0x5036, + TEXT_ANJU_PLEASE_BRING_4_CUCCOS = 0x5037, + TEXT_ANJU_PLEASE_BRING_3_CUCCOS = 0x5038, + TEXT_ANJU_PLEASE_BRING_2_CUCCOS = 0x5039, + TEXT_ANJU_PLEASE_BRING_1_CUCCO = 0x503A, + TEXT_ANJU_THANKS_FOR_FINDING_MY_CUCCOS = 0x503B, + TEXT_ANJU_ROUND_THEM_UP_OR_YOULL_PAY = 0x503C, + TEXT_ANJU_DONT_TEASE_MY_CUCCOS = 0x503D, + TEXT_HBA_NOT_ON_HORSE = 0x603F, + TEXT_HBA_INITIAL_EXPLAINATION = 0x6040, + TEXT_HBA_WANT_TO_TRY_AGAIN_YES_NO = 0x6041, + TEXT_HBA_ALREADY_HAVE_1000 = 0x6042, TEXT_CARPET_SALESMAN_1 = 0x6077, TEXT_CARPET_SALESMAN_2 = 0x6078, TEXT_MARKET_GUARD_NIGHT = 0x7003, @@ -113,6 +156,11 @@ typedef enum { TEXT_SHEIK_HAVE_HOOK = 0x7010, TEXT_ALTAR_CHILD = 0x7040, TEXT_CHEST_GAME_PROCEED = 0x704C, + TEXT_GHOST_SHOP_EXPLAINATION = 0x70F4, + TEXT_GHOST_SHOP_CARD_HAS_POINTS = 0x70F5, + TEXT_GHOST_SHOP_BUY_NORMAL_POE = 0x70F6, + TEXT_GHOST_SHOP_BUY_BIG_POE = 0x70F7, + TEXT_GHOST_SHOP_1000_POINTS = 0x70F8, TEXT_ALTAR_ADULT = 0x7088, TEXT_GANONDORF = 0x70CC, TEXT_GANONDORF_NOHINT = 0x70CD, diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 4504acc9a..6540e18a4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -45,11 +45,12 @@ void HintTable_Init() { HintTable_Init_Exclude_Overworld(); HintTable_Init_Exclude_Dungeon(); + /*-------------------------- - | ALWAYS HINT TEXT | + | SOMETIMES HINT TEXT | ---------------------------*/ - hintTable[RHT_KF_LINKS_HOUSE_COW] = HintText::Always( + hintTable[RHT_KF_LINKS_HOUSE_COW] = HintText::Sometimes( { // obscure text Text{ "the #bovine bounty of a horseback hustle# gifts", @@ -61,7 +62,7 @@ void HintTable_Init() { Text{ "#Malon's obstacle course# leads to", /*french*/ "la #course à obstacle de Malon# amène à", /*spanish*/ "la #carrera de obstáculos de Malon# brinda" }); - hintTable[RHT_KAK_100_GOLD_SKULLTULA_REWARD] = HintText::Always( + hintTable[RHT_KAK_100_GOLD_SKULLTULA_REWARD] = HintText::Sometimes( { // obscure text Text{ "#100 bug badges# rewards", @@ -80,9 +81,6 @@ void HintTable_Init() { /*french*/ "détruire #100 Skulltulas d'or# donne", /*spanish*/ "exterminar #100 skulltulas doradas# revela" }); - /*-------------------------- - | SOMETIMES HINT TEXT | - ---------------------------*/ hintTable[RHT_SONG_FROM_OCARINA_OF_TIME] = HintText::Sometimes({ // obscure text Text{ "the #Ocarina of Time# teaches", /*french*/ "l'#Ocarina du Temps# est accompagné par", @@ -3434,11 +3432,11 @@ std::array AreaHintTextKeys = { RHT_GANONS_CASTLE }; -std::array conditionalAlwaysHints = { +std::array conditionalAlwaysHints = { std::make_pair(RC_MARKET_10_BIG_POES, []() { auto ctx = Rando::Context::GetInstance(); - return ctx->GetOption(RSK_BIG_POE_COUNT).Value() >= 3; + return ctx->GetOption(RSK_BIG_POE_COUNT).Value() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT); }), // Remember, the option's value being 3 means 4 are required std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { @@ -3448,7 +3446,11 @@ std::array conditionalAlwaysHints = { std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }), - std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { return false; }), + std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, + []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_BIGGORON_HINT); + }), std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, []() { auto ctx = Rando::Context::GetInstance(); @@ -3469,6 +3471,16 @@ std::array conditionalAlwaysHints = { auto ctx = Rando::Context::GetInstance(); return !ctx->GetOption(RSK_FROGS_HINT); }), + std::make_pair(RC_KF_LINKS_HOUSE_COW, + []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_MALON_HINT); + }), + std::make_pair(RC_KAK_100_GOLD_SKULLTULA_REWARD, + []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_KAK_100_SKULLS_HINT); + }), }; const HintText& Hint(const RandomizerHintTextKey hintKey) { diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index c9d6d2df5..aa1112764 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -57,6 +57,23 @@ std::array hintTypeNames = { "Junk" }; +std::array, 14> staticHintLocations = {{ + {RC_KAK_10_GOLD_SKULLTULA_REWARD, RSK_KAK_10_SKULLS_HINT}, + {RC_KAK_20_GOLD_SKULLTULA_REWARD, RSK_KAK_20_SKULLS_HINT}, + {RC_KAK_30_GOLD_SKULLTULA_REWARD, RSK_KAK_30_SKULLS_HINT}, + {RC_KAK_40_GOLD_SKULLTULA_REWARD, RSK_KAK_40_SKULLS_HINT}, + {RC_KAK_50_GOLD_SKULLTULA_REWARD, RSK_KAK_50_SKULLS_HINT}, + {RC_KAK_100_GOLD_SKULLTULA_REWARD, RSK_KAK_100_SKULLS_HINT}, + {RC_SONG_FROM_IMPA, RSK_SKIP_CHILD_ZELDA}, + {RC_ZR_FROGS_OCARINA_GAME, RSK_FROGS_HINT}, + {RC_DMT_TRADE_CLAIM_CHECK, RSK_BIGGORON_HINT}, + {RC_MARKET_10_BIG_POES, RSK_BIG_POES_HINT}, + {RC_KAK_ANJU_AS_CHILD, RSK_CHICKENS_HINT}, + {RC_KF_LINKS_HOUSE_COW, RSK_MALON_HINT}, + {RC_GF_HBA_1000_POINTS, RSK_HBA_HINT}, + {RC_GF_HBA_1500_POINTS, RSK_HBA_HINT}, + }}; + bool FilterWotHLocations(RandomizerCheck loc){ auto ctx = Rando::Context::GetInstance(); return ctx->GetItemLocation(loc)->IsWothCandidate(); @@ -280,9 +297,6 @@ Text adultAltarText; Text ganonText; Text ganonHintText; Text sheikText; -Text sariaText; -Text dampesText; -Text gregText; Text warpMinuetText; Text warpBoleroText; Text warpSerenadeText; @@ -292,14 +306,12 @@ Text warpPreludeText; std::string masterSwordHintLoc; std::string lightArrowHintLoc; -std::string dampeHintLoc; -std::string gregHintLoc; -std::string sariaHintLoc; void SetGanonText(Text text){ ganonText = text; } + std::string GetMasterSwordHintLoc() { return masterSwordHintLoc; } @@ -308,18 +320,6 @@ std::string GetLightArrowHintLoc() { return lightArrowHintLoc; } -std::string GetDampeHintLoc() { - return dampeHintLoc; -} - -std::string GetGregHintLoc() { - return gregHintLoc; -} - -std::string GetSariaHintLoc() { - return sariaHintLoc; -} - static std::vector GetEmptyGossipStones() { auto emptyGossipStones = GetEmptyLocations(Rando::StaticData::gossipStoneLocations); return emptyGossipStones; @@ -885,7 +885,7 @@ void CreateMerchantsHints() { } //RANDOTODO add Better Links Pocket and starting item handling once more starting items are added -void CreateSpecialItemHint(uint32_t item, RandomizerHintKey hintKey, std::vector hints, RandomizerHintTextKey text1, RandomizerHintTextKey text2, Text& textLoc, std::string& nameLoc, bool condition, bool yourpocket = false) { +void CreateSpecialItemHint(uint32_t item, RandomizerHintKey hintKey, std::vector hints, RandomizerHintTextKey text1, RandomizerHintTextKey text2, bool condition, bool yourpocket = false) { auto ctx = Rando::Context::GetInstance(); if(condition){ RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) { @@ -895,15 +895,11 @@ void CreateSpecialItemHint(uint32_t item, RandomizerHintKey hintKey, std::vector if (IsReachableWithout(hints,location,true)){ ctx->GetItemLocation(location)->SetAsHinted(); } - + RandomizerArea area = ctx->GetItemLocation(location)->GetArea(); - textLoc = ::Hint(text1).GetText() + ::Hint(area).GetText() + ::Hint(text2).GetText(); - nameLoc = Rando::StaticData::GetLocation(location)->GetName(); - ctx->AddHint(hintKey, AutoFormatHintText(textLoc), location, HINT_TYPE_STATIC, "Static", area); - } else { - textLoc = Text(); - nameLoc = ""; - } + ctx->AddHint(hintKey, AutoFormatHintText(::Hint(text1).GetText() + ::Hint(area).GetText() + ::Hint(text2).GetText()), + location, HINT_TYPE_STATIC, "Static", area); + } } void CreateWarpSongTexts() { @@ -1033,27 +1029,11 @@ void CreateStoneHints() { const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Value()]; std::vector distTable = hintSetting.distTable; - // Apply Special hint exclusions with no requirements - if (ctx->GetOption(RSK_KAK_10_SKULLS_HINT)){ - ctx->GetItemLocation(RC_KAK_10_GOLD_SKULLTULA_REWARD)->SetAsHinted(); - } - if (ctx->GetOption(RSK_KAK_20_SKULLS_HINT)){ - ctx->GetItemLocation(RC_KAK_20_GOLD_SKULLTULA_REWARD)->SetAsHinted(); - } - if (ctx->GetOption(RSK_KAK_30_SKULLS_HINT)){ - ctx->GetItemLocation(RC_KAK_30_GOLD_SKULLTULA_REWARD)->SetAsHinted(); - } - if (ctx->GetOption(RSK_KAK_40_SKULLS_HINT)){ - ctx->GetItemLocation(RC_KAK_40_GOLD_SKULLTULA_REWARD)->SetAsHinted(); - } - if (ctx->GetOption(RSK_KAK_50_SKULLS_HINT)){ - ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->SetAsHinted(); - } - if (ctx->GetOption(RSK_FROGS_HINT)){ - ctx->GetItemLocation(RC_ZR_FROGS_OCARINA_GAME)->SetAsHinted(); - } - if (ctx->GetOption(RSK_SKIP_CHILD_ZELDA)){ - ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetAsHinted(); + // Apply Static hint exclusions with no in-game requirements + for (int c = 0; c < staticHintLocations.size(); c++){ + if(ctx->GetOption(staticHintLocations[c].second)){ + ctx->GetItemLocation(staticHintLocations[c].first)->SetAsHinted(); + } } // Add 'always' location hints @@ -1122,9 +1102,9 @@ void CreateAllHints(){ auto ctx = Rando::Context::GetInstance(); CreateGanonAndSheikText(); CreateAltarText(); - CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, RH_DAMPES_DIARY, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, dampesText, dampeHintLoc, (bool)ctx->GetOption(RSK_DAMPES_DIARY_HINT)); - CreateSpecialItemHint(RG_GREG_RUPEE, RH_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, gregText, gregHintLoc, (bool)ctx->GetOption(RSK_GREG_HINT)); - CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, RH_SARIA, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, sariaText, sariaHintLoc, (bool)ctx->GetOption(RSK_SARIA_HINT)); + CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, RH_DAMPES_DIARY, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, (bool)ctx->GetOption(RSK_DAMPES_DIARY_HINT)); + CreateSpecialItemHint(RG_GREG_RUPEE, RH_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, (bool)ctx->GetOption(RSK_GREG_HINT)); + CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, RH_SARIA, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, (bool)ctx->GetOption(RSK_SARIA_HINT)); if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) { CreateMerchantsHints(); diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp index eb10ca0cc..ed23c1e9a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp @@ -212,7 +212,7 @@ typedef enum { //10 dungeons as GTG and GC are excluded extern std::array dungeonInfoData; -extern std::array conditionalAlwaysHints; +extern std::array conditionalAlwaysHints; extern void CreateAllHints(); extern void CreateWarpSongTexts(); @@ -221,6 +221,4 @@ void SetGanonText(Text text); std::string GetMasterSwordHintLoc(); std::string GetLightArrowHintLoc(); -std::string GetDampeHintLoc(); -std::string GetGregHintLoc(); -std::string GetSariaHintLoc(); + diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 7e73cefce..aaf9d2361 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -551,7 +551,9 @@ Rando::ItemLocation* GetItemLocation(RandomizerGet item) { // Writes the hints to the spoiler log, if they are enabled. static void WriteHints() { auto ctx = Rando::Context::GetInstance(); - int language = ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex(); + + uint8_t language = ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex(); + if (ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)) { jsonData["warpMinuetText"] = ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetForLanguage(language); jsonData["warpBoleroText"] = ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetForLanguage(language); @@ -607,17 +609,17 @@ static void WriteHints() { } if (ctx->GetOption(RSK_DAMPES_DIARY_HINT)){ jsonData["dampeText"] = ctx->GetHint(RH_DAMPES_DIARY)->GetText().GetForLanguage(language); - jsonData["dampeHintLoc"] = GetDampeHintLoc(); + jsonData["dampeHintLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_DAMPES_DIARY)->GetHintedLocation())->GetName(); jsonData["dampeRegion"] = ::Hint(ctx->GetHint(RH_DAMPES_DIARY)->GetHintedArea()).GetText().GetEnglish(); } if (ctx->GetOption(RSK_GREG_HINT)){ jsonData["gregText"] = ctx->GetHint(RH_GREG_RUPEE)->GetText().GetForLanguage(language); - jsonData["gregLoc"] = GetGregHintLoc(); + jsonData["gregLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_GREG_RUPEE)->GetHintedLocation())->GetName(); jsonData["gregRegion"] = ::Hint(ctx->GetHint(RH_GREG_RUPEE)->GetHintedArea()).GetText().GetEnglish(); } if (ctx->GetOption(RSK_SARIA_HINT)){ jsonData["sariaText"] = ctx->GetHint(RH_SARIA)->GetText().GetForLanguage(language); - jsonData["sariaHintLoc"] = GetSariaHintLoc(); + jsonData["sariaHintLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_SARIA)->GetHintedLocation())->GetName(); jsonData["sariaRegion"] = ::Hint(ctx->GetHint(RH_SARIA)->GetHintedArea()).GetText().GetEnglish(); } @@ -630,7 +632,7 @@ static void WriteHints() { std::string hintTextString = hint->GetText().GetForLanguage(language); HintType hintType = hint->GetHintType(); - std::string textStr = hintTextString; + std::string textStr = hintTextString; std::string name = Rando::StaticData::GetLocation(key)->GetName(); jsonData["hints"][name]["hint"] = textStr; jsonData["hints"][name]["distribution"] = hint->GetDistribution(); diff --git a/soh/soh/Enhancements/randomizer/3drando/text.hpp b/soh/soh/Enhancements/randomizer/3drando/text.hpp index cb6d763db..7f7d16736 100644 --- a/soh/soh/Enhancements/randomizer/3drando/text.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/text.hpp @@ -49,13 +49,13 @@ public: const std::string& GetForLanguage(uint8_t language) const { switch (language) { case LANGUAGE_ENG: - return english; + return GetEnglish(); case LANGUAGE_FRA: - return french; + return GetFrench(); case LANGUAGE_GER: - return german; + return GetGerman(); default: - return english; + return GetEnglish(); } } diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 85e5affe8..f618b3212 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -487,9 +487,21 @@ void Settings::CreateOptionDescriptions() { "location of a progressive magic meter."; mOptionDescriptions[RSK_FROGS_HINT] = "Standing near the pedestal for the frogs in Zora's River will tell you the " "reward for the frogs' ocarina game."; + mOptionDescriptions[RSK_BIGGORON_HINT] = "Talking to Biggoron will tell you the item he will give you in exchange for the Claim Check."; + mOptionDescriptions[RSK_BIG_POES_HINT] = "Talking to the Poe Collector in the Market Guardhouse while adult will tell you what you recieve for handing in Big Poes."; + mOptionDescriptions[RSK_CHICKENS_HINT] = "Talking to Anju as a child will tell you the item she will give you for delivering her Cuccos to the pen"; + mOptionDescriptions[RSK_MALON_HINT] = "Talking to Malon as adult will tell you the item on \"Link's cow\", the cow you win from beating her time on the Lon Lon Obsticle Course."; + mOptionDescriptions[RSK_HBA_HINT] = "Talking to the Horseback Archery gerudo in Gerudo Fortress, or the nearby sign, will tell you what you win for scoring 1000 and 1500 points on Horseback Archery."; mOptionDescriptions[RSK_WARP_SONG_HINTS] = "Standing near the pedestal for the frogs in Zora's River will tell you " - "the reward for the frogs' ocarina game."; + "the reward for the frogs' ocarina game."; //RANDOTODO fix this, I can't find the original right now because github search sucks mOptionDescriptions[RSK_SCRUB_TEXT_HINT] = "Business scrubs will reveal the identity of what they're selling."; + mOptionDescriptions[RSK_KAK_10_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 10 tokens will tell you the reward"; + mOptionDescriptions[RSK_KAK_20_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 20 tokens will tell you the reward"; + mOptionDescriptions[RSK_KAK_30_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 30 tokens will tell you the reward"; + mOptionDescriptions[RSK_KAK_40_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 40 tokens will tell you the reward"; + mOptionDescriptions[RSK_KAK_50_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 50 tokens will tell you the reward"; + mOptionDescriptions[RSK_KAK_100_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 100 tokens will tell you the reward"; + mOptionDescriptions[RSK_FULL_WALLETS] = "Start with a full wallet. All wallet upgrades come filled with rupees."; mOptionDescriptions[RSK_BOMBCHUS_IN_LOGIC] = "Bombchus are properly considered in logic.\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 9a5aaf858..aef7291dc 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -16,7 +16,6 @@ #endif #include #include -#include "../custom-message/CustomMessageTypes.h" #include "../item-tables/ItemTableManager.h" #include "../presets.h" #include "../../../src/overlays/actors/ovl_En_GirlA/z_en_girla.h" @@ -279,16 +278,16 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD, - CustomMessage(ctx->GetHint(RH_ALTAR_CHILD)->GetText().GetEnglish(), ctx->GetHint(RH_ALTAR_CHILD)->GetText().GetEnglish(), ctx->GetHint(RH_ALTAR_CHILD)->GetText().GetFrench(), TEXTBOX_TYPE_BLUE)); + CustomMessage(ctx->GetHint(RH_ALTAR_CHILD)->GetText(), TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT, - CustomMessage(ctx->GetHint(RH_ALTAR_ADULT)->GetText().GetEnglish(), ctx->GetHint(RH_ALTAR_ADULT)->GetText().GetEnglish(), ctx->GetHint(RH_ALTAR_ADULT)->GetText().GetFrench(), TEXTBOX_TYPE_BLUE)); + CustomMessage(ctx->GetHint(RH_ALTAR_ADULT)->GetText(), TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_GANONDORF, - CustomMessage(ctx->GetHint(RH_GANONDORF_HINT)->GetText().GetEnglish(), ctx->GetHint(RH_GANONDORF_HINT)->GetText().GetEnglish(), ctx->GetHint(RH_GANONDORF_HINT)->GetText().GetFrench())); + CustomMessage(ctx->GetHint(RH_GANONDORF_HINT)->GetText())); CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT, - CustomMessage(ctx->GetHint(RH_SARIA)->GetText().GetEnglish(), ctx->GetHint(RH_SARIA)->GetText().GetEnglish(), ctx->GetHint(RH_SARIA)->GetText().GetFrench())); + CustomMessage(ctx->GetHint(RH_SARIA)->GetText()));//RANDOTODO: Change to RH_BLANK or remove {{message}} replacment CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_SHEIK_NEED_HOOK, CustomMessage("{{message}}", "{{message}}", "{{message}}")); @@ -297,12 +296,12 @@ void Randomizer::LoadHintMessages() { CustomMessage("{{message}}", "{{message}}", "{{message}}")); CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_SARIAS_SONG_FACE_TO_FACE, - CustomMessage(ctx->GetHint(RH_SARIA)->GetText().GetEnglish(), ctx->GetHint(RH_SARIA)->GetText().GetGerman(), ctx->GetHint(RH_SARIA)->GetText().GetFrench(), TEXTBOX_TYPE_BLUE)); + CustomMessage(ctx->GetHint(RH_SARIA)->GetText(), TEXTBOX_TYPE_BLUE)); for (int i : Rando::StaticData::gossipStoneLocations) { RandomizerHintKey rhk = RandomizerHintKey(i - RC_COLOSSUS_GOSSIP_STONE + 1); CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, i, CustomMessage(ctx->GetHint(rhk)->GetText().GetEnglish(), ctx->GetHint(rhk)->GetText().GetEnglish(), ctx->GetHint(rhk)->GetText().GetFrench())); + Randomizer::hintMessageTableID, i, CustomMessage(ctx->GetHint(rhk)->GetText())); } //Extra Hints @@ -310,24 +309,20 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::randoMiscHintsTableID); CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_CURSED_SKULLTULA_PEOPLE, - CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying&%r{{params}} Spiders of the Curse%w&and I will give you my&%g{{check}}%w!", - "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem du %r{{params}} Skulltulas&%wzerstörst und ich werde dir dafür&%g{{check}} %wgeben!", - "Yeaaarrgh! Je suis maudit!^Détruit encore %r{{params}} Araignées de&la Malédiction%w et j'aurai quelque&chose à te donner!&%g({{check}})") + Randomizer::randoMiscHintsTableID, TEXT_SKULLTULA_PEOPLE_IM_CURSED, + CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying&%r{{params}} Spiders of the Curse%w&and I will give you my&%g{{item1}}%w!", + "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem du %r{{params}} Skulltulas&%wzerstörst und ich werde dir dafür&%g{{item1}} %wgeben!", + "Yeaaarrgh! Je suis maudit!^Détruit encore %r{{params}} Araignées de&la Malédiction%w et j'aurai quelque&chose à te donner!&%g({{item1}})") ); - CustomMessageManager::Instance->CreateMessage( + CustomMessageManager::Instance->CreateMessage( Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY, - CustomMessage(ctx->GetHint(RH_DAMPES_DIARY)->GetText().GetEnglish(), - ctx->GetHint(RH_DAMPES_DIARY)->GetText().GetEnglish(), - ctx->GetHint(RH_DAMPES_DIARY)->GetText().GetFrench()) + CustomMessage(ctx->GetHint(RH_DAMPES_DIARY)->GetText()) ); - CustomMessageManager::Instance->CreateMessage( + CustomMessageManager::Instance->CreateMessage( Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED, - CustomMessage(ctx->GetHint(RH_GREG_RUPEE)->GetText().GetEnglish(), - ctx->GetHint(RH_GREG_RUPEE)->GetText().GetEnglish(), - ctx->GetHint(RH_GREG_RUPEE)->GetText().GetFrench()) + CustomMessage(ctx->GetHint(RH_GREG_RUPEE)->GetText()) ); - CustomMessageManager::Instance->CreateMessage( + CustomMessageManager::Instance->CreateMessage( Randomizer::randoMiscHintsTableID, TEXT_FROGS_UNDERWATER, CustomMessage(ctx->GetHint(RH_FROGS)->GetText().GetEnglish(), ctx->GetHint(RH_FROGS)->GetText().GetGerman(), @@ -349,6 +344,111 @@ void Randomizer::LoadHintMessages() { CustomMessage(ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetEnglish(), ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetGerman(), ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetFrench())); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_SARIAS_SONG_FOREST_SOUNDS, + CustomMessage("{{message}}", "{{message}}", "{{message}}", TEXTBOX_TYPE_BLUE) + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_BIGGORON_BETTER_AT_SMITHING, + CustomMessage("Arrrrrre you here to claim my finest&%g{{item1}}%w?&Shoooooow me your %rClaim Check.%w", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_GHOST_SHOP_CARD_HAS_POINTS, + CustomMessage("You have %g\x1E\x01%r Poe Points%w!&Reach 1000 and you'll get a&%g{{item1}}%w!", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, + CustomMessage("You! Please!&Bring my Cucco's back to my pen!&I'll give you my %g{{item1}}%w!", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_MALON_OBSTICLE_COURSE, + CustomMessage("How about trying the %rObsticle Course?%w&If you beat my time I'll let you keep&my favourite cow Elsie and&her toy %g{{item1}}%w!^" + "Challenge the %rObsticle Course?&\x1B&%gLet's go&No thanks%w", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_MALON_HOW_IS_EPONA_DOING, + CustomMessage("@! You should come back &with Epona and try to beat my time&on the %rObsticle Course%w!^If you beat my time, I'll give you&my favourite %rcow%w Elsie and&her toy %g{{item1}}%w!", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_MALON_EVERYONE_TURNING_EVIL, + CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an &%rObsticle Course%w, and whoever gets&the best time would win a %rcow%w!^Elsie loves sharing her %g{{item1}}%w&with new people, It'll be fun!^...But Ingo won't let me...", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, + CustomMessage("@! You should come back in&the morning and try to beat my time&on the %rObsticle Course%w!^If you beat my time, I'll give you&my favourite %rcow%w Elsie and&her toy %g{{item1}}%w!", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_HBA_NOT_ON_HORSE, + CustomMessage("Hey, rookie!&Come back on your %rhorse%w&and take on the&%rHorseback Archery%w challenge!^Impress me with a high score of 1000&to win a %g{{item1}}%w&or score 1500 for my&%g{{item2}}%w!", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_HBA_INITIAL_EXPLAINATION, + CustomMessage("Hey, rookie!&Want to take on the&%rHorseback Archery%w challenge?^Impress me with a high score of 1000&to win a %g{{item1}}%w&or score 1500 for my&%g{{item2}}%w!\x0B", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_HBA_ALREADY_HAVE_1000, + CustomMessage("Hey, newcomer!&Want to take on the&%rHorseback Archery%w challenge?^Prove yourself to be a horsemaster&by scoring 1500 points to win &my %g{{item1}}%w!\x0B", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_GF_HBA_SIGN, + CustomMessage("%rHorseback Archery%w Range Prizes:&1000: %g{{item1}}%w&1500: %g{{item2}}%w^@'s Record: %g\x1E\x00%w", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_MALON_OBSTICLE_COURSE, + CustomMessage("How about trying your skill on the %rObsticle Course?%w& If you beat my time I'll let you keep my favourite cow Elsie and& her toy %g{{item1}}%w!&x1B&%gLet's go&No thanks%w", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_MALON_EVERYONE_TURNING_EVIL, + CustomMessage("@? Is that you? &If I ran the ranch, I'd build an %rObsticle Course%w, and whoever gets the best time would win a cow!& Elsie loves sharing her %g{{item1}}%w&with new people, It'll be fun!&...But Ingo won't let me...", + "", + "") + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, + CustomMessage("@! You should come back in the morning and try to beat my time on the %rObsticle Course%w!&If you beat my time, I'll let you keep Elsie and& her toy %g{{item1}}%w!", + "", + "") + ); + CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_NOCTURNE_OF_SHADOW, CustomMessage(ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetEnglish(), ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetGerman(), @@ -2360,6 +2460,41 @@ void RandomizerSettingsWindow::UpdateElement() { } } +CustomMessage Randomizer::ReplaceWithItemName(CustomMessage message, std::string&& toReplace, RandomizerCheck hintedCheck){ + auto ctx = Rando::Context::GetInstance(); + RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet(); + std::array itemName; + if (targetRG == RG_ICE_TRAP) { + targetRG = ctx->overrides[hintedCheck].LooksLike(); + itemName = { + ctx->overrides[hintedCheck].GetTrickName().english, + ctx->overrides[hintedCheck].GetTrickName().french, + ctx->overrides[hintedCheck].GetTrickName().english + }; + } else { + itemName = EnumToSpoilerfileGetName[targetRG]; + } + message.Replace(std::move(toReplace), std::move(itemName[0]), std::move(itemName[1]), std::move(itemName[2])); + return message; +} + + +CustomMessage Randomizer::GetMiscHintMessage(TextIDs textToGet, RandomizerCheck hintedCheck, RandomizerCheck otherCheck) { + CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, textToGet); + messageEntry = ReplaceWithItemName(messageEntry, "{{item1}}", hintedCheck); + if (otherCheck != RC_UNKNOWN_CHECK){ + messageEntry = ReplaceWithItemName(messageEntry, "{{item2}}", otherCheck); + } + return messageEntry; +} + +CustomMessage Randomizer::GetCursedSkullMessage(s16 params, RandomizerCheck hintedCheck) { + auto ctx = Rando::Context::GetInstance(); + CustomMessage messageEntry = GetMiscHintMessage(TEXT_SKULLTULA_PEOPLE_IM_CURSED, hintedCheck); + messageEntry.Replace("{{params}}", std::to_string(params*10)); + return messageEntry; +} + CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { auto ctx = Rando::Context::GetInstance(); CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, originalTextId); @@ -2461,28 +2596,6 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 te return messageEntry; } -CustomMessage Randomizer::GetCursedSkullMessage(s16 params) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_CURSED_SKULLTULA_PEOPLE); - RandomizerCheck rc = GetCheckFromActor(ACTOR_EN_SSH, SCENE_HOUSE_OF_SKULLTULA, params); - RandomizerGet itemGet = ctx->GetItemLocation(rc)->GetPlacedRandomizerGet(); - std::array itemName; - if (itemGet == RG_ICE_TRAP) { - itemGet = ctx->overrides[rc].LooksLike(); - itemName = { - std::string(ctx->overrides[rc].GetTrickName().english), - std::string(ctx->overrides[rc].GetTrickName().french), - std::string(ctx->overrides[rc].GetTrickName().english) - }; - } else { - itemName = EnumToSpoilerfileGetName[itemGet]; - } - - messageEntry.Replace("{{params}}", std::to_string(params*10)); - messageEntry.Replace("{{check}}", std::move(itemName[0]), std::move(itemName[1]), std::move(itemName[2])); - return messageEntry; -} - static const char* mapGetItemHints[3][2] = { { " It's ordinary.", " It's masterful!" }, { "&Sieht aus wie immer.", " &Man kann darauf die Worte&%r\"Master Quest\"%w entziffern..." }, diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 0949f91cb..f0e3a3440 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -12,6 +12,7 @@ #include "soh/Enhancements/randomizer/randomizer_check_objects.h" #include #include "soh/Enhancements/item-tables/ItemTableTypes.h" +#include "../custom-message/CustomMessageTypes.h" #define MAX_SEED_STRING_SIZE 1024 #define NUM_TRIFORCE_PIECE_MESSAGES 6 @@ -46,7 +47,6 @@ class Randomizer { void LoadHintMessages(); bool IsTrialRequired(RandomizerInf trial); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); - RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf); RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc); Rando::Location* GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams); @@ -59,9 +59,12 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); + CustomMessage ReplaceWithItemName(CustomMessage message, std::string&& toReplace, RandomizerCheck hintedCheck); + CustomMessage GetMiscHintMessage(TextIDs textToGet, RandomizerCheck hintedCheck, RandomizerCheck otherCheck = RC_UNKNOWN_CHECK); CustomMessage GetSariaMessage(u16 originalTextId); CustomMessage GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false); - CustomMessage GetCursedSkullMessage(s16 params); + RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); + CustomMessage GetCursedSkullMessage(s16 params, RandomizerCheck hintedCheck); CustomMessage GetGoronMessage(u16 index); CustomMessage GetMapGetItemMessageWithHint(GetItemEntry itemEntry); static void CreateCustomMessages(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 1a2d628ac..f37952001 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -3445,6 +3445,12 @@ typedef enum { RSK_KAK_30_SKULLS_HINT, RSK_KAK_40_SKULLS_HINT, RSK_KAK_50_SKULLS_HINT, + RSK_KAK_100_SKULLS_HINT, + RSK_BIGGORON_HINT, + RSK_BIG_POES_HINT, + RSK_CHICKENS_HINT, + RSK_MALON_HINT, + RSK_HBA_HINT, RSK_WARP_SONG_HINTS, RSK_SCRUB_TEXT_HINT, RSK_HINT_CLARITY, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 40f47c78b..edc8880fa 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -155,13 +155,19 @@ void Settings::CreateOptions() { mOptions[RSK_GREG_HINT] = Option::Bool("Greg the Green Rupee Hint", "gRandomizeGregHint", mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE); mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", "gRandomizeSariaHint", mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE); mOptions[RSK_FROGS_HINT] = Option::Bool("Frog Ocarina Game Hint", "gRandomizeFrogsHint", mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE); + mOptions[RSK_BIGGORON_HINT] = Option::Bool("Biggoron's Hint", "gRandomizeBiggoronHint", mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE); + mOptions[RSK_BIG_POES_HINT] = Option::Bool("Big Poes Hint", "gRandomizeBigPoesHint", mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE); + mOptions[RSK_CHICKENS_HINT] = Option::Bool("Chickens Hint", "gRandomizeChickensHint", mOptionDescriptions[RSK_CHICKENS_HINT], IMFLAG_NONE); + mOptions[RSK_MALON_HINT] = Option::Bool("Malon Hint", "gRandomizeMalonHint", mOptionDescriptions[RSK_MALON_HINT], IMFLAG_NONE); + mOptions[RSK_HBA_HINT] = Option::Bool("Horseback Archery Hint", "gRandomizeHBAHint", mOptionDescriptions[RSK_HBA_HINT], IMFLAG_NONE); mOptions[RSK_WARP_SONG_HINTS] = Option::Bool("Warp Song Hints", "gRandomizeWarpSongText", mOptionDescriptions[RSK_WARP_SONG_HINTS], IMFLAG_NONE, WidgetType::Checkbox, RO_GENERIC_ON); - mOptions[RSK_KAK_10_SKULLS_HINT] = Option::Bool("10 GS Hint", "gRandomize10GSHint", "", IMFLAG_NONE); - mOptions[RSK_KAK_20_SKULLS_HINT] = Option::Bool("20 GS Hint", "gRandomize20GSHint", "", IMFLAG_NONE); - mOptions[RSK_KAK_30_SKULLS_HINT] = Option::Bool("30 GS Hint", "gRandomize30GSHint", "", IMFLAG_NONE); - mOptions[RSK_KAK_40_SKULLS_HINT] = Option::Bool("40 GS Hint", "gRandomize40GSHint", "", IMFLAG_NONE); - mOptions[RSK_KAK_50_SKULLS_HINT] = Option::Bool("50 GS Hint", "gRandomize50GSHint"); mOptions[RSK_SCRUB_TEXT_HINT] = Option::Bool("Scrub Hint Text", "gRandomizeScrubText", mOptionDescriptions[RSK_SCRUB_TEXT_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_10_SKULLS_HINT] = Option::Bool("10 GS Hint", "gRandomize10GSHint", mOptionDescriptions[RSK_KAK_10_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_20_SKULLS_HINT] = Option::Bool("20 GS Hint", "gRandomize20GSHint", mOptionDescriptions[RSK_KAK_20_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_30_SKULLS_HINT] = Option::Bool("30 GS Hint", "gRandomize30GSHint", mOptionDescriptions[RSK_KAK_30_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_40_SKULLS_HINT] = Option::Bool("40 GS Hint", "gRandomize40GSHint", mOptionDescriptions[RSK_KAK_40_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_50_SKULLS_HINT] = Option::Bool("50 GS Hint", "gRandomize50GSHint", mOptionDescriptions[RSK_KAK_50_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_100_SKULLS_HINT] = Option::Bool("100 GS Hint", "gRandomize100GSHint", mOptionDescriptions[RSK_KAK_100_SKULLS_HINT]); // TODO: Compasses show rewards/woth, maps show dungeon mode mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", "gRandomizeBlueFireArrows", mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", "gRandomizeSunlightArrows", mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); @@ -708,16 +714,20 @@ void Settings::CreateOptions() { &mOptions[RSK_GREG_HINT], &mOptions[RSK_SARIA_HINT], &mOptions[RSK_FROGS_HINT], + &mOptions[RSK_BIGGORON_HINT], + &mOptions[RSK_BIG_POES_HINT], + &mOptions[RSK_CHICKENS_HINT], + &mOptions[RSK_MALON_HINT], + &mOptions[RSK_HBA_HINT], &mOptions[RSK_WARP_SONG_HINTS], &mOptions[RSK_SCRUB_TEXT_HINT], &mOptions[RSK_KAK_10_SKULLS_HINT], &mOptions[RSK_KAK_20_SKULLS_HINT], &mOptions[RSK_KAK_30_SKULLS_HINT], &mOptions[RSK_KAK_40_SKULLS_HINT], - &mOptions[RSK_KAK_50_SKULLS_HINT] - }, false, WidgetContainerType::SECTION, "This setting adds some hints at locations other than Gossip Stones.\n\n" - "House of Skulltula: # - Talking to a cursed House of Skulltula resident will tell you the reward" - "they will give you for obtaining that many tokens."); + &mOptions[RSK_KAK_50_SKULLS_HINT], + &mOptions[RSK_KAK_100_SKULLS_HINT] + }, false, WidgetContainerType::SECTION, "This setting adds some hints at locations other than Gossip Stones."); mOptionGroups[RSG_ITEM_POOL_HINTS_IMGUI_COLUMN] = OptionGroup::SubGroup("Item Pool & Hints", std::initializer_list{ &mOptionGroups[RSG_ITEM_POOL_HINTS_IMGUI], &mOptionGroups[RSG_EXTRA_HINTS_IMGUI], @@ -924,11 +934,17 @@ void Settings::CreateOptions() { &mOptions[RSK_SARIA_HINT], &mOptions[RSK_FROGS_HINT], &mOptions[RSK_WARP_SONG_HINTS], + &mOptions[RSK_BIGGORON_HINT], + &mOptions[RSK_BIG_POES_HINT], + &mOptions[RSK_CHICKENS_HINT], + &mOptions[RSK_MALON_HINT], + &mOptions[RSK_HBA_HINT], &mOptions[RSK_KAK_10_SKULLS_HINT], &mOptions[RSK_KAK_20_SKULLS_HINT], &mOptions[RSK_KAK_30_SKULLS_HINT], &mOptions[RSK_KAK_40_SKULLS_HINT], &mOptions[RSK_KAK_50_SKULLS_HINT], + &mOptions[RSK_KAK_100_SKULLS_HINT], &mOptions[RSK_SCRUB_TEXT_HINT], // TODO: Compasses show Reward/WOTH, Maps show Dungeon Mode, Starting Time &mOptions[RSK_DAMAGE_MULTIPLIER], @@ -1126,6 +1142,9 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:30 GS Hint", RSK_KAK_30_SKULLS_HINT }, { "Miscellaneous Settings:40 GS Hint", RSK_KAK_40_SKULLS_HINT }, { "Miscellaneous Settings:50 GS Hint", RSK_KAK_50_SKULLS_HINT }, + { "Miscellaneous Settings:50 GS Hint", RSK_KAK_100_SKULLS_HINT }, + { "Miscellaneous Settings:Biggoron's Hint", RSK_BIGGORON_HINT }, + { "Miscellaneous Settings:Big Poes Hint", RSK_BIG_POES_HINT }, { "Miscellaneous Settings:Warp Song Hints", RSK_WARP_SONG_HINTS }, { "Miscellaneous Settings:Scrub Hint Text", RSK_SCRUB_TEXT_HINT }, { "Miscellaneous Settings:Hint Distribution", RSK_HINT_DISTRIBUTION }, @@ -1646,6 +1665,24 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_HINT_CLARITY].Unhide(); mOptions[RSK_HINT_DISTRIBUTION].Unhide(); } + + if (CVarGetInteger("gRandomizeShuffleCows", RO_GENERIC_OFF)) { + mOptions[RSK_MALON_HINT].Enable(); + } else { + mOptions[RSK_MALON_HINT].Disable("Malon's hint points to a cow, so requires cows to be shuffled."); + } + + if (CVarGetInteger("gRandomizeShuffle100GSReward", RO_GENERIC_OFF)) { + mOptions[RSK_KAK_100_SKULLS_HINT].Enable(); + } else { + mOptions[RSK_KAK_100_SKULLS_HINT].Disable("There is no point to hinting 100 skulls if it is not shuffled"); + } + + if (CVarGetInteger("gRandomizeCuccosToReturn", 7) == 0) { + mOptions[RSK_CHICKENS_HINT].Disable("Anju will just give you the item instead with 0 chickens"); + } else { + mOptions[RSK_CHICKENS_HINT].Enable(); + } } void Settings::FinalizeSettings(const std::set& excludedLocations, const std::set& enabledTricks) { @@ -1927,6 +1964,18 @@ void Settings::FinalizeSettings(const std::set& excludedLocatio mOptions[RSK_KEYSANITY].SetDelayedOption(); mOptions[RSK_KEYSANITY].SetSelectedIndex(3); } + + if (!mOptions[RSK_SHUFFLE_COWS]) { + mOptions[RSK_MALON_HINT].SetSelectedIndex(RO_GENERIC_OFF); + } + + if (!mOptions[RSK_SHUFFLE_100_GS_REWARD]) { + mOptions[RSK_KAK_100_SKULLS_HINT].SetSelectedIndex(RO_GENERIC_OFF); + } + + if (mOptions[RSK_CUCCO_COUNT].Is(0)) { + mOptions[RSK_CHICKENS_HINT].SetSelectedIndex(RO_GENERIC_OFF); + } } void Settings::ParseJson(nlohmann::json spoilerFileJson) { mSeedString = spoilerFileJson["seed"].get(); @@ -2171,6 +2220,12 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_KAK_30_SKULLS_HINT: case RSK_KAK_40_SKULLS_HINT: case RSK_KAK_50_SKULLS_HINT: + case RSK_KAK_100_SKULLS_HINT: + case RSK_BIGGORON_HINT: + case RSK_BIG_POES_HINT: + case RSK_CHICKENS_HINT: + case RSK_MALON_HINT: + case RSK_HBA_HINT: case RSK_WARP_SONG_HINTS: case RSK_SCRUB_TEXT_HINT: case RSK_KEYRINGS_GERUDO_FORTRESS: diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 6f4ffe305..d39d115d9 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2589,11 +2589,12 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); - } else if (textId == TEXT_CURSED_SKULLTULA_PEOPLE) { + } else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { actorParams = GET_PLAYER(play)->targetActor->params; RandomizerSettingKey rsk = (RandomizerSettingKey)(RSK_KAK_10_SKULLS_HINT + (actorParams - 1)); if (Randomizer_GetSettingValue(rsk)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetCursedSkullMessage(actorParams); + messageEntry = OTRGlobals::Instance->gRandomizer->GetCursedSkullMessage(actorParams, + OTRGlobals::Instance->gRandomizer->GetCheckFromActor(ACTOR_EN_SSH, SCENE_HOUSE_OF_SKULLTULA, actorParams)); } } else if (Randomizer_GetSettingValue(RSK_DAMPES_DIARY_HINT) && textId == TEXT_DAMPES_DIARY) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY); @@ -2608,15 +2609,38 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId); } else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW); - } else if (textId == 0x3052 || (textId >= 0x3069 && textId <= 0x3070)) { //Fire Temple gorons + } else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } else if (Randomizer_GetSettingValue(RSK_FROGS_HINT) && textId == TEXT_FROGS_UNDERWATER) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, textId); - } else if (Randomizer_GetSettingValue(RSK_SARIA_HINT)) { - if ((gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_FROGS_UNDERWATER, RC_ZR_FROGS_OCARINA_GAME); + } else if (Randomizer_GetSettingValue(RSK_SARIA_HINT) && + (gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) { messageEntry = OTRGlobals::Instance->gRandomizer->GetSariaMessage(textId); - } + } else if (Randomizer_GetSettingValue(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS)) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_BIGGORON_BETTER_AT_SMITHING, RC_DMT_TRADE_CLAIM_CHECK); + } else if (Randomizer_GetSettingValue(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_GHOST_SHOP_CARD_HAS_POINTS, RC_MARKET_10_BIG_POES); + } else if (Randomizer_GetSettingValue(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RC_KAK_ANJU_AS_CHILD); + } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && (textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG)) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_EVERYONE_TURNING_EVIL, RC_KF_LINKS_HOUSE_COW); + } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && textId == TEXT_MALON_HOW_IS_EPONA_DOING) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_HOW_IS_EPONA_DOING, RC_KF_LINKS_HOUSE_COW); + } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && textId == TEXT_MALON_OBSTICLE_COURSE) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_OBSTICLE_COURSE, RC_KF_LINKS_HOUSE_COW); + } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RC_KF_LINKS_HOUSE_COW); + } else if (Randomizer_GetSettingValue(RSK_KAK_100_SKULLS_HINT) && textId == TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetCursedSkullMessage(10, RC_KAK_100_GOLD_SKULLTULA_REWARD); + } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_GF_HBA_SIGN) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_GF_HBA_SIGN, RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS); + } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_HBA_NOT_ON_HORSE) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_HBA_NOT_ON_HORSE, RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS); + } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_HBA_INITIAL_EXPLAINATION) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_HBA_INITIAL_EXPLAINATION, RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS); + } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_HBA_ALREADY_HAVE_1000) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_HBA_ALREADY_HAVE_1000, RC_GF_HBA_1500_POINTS); } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { diff --git a/soh/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c b/soh/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c index c6224d97f..fc814f915 100644 --- a/soh/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c +++ b/soh/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c @@ -350,12 +350,13 @@ void EnSsh_Bob(EnSsh* this, PlayState* play) { } s32 EnSsh_IsCloseToLink(EnSsh* this, PlayState* play) { - Player* player = GET_PLAYER(play); - f32 yDist; - + // #region SOH [Randomizer] automatically lower skultulla people if (IS_RANDO) { return true; } + // #endregion + Player* player = GET_PLAYER(play); + f32 yDist; if (this->stateFlags & SSH_STATE_GROUND_START) { return true; } @@ -698,19 +699,25 @@ void EnSsh_Idle(EnSsh* this, PlayState* play) { this->actor.textId = Text_GetFaceReaction(play, 0xD); if (this->actor.textId == 0) { if (this->actor.params == ENSSH_FATHER) { - if (gSaveContext.inventory.gsTokens >= 50) { - this->actor.textId = 0x29; - } else if (gSaveContext.inventory.gsTokens >= 10) { - if (Flags_GetInfTable(INFTABLE_197)) { - this->actor.textId = 0x24; - } else { - this->actor.textId = 0x25; - } + // #region SOH [Randomizer] Skip the complexity of the father's text when he should just give a hint + if (IS_RANDO && Randomizer_GetSettingValue(RSK_KAK_100_SKULLS_HINT)){ + this->actor.textId = 0x27; + // #endregion } else { - if (Flags_GetInfTable(INFTABLE_196)) { - this->actor.textId = 0x27; + if (gSaveContext.inventory.gsTokens >= 50) { + this->actor.textId = 0x29; + } else if (gSaveContext.inventory.gsTokens >= 10) { + if (Flags_GetInfTable(INFTABLE_197)) { + this->actor.textId = 0x24; + } else { + this->actor.textId = 0x25; + } } else { - this->actor.textId = 0x26; + if (Flags_GetInfTable(INFTABLE_196)) { + this->actor.textId = 0x27; + } else { + this->actor.textId = 0x26; + } } } } else {