diff --git a/.gitmodules b/.gitmodules index 12a5f3b..a0bdeab 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "Z3DR"] path = Z3DR url = https://github.com/Z3DR/mm3dr.git - branch = dev + branch = dev \ No newline at end of file diff --git a/Z3DR b/Z3DR index c08d2cf..0a68f83 160000 --- a/Z3DR +++ b/Z3DR @@ -1 +1 @@ -Subproject commit c08d2cf3121e33be9d3510e0ef419b693b79eef8 +Subproject commit 0a68f8318eb45ba7fa32706ff3988fd0f6851648 diff --git a/source/dungeon.cpp b/source/dungeon.cpp index fb704cd..fce0ac5 100644 --- a/source/dungeon.cpp +++ b/source/dungeon.cpp @@ -237,6 +237,7 @@ std::vector DungeonInfo::GetEveryLocation() const { STONE_TOWER_TEMPLE_BOSS_KEY_CHEST, STONE_TOWER_TEMPLE_ARMOS_ROOM_CHEST, STONE_TOWER_TEMPLE_DEATH_ARMOS_ROOM_CHEST, + STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST, STONE_TOWER_TEMPLE_BRIDGE_SWITCH_CHEST, STONE_TOWER_TEMPLE_UPDRAFT_ROOM_CHEST, STONE_TOWER_TEMPLE_GIANTS_MASK_CHEST, diff --git a/source/hint_list.cpp b/source/hint_list.cpp index 73884ba..7a64f11 100644 --- a/source/hint_list.cpp +++ b/source/hint_list.cpp @@ -1792,6 +1792,8 @@ void HintTable_Init() { Text{"a rocky temple contains", "**FRENCH**", "**SPANISH**"}}); hintTable[STONE_TOWER_TEMPLE_DEATH_ARMOS_ROOM_CHEST] = HintText::Exclude({ Text{"a rocky temple contains", "**FRENCH**", "**SPANISH**"}}); + hintTable[STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST] = HintText::Exclude({ + Text{"a rocky temple contains", "**FRENCH**", "**SPANISH**"}}); hintTable[STONE_TOWER_TEMPLE_LIGHT_ARROW_CHEST] = HintText::Exclude({ Text{"a rocky temple contains", "**FRENCH**", "**SPANISH**"}}); hintTable[STONE_TOWER_TEMPLE_GIANTS_MASK_CHEST] = HintText::Exclude({ diff --git a/source/hints.cpp b/source/hints.cpp index 41ba718..729bcf0 100644 --- a/source/hints.cpp +++ b/source/hints.cpp @@ -449,10 +449,10 @@ void CreateTingleHintText() { Text ikanaMap = Text{"#"}+ItemTable(Location(TINGLE_GBC_ST)->GetPlacedItemKey()).GetName(); // {"English", "French", "Spanish"} - Text priceFive = {" ##5 Rupees#&", " ##5 Rubis#&", ""}; - Text priceTwenty = {" ##20 Rupees#&", " ##20 Rubis#&", ""}; - Text priceForty = {" ##40 Rupees#", " ##40 Rubis#", ""}; - Text leaveShop = {"&#No thanks#", "&#Non merci#", ""}; + Text priceFive = {" ##5 Rupees#&", " ##5 Rubis#&", " ##5 rupias#&"}; + Text priceTwenty = {" ##20 Rupees#&", " ##20 Rubis#&", " ##20 rupias#&"}; + Text priceForty = {" ##40 Rupees#", " ##40 Rubis#", " ##40 rupias#"}; + Text leaveShop = {"&#No thanks#", "&#Non merci#", "&#No, gracias#"}; Text tingleTextClockTown = clockTownMap+priceFive+woodfallMap+priceForty+leaveShop; Text tingleTextWoodfall = woodfallMap+priceTwenty+snowHeadMap+priceForty+leaveShop; @@ -505,85 +505,93 @@ static Text BuildDoorText(const ItemKey itemKey) { void CreateClockTowerDoorHints() { // Create hint text Text ocarinaHint = Text{ - //English - "Hey, didn't you have some sort of #musical instrument#?&If I know the Skull Kid, I bet he hid it at ", - //French - "Dis, t'avais pas un #instrument de musique#?&Je parie que Skull Kid, l'a caché vers ", - //Spanish - "" + /*English*/"Hey, didn't you have some sort of #musical instrument#?&If I know the Skull Kid, I bet he hid it at ", + /*French */"Dis, t'avais pas un #instrument de musique#?&Je parie que Skull Kid, l'a caché vers ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(OCARINA_OF_TIME); Text odolwaHint = Text{ - //English - "There's one with a #crown# and #jewellery# said to be found at ", - //French - "Y'en a un avec une #couronne# et des #bijoux# situé vers ", - //Spanish - "" + /*English*/"There's one with a #crown# and #jewellery# said to be found at ", + /*French */"Y'en a un avec une #couronne# et des #bijoux# situé vers ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(ODOLWAS_REMAINS); Text gohtHint = Text{ - //English - "Another #extremely sturdy# one with #huge horns# at ", - //French - "Un autre #très solide# avec des #cornes immenses# situé vers ", - //Spanish - "" + /*English*/"Another #extremely sturdy# one with #huge horns# at ", + /*French */"Un autre #très solide# avec des #cornes immenses# situé vers ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(GOHTS_REMAINS); Text gyorgHint = Text{ - //English - "One with #giant fins# and #razor sharp teeth# at ", - //French - "Un qui a des #nageoires géantes# et #dents acérées# situé vers ", - //Spanish - "" + /*English*/"One with #giant fins# and #razor sharp teeth# at ", + /*French */"Un qui a des #nageoires géantes# et #dents acérées# situé vers ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(GYORGS_REMAINS); Text twinmoldHint = Text{ - //English - "And one with #three eyes# and #enormous mandibles# at ", - //French - "Et un avec #trois yeux# et d'#énormes mandibules# situé vers ", - //Spanish - "" + /*English*/"And one with #three eyes# and #enormous mandibles# at ", + /*French */"Et un avec #trois yeux# et d'#énormes mandibules# situé vers ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(TWINMOLDS_REMAINS); if (StartingOdolwaRemains.Value() == 1) { odolwaHint = Text{ - //English - "There's one with a #crown# and #jewellery# said to be found in ", - //French - "Y'en a un avec une #couronne# et des #bijoux# situé dans ", - //Spanish - "" + /*English*/"There's one with a #crown# and #jewellery# said to be found in ", + /*French */"Y'en a un avec une #couronne# et des #bijoux# situé dans ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(ODOLWAS_REMAINS); } if (StartingGohtRemains.Value() == 1) { gohtHint = Text{ - //English - "Another #extremely sturdy# one with #huge horns# in ", - //French - "Un autre #très solide# avec des #cornes immenses# situé dans ", - //Spanish - "" + /*English*/"Another #extremely sturdy# one with #huge horns# in ", + /*French */"Un autre #très solide# avec des #cornes immenses# situé dans ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(GOHTS_REMAINS); } if (StartingGyorgRemains.Value() == 1) { gyorgHint = Text{ - //English - "One with #giant fins# and #razor sharp teeth# in ", - //French - "Un qui a des #nageoires géantes# et #dents acérées# situé dans ", - //Spanish - "" + /*English*/"One with #giant fins# and #razor sharp teeth# in ", + /*French */"Un qui a des #nageoires géantes# et #dents acérées# situé dans ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(GYORGS_REMAINS); } if (StartingTwinmoldRemains.Value() == 1){ twinmoldHint = Text{ - //English - "And one with #three eyes# and #enormous mandibles# in ", - //French - "Et un avec #trois yeux# et d'#énormes mandibules# situé dans ", - //Spanish - "" + /*English*/"And one with #three eyes# and #enormous mandibles# in ", + /*French */"Et un avec #trois yeux# et d'#énormes mandibules# situé dans ", + /*Spanish*/"**SPANISH** " }+BuildDoorText(TWINMOLDS_REMAINS); } + Text remainsNeededHint = { + /*English*/"The rumours say having #all four# causes something good to happen.", + /*French */"D'après les rumeurs, si on a #les quatre#, un truc bien va se produire.", + /*Spanish*/"**SPANISH**" + }; + switch (4 - MoonRemainsRequired.Value()) { + case 0: + remainsNeededHint = { + /*English*/"I think collecting them would just be a #waste of time# though.", + /*French */"Mais à mon avis, les collectionner ne serait qu'une #perte de temps#.", + /*Spanish*/"**SPANISH**" + }; + break; + case 1: + remainsNeededHint = { + /*English*/"The rumours say having #just one# is enough to make something good happen.", + /*French */"D'après les rumeurs, il suffit d'en avoir #un seul# pour qu'un truc bien se produise.", + /*Spanish*/"**SPANISH**" + }; + break; + case 2: + remainsNeededHint = { + /*English*/"The rumours say having #half of them# causes something good to happen.", + /*French */"D'après les rumeurs, si on en a #la moitié#, un truc bien va se produire.", + /*Spanish*/"**SPANISH**" + }; + break; + case 3: + remainsNeededHint = { + /*English*/"The rumours say having #three of them# causes something good to happen.", + /*French */"D'après les rumeurs, si on en a #trois#, un truc bien va se produire.", + /*Spanish*/"**SPANISH**" + }; + break; + } CustomMessages::CreateMessage(0x0630, (StartingOcarina.Value() == 0) ? 0x8000 : 0x8002, 0x3FFFFFFF, 0x0FF0211, {"Rooftop access strictly prohibited!&(Enforceable until #midnight# on the&#eve# of the carnival.)^" @@ -599,7 +607,53 @@ void CreateClockTowerDoorHints() { CustomMessages::CreateMessage(0x8003, 0x8004, 0x3FFFFFFF, 0x15D0000, {odolwaHint.GetNAEnglish().c_str()}, {QM_GREEN, QM_GREEN, QM_RED}, {}, {}, 0x0, false, false); CustomMessages::CreateMessage(0x8004, 0x8005, 0x3FFFFFFF, 0x15E0000, {gohtHint.GetNAEnglish().c_str()}, {QM_MAGENTA, QM_MAGENTA, QM_RED}, {}, {}, 0x0, false, false); CustomMessages::CreateMessage(0x8005, 0x8006, 0x3FFFFFFF, 0x15F0000, {gyorgHint.GetNAEnglish().c_str()}, {QM_CYAN, QM_CYAN, QM_RED}, {}, {}, 0x0, false, false); - CustomMessages::CreateMessage(0x8006, 0xFFFF, 0x3FFFFFFF, 0x0600000, {twinmoldHint.GetNAEnglish().c_str()}, {QM_YELLOW, QM_YELLOW, QM_RED}, {}, {}, 0x0, false, false); + CustomMessages::CreateMessage(0x8006, 0x8007, 0x3FFFFFFF, 0x1600000, {twinmoldHint.GetNAEnglish().c_str()}, {QM_YELLOW, QM_YELLOW, QM_RED}, {}, {}, 0x0, false, false); + CustomMessages::CreateMessage(0x8007, 0xFFFF, 0x3FFFFFFF, 0x0FF0000, {remainsNeededHint.GetNAEnglish().c_str()}, {QM_RED}, {}, {}, 0x0, false, false); +} + +void CreateMoonChildHint() { + // Create textbox with main hint + Text moonChildHint = { + /*English*/"^Come back with &#four Bosses' Remains#...", + /*French */"^Reviens avec les &#restes de quatre boss#...", + /*Spanish*/"^**SPANISH**" + }; + switch (4 - MajoraRemainsRequired.Value()) { + case 1: + moonChildHint = { + /*English*/"^Come back with &#one Boss's Remains#...", + /*French */"^Reviens avec les &#restes d'un boss#...", + /*Spanish*/"**SPANISH**" + }; + break; + case 2: + moonChildHint = { + /*English*/"^Come back with &#two Bosses' Remains#...", + /*French */"^Reviens avec les &#restes de deux boss#...", + /*Spanish*/"**SPANISH**" + }; + break; + case 3: + moonChildHint = { + /*English*/"^Come back with &#three Bosses' Remains#...", + /*French */"^Reviens avec les &#restes de trois boss#...", + /*Spanish*/"**SPANISH**" + }; + break; + } + + // Add opening and closing textboxes to hint + moonChildHint = Text{ + /*English*/"You...^You don't have many masks...do you?", + /*French */"Toi...^Tu n'as pas beaucoup de masques... n'est-ce pas ?", + /*Spanish*/"**SPANISH**" + }+moonChildHint+Text{ + /*English*/"^Then we can play.", + /*French */"^Alors, on pourra jouer.", + /*Spanish*/"^**SPANISH**" + }; + + CustomMessages::CreateMessage(0x6144, 0xFFFF, 0x3FFFFFFF, 0x0FF0020, {moonChildHint.GetNAEnglish().c_str()}, {QM_RED}, {}, {}, 0x0, false, false); } //insert the required number into the hint and set the singular/plural form diff --git a/source/include/hints.hpp b/source/include/hints.hpp index c81f027..6933142 100644 --- a/source/include/hints.hpp +++ b/source/include/hints.hpp @@ -166,4 +166,5 @@ class HintText { extern void CreateAllHints(); extern void CreateTingleHintText(); -extern void CreateClockTowerDoorHints(); \ No newline at end of file +extern void CreateClockTowerDoorHints(); +extern void CreateMoonChildHint(); \ No newline at end of file diff --git a/source/include/keys.hpp b/source/include/keys.hpp index b6bab7b..3ed8eab 100644 --- a/source/include/keys.hpp +++ b/source/include/keys.hpp @@ -582,6 +582,7 @@ typedef enum { STONE_TOWER_TEMPLE_BRIDGE_SWITCH_CHEST, STONE_TOWER_TEMPLE_UPDRAFT_ROOM_CHEST, STONE_TOWER_TEMPLE_DEATH_ARMOS_ROOM_CHEST, + STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST, STONE_TOWER_TEMPLE_LIGHT_ARROW_CHEST, STONE_TOWER_TEMPLE_GIANTS_MASK_CHEST, ST_SF_MIRROR_SUN_BLOCK, diff --git a/source/include/logic.hpp b/source/include/logic.hpp index 33ff078..4169175 100644 --- a/source/include/logic.hpp +++ b/source/include/logic.hpp @@ -332,6 +332,9 @@ namespace Logic { extern bool PostedKafeiLetter; extern bool CanGoToMoon; + extern bool RemainsForMoon; + extern bool RemainsForMajora; + extern u8 CurrentRemains; void UpdateHelpers(); bool CanPlay(bool song); diff --git a/source/include/setting_descriptions.hpp b/source/include/setting_descriptions.hpp index 0c4df3d..9f3bc89 100644 --- a/source/include/setting_descriptions.hpp +++ b/source/include/setting_descriptions.hpp @@ -228,6 +228,7 @@ extern string_view compassShowWotHDesc; extern string_view skipHMSCutsceneDesc; extern string_view skipDarmaniCutsceneDesc; extern string_view skipMikauCutsceneDesc; +extern string_view skipGiantCutsceneDesc; extern string_view skipBombersMinigameDesc; extern string_view NARegionDesc; extern string_view EURegionDesc; @@ -235,4 +236,6 @@ extern string_view VersionDesc; extern string_view LanguageDesc; extern string_view fastMaskDesc; extern string_view disableBotebookAnimation; -extern string_view repeatItemsOnTokensDesc; \ No newline at end of file +extern string_view repeatItemsOnTokensDesc; +extern string_view MoonRemainsRequiredDesc; +extern string_view MajoraRemainsRequiredDesc; \ No newline at end of file diff --git a/source/include/settings.hpp b/source/include/settings.hpp index bd8e477..9887a05 100644 --- a/source/include/settings.hpp +++ b/source/include/settings.hpp @@ -416,6 +416,8 @@ namespace Settings { extern Option StrayFairysanity; extern Option ShuffleRewards; extern Option ShuffleHeartContainers; + extern Option MoonRemainsRequired; + extern Option MajoraRemainsRequired; extern std::vector shuffleItemOptions; //ItemPool Settings diff --git a/source/item_location.cpp b/source/item_location.cpp index 01bf7e4..f59a39c 100644 --- a/source/item_location.cpp +++ b/source/item_location.cpp @@ -302,6 +302,7 @@ void LocationTable_Init() { locationTable[STONE_TOWER_TEMPLE_BRIDGE_SWITCH_CHEST] = ItemLocation::Chest (0x16, 0x01, true, "Stone Tower Temple Bridge Switch Chest", STONE_TOWER_TEMPLE_BRIDGE_SWITCH_CHEST, STONE_TOWER_TEMPLE_SMALL_KEY, {Category::cStoneTowerTemple, Category::cVanillaSmallKey,Category::cDayOne}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER ); locationTable[STONE_TOWER_TEMPLE_UPDRAFT_ROOM_CHEST] = ItemLocation::Chest (0x18, 0x04, true, "Stone Tower Temple Updraft Room Chest", STONE_TOWER_TEMPLE_UPDRAFT_ROOM_CHEST, STONE_TOWER_TEMPLE_SMALL_KEY, {Category::cStoneTowerTemple, Category::cVanillaSmallKey,Category::cDayOne}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER ); locationTable[STONE_TOWER_TEMPLE_DEATH_ARMOS_ROOM_CHEST] = ItemLocation::Chest (0x18, 0x05, true, "Stone Tower Temple Death Armos Room Chest", STONE_TOWER_TEMPLE_DEATH_ARMOS_ROOM_CHEST, STONE_TOWER_TEMPLE_SMALL_KEY, {Category::cStoneTowerTemple, Category::cVanillaSmallKey,Category::cDayOne}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER ); + locationTable[STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST] = ItemLocation::Chest (0x16, 0x05, true, "Stone Tower Temple Upright Death Armos Room Chest", STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST, STONE_TOWER_TEMPLE_SMALL_KEY, {Category::cNull}, SpoilerCollectionCheckGroup::GROUP_NO_GROUP); locationTable[STONE_TOWER_TEMPLE_LIGHT_ARROW_CHEST] = ItemLocation::Chest (0x16, 0x1B, true, "Stone Tower Temple Light Arrow Chest", STONE_TOWER_TEMPLE_LIGHT_ARROW_CHEST, LIGHT_ARROWS, {Category::cStoneTowerTemple,Category::cChest ,Category::cDayOne, Category::cMainInventory}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER ); locationTable[STONE_TOWER_TEMPLE_GIANTS_MASK_CHEST] = ItemLocation::Chest (0x36, 0x00, false, "Stone Tower Temple Giant's Mask Chest", STONE_TOWER_TEMPLE_GIANTS_MASK_CHEST, GIANTS_MASK, {Category::cStoneTowerTemple,Category::cChest, Category::cVanillaMask ,Category::cDayOne}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER ); @@ -1232,9 +1233,12 @@ void CreateItemOverrides() { PlaceItemInLocation(SOUTHERN_SWAMP_SCRUB_PURCHASE_CLEAR, loc19->GetPlacedItemKey()); PlaceItemInLocation(SOUTHERN_SWAMP_SCRUB_TRADE_CLEAR, loc20->GetPlacedItemKey()); PlaceItemInLocation(SWAMP_TOURIST_CENTER_ROOF_CLEAR, loc21->GetPlacedItemKey()); + //For the upright version of this chest which is normally obtained in the inverted stone tower - obtainable with goron missile + auto loc23 = Location(STONE_TOWER_TEMPLE_DEATH_ARMOS_ROOM_CHEST); + PlaceItemInLocation(STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST, loc23->GetPlacedItemKey()); //Curiosity Shop Big Bomb Bag is same as Bomb Shop Big Bomb Bag - auto loc22 = Location(W_CLOCK_TOWN_BIG_BOMB_BAG_BUY); - PlaceItemInLocation(W_CLOCK_TOWN_CURIOSITY_BOMB_BAG, loc22->GetPlacedItemKey()); + auto loc24 = Location(W_CLOCK_TOWN_BIG_BOMB_BAG_BUY); + PlaceItemInLocation(W_CLOCK_TOWN_CURIOSITY_BOMB_BAG, loc24->GetPlacedItemKey()); for (LocationKey locKey : allLocations) { auto loc = Location(locKey); diff --git a/source/item_pool.cpp b/source/item_pool.cpp index 7643815..6ccc0f9 100644 --- a/source/item_pool.cpp +++ b/source/item_pool.cpp @@ -912,6 +912,7 @@ void GenerateItemPool() { PlaceItemInLocation(SOUTHERN_SWAMP_SCRUB_PURCHASE_CLEAR, BLUE_RUPEE); PlaceItemInLocation(SOUTHERN_SWAMP_SCRUB_TRADE_CLEAR, BLUE_RUPEE); PlaceItemInLocation(SWAMP_TOURIST_CENTER_ROOF_CLEAR, BLUE_RUPEE); + PlaceItemInLocation(STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST, BLUE_RUPEE); //Check Non Dungeon Settings //OCARINA SHUFFLE diff --git a/source/location_access.cpp b/source/location_access.cpp index edce9dd..1a2c5ef 100644 --- a/source/location_access.cpp +++ b/source/location_access.cpp @@ -587,7 +587,7 @@ void AreaTable_Init() { areaTable[CLOCK_TOWER_ROOF] = Area("Clock Tower Roof", "Clock Tower Roof", CLOCK_TOWER_ROOF, { //Events - EventAccess(&CanGoToMoon, {[]{return OdolwaRemains && GohtRemains && GyorgRemains && TwinmoldRemains && CanPlay(OathToOrder);}}), + EventAccess(&CanGoToMoon, {[]{return RemainsForMoon && CanPlay(OathToOrder);}}), }, { //Locations @@ -2856,6 +2856,7 @@ void AreaTable_Init() { }, { //Locations + LocationAccess(STONE_TOWER_TEMPLE_UPRIGHT_DEATH_ARMOS_ROOM_CHEST, {[] {return GoronMask && Pictobox && Bow;}}), }, { //Exits @@ -3725,7 +3726,7 @@ void AreaTable_Init() { { //Exits Entrance(S_CLOCK_TOWN, {[]{return true;}}), - Entrance(THE_MOON_BOSS_ROOM, {[]{return true;}}), + Entrance(THE_MOON_BOSS_ROOM, {[]{return RemainsForMajora;}}), Entrance(THE_MOON_DEKU_TRIAL, {[]{return (TotalMaskCount() >= 1);}}), Entrance(THE_MOON_GORON_TRIAL, {[]{return (TotalMaskCount() >= 2);}}), Entrance(THE_MOON_ZORA_TRIAL, {[]{return (TotalMaskCount() >= 3);}}), diff --git a/source/logic.cpp b/source/logic.cpp index 1faf094..2561737 100644 --- a/source/logic.cpp +++ b/source/logic.cpp @@ -339,6 +339,10 @@ namespace Logic { u8 PlacedMasks = 0; u8 PiecesOfHeart = 0; u8 HeartContainers = 0; + + bool RemainsForMoon = false; + bool RemainsForMajora = false; + u8 CurrentRemains = 0; bool CanPlay(bool song) { return Ocarina && song; @@ -552,6 +556,12 @@ namespace Logic { AllMasks = (PostmansHat && AllNightMask && BlastMask && StoneMask && GreatFairyMask && KeatonMask && BremenMask && BunnyHood && DonGerosMask && MaskOfScents && RomanisMask && CircusLeadersMask && KafeisMask && CouplesMask && MaskOfTruth && KamarosMask && GibdosMask && GarosMask && CaptainsHat && GiantsMask); + + //Calculate number of masks needed + CurrentRemains = OdolwaRemains + GohtRemains + GyorgRemains + TwinmoldRemains; + RemainsForMoon = ((4 - MoonRemainsRequired.Value()) <= CurrentRemains); + RemainsForMajora = ((4 - MajoraRemainsRequired.Value()) <= CurrentRemains); + } bool EventsUpdated() { @@ -883,6 +893,10 @@ namespace Logic { PlacedMasks = 0; PiecesOfHeart = 0; HeartContainers = 0; + + CurrentRemains = 0; + RemainsForMoon = 0; + RemainsForMajora = 0; } } diff --git a/source/playthrough.cpp b/source/playthrough.cpp index c3d3b42..06d628b 100644 --- a/source/playthrough.cpp +++ b/source/playthrough.cpp @@ -79,6 +79,7 @@ namespace Playthrough { } CreateTingleHintText(); CreateClockTowerDoorHints(); + CreateMoonChildHint(); playthroughLocations.clear(); wothLocations.clear(); diff --git a/source/setting_descriptions.cpp b/source/setting_descriptions.cpp index c1143e2..f1e7e9d 100644 --- a/source/setting_descriptions.cpp +++ b/source/setting_descriptions.cpp @@ -633,6 +633,7 @@ const std::vector GlitchDifficulties{"Novice", "Intermediate", "Adv string_view skipHMSCutsceneDesc = "Skips the initial Happy Mask Salesman's cutscenes"; // string_view skipDarmaniCutsceneDesc = "Skips the Song of Healing Cutscene for Darmani"; // string_view skipMikauCutsceneDesc = "Skips the Song of Healing Cutscene for Mikau"; // +string_view skipGiantCutsceneDesc = "Skips the cutscene of the giants catching the moon";// /*------------------------------ // | REGION OPTIONS | // ------------------------------*/ // @@ -652,4 +653,11 @@ string_view LanguageDesc = "Selected region differs from console mean ------------------------------*/ // string_view repeatItemsOnTokensDesc = "Allows items potentially needed more than once \n" // "such as Title Deeds and Anju & Kafei quest items \n"// - "to be placed on gold skulltula drops"; // \ No newline at end of file + "to be placed on gold skulltula drops"; // +/*------------------------------ // +| MOON AND MAJORA REQUIREMENTS | // +------------------------------*/ // +string_view MoonRemainsRequiredDesc = "Select the number of Boss Remains needed to \n" // + "enter the moon by playing Oath to Order on the roof";// +string_view MajoraRemainsRequiredDesc="Select the number of Boss Remains needed to \n" // + "Fight Majora"; // \ No newline at end of file diff --git a/source/settings.cpp b/source/settings.cpp index a217fa8..204036c 100644 --- a/source/settings.cpp +++ b/source/settings.cpp @@ -341,6 +341,8 @@ namespace Settings { Option StrayFairysanity = Option::U8("Stray Fairies", { "Vanilla", "Start With", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }, { fairyVanilla, fairyStartWith, fairyOwnDungeon, fairyAnyDungeon, fairyOverworld, fairyAnywhere }, OptionCategory::Setting, (u8)StrayFairySanitySetting::STRAYFAIRYSANITY_VANILLA); Option ShuffleRewards = Option::U8("Dungeon Rewards", { "Vanilla", "Any Dungeon", "Overworld", "Anywhere" }, { shuffleRewardsEndOfDungeon, shuffleRewardsAnyDungeon, shuffleRewardsOverworld, shuffleRewardsAnywhere }); Option ShuffleHeartContainers = Option::Bool("Heart Containers", { "Vanilla", "Random"}, { shuffleHeartContainersDesc }); + Option MoonRemainsRequired = Option::U8("Moon Requirements", {"Vanilla", "3", "2", "1", "0"}, { MoonRemainsRequiredDesc }, OptionCategory::Setting); + Option MajoraRemainsRequired = Option::U8("Majora Requirements",{"Vanilla", "3", "2", "1", "0"}, { MajoraRemainsRequiredDesc }, OptionCategory::Setting); std::vectordungeonSettingsOptions = { &RandomizeDungeon, @@ -350,6 +352,8 @@ namespace Settings { //&StrayFairysanity, &ShuffleRewards, &ShuffleHeartContainers, + &MoonRemainsRequired, + &MajoraRemainsRequired, }; //Item Pool Settings @@ -459,10 +463,12 @@ namespace Settings { Option SkipHMSCutscenes = Option::Bool("Skip HMS Cutscenes", {"Don't Skip", "Skip"}, {skipHMSCutsceneDesc}); Option SkipDarmaniCutscenes = Option::Bool("Skip Darmani Cutscenes", {"Don't Skip", "Skip"}, {skipDarmaniCutsceneDesc}); Option SkipMikauCutscenes = Option::Bool("Skip Mikau Cutscenes", {"Don't Skip", "Skip"}, {skipMikauCutsceneDesc}); + Option SkipGiantCutscenes = Option::Bool("Skip Giants Cutscene", {"Don't Skip", "Skip"}, {skipGiantCutsceneDesc}); std::vector