diff --git a/soh/assets/objects/object_link_boy/object_link_boy.h b/soh/assets/objects/object_link_boy/object_link_boy.h
index 084225d14..13ad2b3a1 100644
--- a/soh/assets/objects/object_link_boy/object_link_boy.h
+++ b/soh/assets/objects/object_link_boy/object_link_boy.h
@@ -309,8 +309,8 @@ static const ALIGN_ASSET(2) char gLinkAdultHookshotDesignTex[] = dgLinkAdultHook
#define dgLinkAdultHookshotChainTex "__OTR__objects/object_link_boy/gLinkAdultHookshotChainTex"
static const ALIGN_ASSET(2) char gLinkAdultHookshotChainTex[] = dgLinkAdultHookshotChainTex;
-#define dgLinkAdultHookshotRedicleVtx "__OTR__objects/object_link_boy/gLinkAdultHookshotRedicleVtx"
-static const ALIGN_ASSET(2) char gLinkAdultHookshotRedicleVtx[] = dgLinkAdultHookshotRedicleVtx;
+#define dgLinkAdultHookshotReticleVtx "__OTR__objects/object_link_boy/gLinkAdultHookshotReticleVtx"
+static const ALIGN_ASSET(2) char gLinkAdultHookshotReticleVtx[] = dgLinkAdultHookshotReticleVtx;
#define dgLinkAdultHookshotReticleTex "__OTR__objects/object_link_boy/gLinkAdultHookshotReticleTex"
static const ALIGN_ASSET(2) char gLinkAdultHookshotReticleTex[] = dgLinkAdultHookshotReticleTex;
diff --git a/soh/assets/xml/GC_MQ_D/objects/object_link_boy.xml b/soh/assets/xml/GC_MQ_D/objects/object_link_boy.xml
index 8500b975b..60b9e0984 100644
--- a/soh/assets/xml/GC_MQ_D/objects/object_link_boy.xml
+++ b/soh/assets/xml/GC_MQ_D/objects/object_link_boy.xml
@@ -209,7 +209,7 @@
-
+
diff --git a/soh/assets/xml/GC_MQ_PAL_F/objects/object_link_boy.xml b/soh/assets/xml/GC_MQ_PAL_F/objects/object_link_boy.xml
index 02075c999..6351af505 100644
--- a/soh/assets/xml/GC_MQ_PAL_F/objects/object_link_boy.xml
+++ b/soh/assets/xml/GC_MQ_PAL_F/objects/object_link_boy.xml
@@ -209,7 +209,7 @@
-
+
diff --git a/soh/assets/xml/GC_NMQ_D/objects/object_link_boy.xml b/soh/assets/xml/GC_NMQ_D/objects/object_link_boy.xml
index 7c0014699..5342d5271 100644
--- a/soh/assets/xml/GC_NMQ_D/objects/object_link_boy.xml
+++ b/soh/assets/xml/GC_NMQ_D/objects/object_link_boy.xml
@@ -209,7 +209,7 @@
-
+
diff --git a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_link_boy.xml b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_link_boy.xml
index 02075c999..6351af505 100644
--- a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_link_boy.xml
+++ b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_link_boy.xml
@@ -209,7 +209,7 @@
-
+
diff --git a/soh/assets/xml/N64_PAL_10/objects/object_link_boy.xml b/soh/assets/xml/N64_PAL_10/objects/object_link_boy.xml
index 02075c999..6351af505 100644
--- a/soh/assets/xml/N64_PAL_10/objects/object_link_boy.xml
+++ b/soh/assets/xml/N64_PAL_10/objects/object_link_boy.xml
@@ -209,7 +209,7 @@
-
+
diff --git a/soh/assets/xml/N64_PAL_11/objects/object_link_boy.xml b/soh/assets/xml/N64_PAL_11/objects/object_link_boy.xml
index 02075c999..6351af505 100644
--- a/soh/assets/xml/N64_PAL_11/objects/object_link_boy.xml
+++ b/soh/assets/xml/N64_PAL_11/objects/object_link_boy.xml
@@ -209,7 +209,7 @@
-
+
diff --git a/soh/assets/xml/N64_PAL_11/overlays/ovl_Boss_Ganon.xml b/soh/assets/xml/N64_PAL_11/overlays/ovl_Boss_Ganon.xml
index 8f94fe55b..30b885713 100644
--- a/soh/assets/xml/N64_PAL_11/overlays/ovl_Boss_Ganon.xml
+++ b/soh/assets/xml/N64_PAL_11/overlays/ovl_Boss_Ganon.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/soh/assets/xml/N64_PAL_11/overlays/ovl_Oceff_Spot.xml b/soh/assets/xml/N64_PAL_11/overlays/ovl_Oceff_Spot.xml
index 34a8ac209..64ddc8e1c 100644
--- a/soh/assets/xml/N64_PAL_11/overlays/ovl_Oceff_Spot.xml
+++ b/soh/assets/xml/N64_PAL_11/overlays/ovl_Oceff_Spot.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
index 97b2921c6..548ffa60c 100644
--- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
+++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
@@ -46,6 +46,7 @@ extern PlayState* gPlayState;
#include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h"
#include "objects/object_gjyo_objects/object_gjyo_objects.h"
#include "textures/nintendo_rogo_static/nintendo_rogo_static.h"
+#include "objects/object_gi_rabit_mask/object_gi_rabit_mask.h"
void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction);
void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const char* patchName, int destinationIndex, int sourceIndex);
void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
@@ -228,6 +229,7 @@ static std::map cosmeticOptions = {
COSMETIC_OPTION("Equipment_BowHandle", "Bow Handle", GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true),
COSMETIC_OPTION("Equipment_ChuFace", "Bombchu Face", GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true),
COSMETIC_OPTION("Equipment_ChuBody", "Bombchu Body", GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true),
+ COSMETIC_OPTION("Equipment_BunnyHood", "Bunny Hood", GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true),
COSMETIC_OPTION("Consumable_Hearts", "Hearts", GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false),
COSMETIC_OPTION("Consumable_HeartBorder", "Heart Border", GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true),
@@ -916,6 +918,26 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) {
PATCH_GFX(gBombchuDL, "Equipment_ChuBody5", equipmentChuBody.changedCvar, 46, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
}
+ static CosmeticOption& equipmentBunnyHood = cosmeticOptions.at("Equipment_BunnyHood");
+ if (manualChange || CVarGetInteger(equipmentBunnyHood.rainbowCvar, 0)) {
+ static Color_RGBA8 defaultColor = {equipmentBunnyHood.defaultColor.x, equipmentBunnyHood.defaultColor.y, equipmentBunnyHood.defaultColor.z, equipmentBunnyHood.defaultColor.w};
+ Color_RGBA8 color = CVarGetColor(equipmentBunnyHood.cvar, defaultColor);
+ PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood1", equipmentBunnyHood.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
+ PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood2", equipmentBunnyHood.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255));
+ PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood3", equipmentBunnyHood.changedCvar, 83, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
+ PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood4", equipmentBunnyHood.changedCvar, 84, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255));
+ PATCH_GFX(gLinkChildBunnyHoodDL, "Equipment_BunnyHood5", equipmentBunnyHood.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255));
+
+ if (manualChange) {
+ PATCH_GFX(gLinkChildBunnyHoodDL, "Equipment_BunnyHood6", equipmentBunnyHood.changedCvar, 13, gsSPGrayscale(true));
+ if (CVarGetInteger(equipmentBunnyHood.changedCvar, 0)) {
+ ResourceMgr_PatchGfxByName(gLinkChildBunnyHoodDL, "Equipment_BunnyHood7", 125, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
+ } else {
+ ResourceMgr_UnpatchGfxByName(gLinkChildBunnyHoodDL, "Equipment_BunnyHood7");
+ }
+ }
+ }
+
static CosmeticOption& consumableGreenRupee = cosmeticOptions.at("Consumable_GreenRupee");
if (manualChange || CVarGetInteger(consumableGreenRupee.rainbowCvar, 0)) {
static Color_RGBA8 defaultColor = {consumableGreenRupee.defaultColor.x, consumableGreenRupee.defaultColor.y, consumableGreenRupee.defaultColor.z, consumableGreenRupee.defaultColor.w};
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
index 9a8cc2682..cb16a9915 100644
--- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
+++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
@@ -1694,6 +1694,10 @@ void DrawPlayerTab() {
ImU16 one = 1;
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
+ ImGui::Text("Current B Item");
+ ImGui::InputScalar("B Button", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[0], &one, NULL);
+ ImGui::NewLine();
+
ImGui::Text("Current C Equips");
ImGui::InputScalar("C Left", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[1], &one, NULL);
ImGui::SameLine();
diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp
index e4a5d37a8..73d6c4634 100644
--- a/soh/soh/Enhancements/mods.cpp
+++ b/soh/soh/Enhancements/mods.cpp
@@ -42,8 +42,8 @@ bool performSave = false;
void ReloadSceneTogglingLinkAge() {
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
gPlayState->sceneLoadFlag = 0x14;
- gPlayState->fadeTransition = 11;
- gSaveContext.nextTransitionType = 11;
+ gPlayState->fadeTransition = 42; // Fade Out
+ gSaveContext.nextTransitionType = 42;
gPlayState->linkAgeOnLoad ^= 1; // toggle linkAgeOnLoad
}
diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h
index adfb3e080..8847f61f1 100644
--- a/soh/soh/Enhancements/presets.h
+++ b/soh/soh/Enhancements/presets.h
@@ -74,6 +74,7 @@ const std::vector enhancementsCvars = {
"gNoForcedNavi",
"gSkulltulaFreeze",
"gMMBunnyHood",
+ "gAdultBunnyHood",
"gFastChests",
"gChestSizeAndTextureMatchesContents",
"gFastDrops",
@@ -545,6 +546,8 @@ const std::vector enhancedPresetEntries = {
PRESET_ENTRY_S32("gSkulltulaFreeze", 1),
// MM Bunny Hood
PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST_AND_JUMP),
+ // Adult Bunny Hood
+ PRESET_ENTRY_S32("gAdultBunnyHood", 1),
// Fast Chests
PRESET_ENTRY_S32("gFastChests", 1),
// Fast Drops
@@ -665,6 +668,8 @@ const std::vector randomizerPresetEntries = {
PRESET_ENTRY_S32("gSkulltulaFreeze", 1),
// MM Bunny Hood
PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST_AND_JUMP),
+ // Adult Bunny Hood
+ PRESET_ENTRY_S32("gAdultBunnyHood", 1),
// Fast Chests
PRESET_ENTRY_S32("gFastChests", 1),
// Fast Drops
@@ -763,6 +768,7 @@ const std::vector spockRacePresetEntries = {
PRESET_ENTRY_S32("gInstantPutaway", 1),
PRESET_ENTRY_S32("gFastBoomerang", 1),
PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1),
+ PRESET_ENTRY_S32("gAdultBunnyHood", 1),
PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST),
PRESET_ENTRY_S32("gSeparateArrows", 1),
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
@@ -835,6 +841,7 @@ const std::vector spockRacePresetEntries = {
};
const std::vector spockRaceNoLogicPresetEntries = {
+ PRESET_ENTRY_S32("gAdultBunnyHood", 1),
PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6),
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
PRESET_ENTRY_S32("gCheatEasyPauseBufferEnabled", 1),
@@ -945,6 +952,7 @@ const std::vector s6PresetEntries = {
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", CSMC_BOTH),
PRESET_ENTRY_S32("gFastChests", 1),
PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST),
+ PRESET_ENTRY_S32("gAdultBunnyHood", 1),
PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1),
PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 4),
PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN),
@@ -978,6 +986,7 @@ const std::vector hellModePresetEntries = {
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", CSMC_BOTH),
PRESET_ENTRY_S32("gFastChests", 1),
PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST),
+ PRESET_ENTRY_S32("gAdultBunnyHood", 1),
PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1),
PRESET_ENTRY_S32("gRandomizeBlueFireArrows", 1),
PRESET_ENTRY_S32("gRandomizeBossKeysanity", RO_DUNGEON_ITEM_LOC_ANYWHERE),
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
index 358ae285d..b830efb60 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
@@ -28,12 +28,12 @@ void HintTable_Init() {
hintTable[PREFIX] =
HintText::Exclude({ Text{ "They say that ", /*french*/ "Selon moi, ", /*spanish*/ "Según dicen, " } });
hintTable[WAY_OF_THE_HERO] =
- HintText::Exclude({ Text{ " is on the way of the hero.", /*french*/ " est sur la voie du héros.",
+ HintText::Exclude({ Text{ " is on %cthe way of the hero%w.", /*french*/ " est sur %cla voie du héros%w.",
/*spanish*/ " conduce a la senda del héroe." } });
hintTable[PLUNDERING] =
HintText::Exclude({ Text{ "plundering ", /*french*/ "explorer ", /*spanish*/ "inspeccionar " } });
hintTable[FOOLISH] = HintText::Exclude(
- { Text{ " is a foolish choice.", /*french*/ " est futile.", /*spanish*/ " no es una sabia decisión." } });
+ { Text{ " is %pa foolish choice%w.", /*french*/ " est %pfutile%w.", /*spanish*/ " no es una sabia decisión." } });
hintTable[CAN_BE_FOUND_AT] =
HintText::Exclude({ Text{ "can be found at", /*french*/ "se trouve dans", /*spanish*/ "aguarda en" } });
hintTable[HOARDS] = HintText::Exclude({ Text{ "hoards", /*french*/ "recèle", /*spanish*/ "acapara" } });
diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
index c1610ce07..dea7833fc 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
@@ -314,7 +314,7 @@ static void CreateLocationHint(const std::vector& possibleHintLocation
Text itemHintText = Location(hintedLocation)->GetPlacedItem().GetHint().GetText();
Text prefix = Hint(PREFIX).GetText();
- Text finalHint = prefix + locationHintText + " #"+itemHintText+"#.";
+ Text finalHint = prefix + "%r" + locationHintText + " #%g" + itemHintText + "#%w.";
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
@@ -367,7 +367,7 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) {
// form hint text
Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
- Text finalWothHint = Hint(PREFIX).GetText() + "#" + locationText + "#" + Hint(WAY_OF_THE_HERO).GetText();
+ Text finalWothHint = Hint(PREFIX).GetText() + "%r#" + locationText + "#%w" + Hint(WAY_OF_THE_HERO).GetText();
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalWothHint.english);
SPDLOG_DEBUG("\n\n");
@@ -411,7 +411,7 @@ static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vectorGetParentRegionKey())->GetHint().GetText();
Text finalBarrenHint =
- Hint(PREFIX).GetText() + Hint(PLUNDERING).GetText() + "#" + locationText + "#" + Hint(FOOLISH).GetText();
+ Hint(PREFIX).GetText() + Hint(PLUNDERING).GetText() + "%r#" + locationText + "#%w" + Hint(FOOLISH).GetText();
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalBarrenHint.english);
SPDLOG_DEBUG("\n\n");
@@ -457,13 +457,13 @@ static void CreateRandomLocationHint(const bool goodItem = false) {
Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
// RANDOTODO: reconsider dungeon vs non-dungeon item location hints when boss shuffle mixed pools happens
if (Location(hintedLocation)->IsDungeon()) {
- Text finalHint = Hint(PREFIX).GetText()+"#"+locationText+"# "+Hint(HOARDS).GetText()+" #"+itemText+"#.";
+ Text finalHint = Hint(PREFIX).GetText()+"%r#"+locationText+"#%w "+Hint(HOARDS).GetText()+" %g#"+itemText+"#%w.";
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED}, HINT_TYPE_NAMED_ITEM, hintedLocation);
} else {
- Text finalHint = Hint(PREFIX).GetText()+"#"+itemText+"# "+Hint(CAN_BE_FOUND_AT).GetText()+" #"+locationText+"#.";
+ Text finalHint = Hint(PREFIX).GetText()+"%r#"+itemText+"#%w "+Hint(CAN_BE_FOUND_AT).GetText()+" %g#"+locationText+"#%w.";
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
@@ -602,7 +602,7 @@ void CreateGanonText() {
ganonHintText = hint.GetText()+Hint(YOUR_POCKET).GetText();
lightArrowHintLoc = "Link's Pocket";
} else {
- ganonHintText = hint.GetText()+GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
+ ganonHintText = hint.GetText() + "%r" + GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
lightArrowHintLoc = Location(lightArrowLocation[0])->GetName();
}
ganonHintText = ganonHintText + "!";
@@ -814,9 +814,9 @@ void CreateDampesDiaryText() {
uint32_t location = FilterFromPool(allLocations, [item](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == item;})[0];
Text area = GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
- "Whoever reads this, please enter %g",
- "Toi qui lit ce journal, rends-toi dans %g",
- "Wer immer dies liest, der möge folgenden Ort aufsuchen: %g"
+ "Whoever reads this, please enter %r",
+ "Toi qui lit ce journal, rends-toi dans %r",
+ "Wer immer dies liest, der möge folgenden Ort aufsuchen: %r"
};
Text temp2 = {
@@ -839,13 +839,13 @@ void CreateGregRupeeHint() {
Text area = GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
- "By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%g ",
- "Au fait, si ça t'intéresse, j'ai aperçu le plus éclatant des %gRubis Verts%w quelque part à %g",
+ "By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%r ",
+ "Au fait, si ça t'intéresse, j'ai aperçu le plus éclatant des %gRubis Verts%w quelque part à %r",
""
};
Text temp2 = {
- "%w.^It's said to have %rmysterious powers%w...^But then, it could just be another regular rupee.&Oh well.",
+ "%w.^It's said to have %cmysterious powers%w...^But then, it could just be another regular rupee.&Oh well.",
"%w. On dit qu'il possède des pouvoirs mystérieux... Mais bon, ça pourrait juste être un autre rubis ordinaire.",
""
};
@@ -859,8 +859,8 @@ void CreateSheikText() {
lightArrowHintLoc = Location(lightArrowLocation[0])->GetName();
Text area = GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
- "I overheard Ganondorf say that he misplaced the %rLight Arrows%w in&%g",
- "J'ai entendu dire que Ganondorf aurait caché les %rFlèches de Lumière%w dans %g",
+ "I overheard Ganondorf say that he misplaced the %yLight Arrows%w in&%r",
+ "J'ai entendu dire que Ganondorf aurait caché les %yFlèches de Lumière%w dans %r",
""
};
Text temp2 = Text{"%w.", "%w.", "%w."};
@@ -873,8 +873,8 @@ void CreateSariaText() {
sariaHintLoc = Location(magicLocation[0])->GetName();
Text area = GetHintRegion(Location(magicLocation[0])->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
- "Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %g",
- "As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %g",
+ "Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %r",
+ "As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %r",
""
};
Text temp2 = Text{
diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp
index 3e9c0f7c5..578532a33 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -465,9 +465,9 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
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&%b{{check}}%w!",
- "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem du %r{{params}} Skulltulas&%wzerstörst und ich werde dir dafür&%b{{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!&%b({{check}})")
+ 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}})")
);
CustomMessageManager::Instance->CreateMessage(
Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY,
@@ -481,7 +481,7 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
Randomizer::randoMiscHintsTableID, TEXT_FROGS_UNDERWATER,
CustomMessage("Some frogs holding&%g{{item}}%w&are looking at you from underwater...",
"Unter Wasser gibt es Frösche,&die %g{{item}}%w&bei sich haben und Dich neugierig&beobachten...",
- "Des grenouilles se trouvant&sous l'eau vous fixent attentivement,&tenant fermement&%r{{item}}%w.", TEXTBOX_TYPE_BLUE)
+ "Des grenouilles se trouvant&sous l'eau vous fixent attentivement,&tenant fermement&%g{{item}}%w.", TEXTBOX_TYPE_BLUE)
);
CustomMessageManager::Instance->CreateMessage(
Randomizer::randoMiscHintsTableID, TEXT_SARIAS_SONG_FOREST_SOUNDS,
@@ -565,17 +565,17 @@ void Randomizer::LoadMerchantMessages(const char* spoilerFileName) {
//RANDOTODO: Implement obscure/ambiguous hints
CustomMessageManager::Instance->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_MEDIGORON,
- CustomMessage("How about buying %r&{{item}}%w for %g200 rupees%w?\x1B&%gYes&No%w",
- "Wie wäre es mit %r&{{item}}%w für %g200 Rubine?%w\x1B&%gJa!&Nein!%w",
- "Veux-tu acheter %r&{{item}}%w pour %g200 rubis?%w\x1B&%gOui&Non&w"));
+ CustomMessage("How about buying %g&{{item}}%w for %y200 rupees%w?\x1B&%gYes&No%w",
+ "Wie wäre es mit %g&{{item}}%w für %y200 Rubine?%w\x1B&%gJa!&Nein!%w",
+ "Veux-tu acheter %g&{{item}}%w pour %y200 rubis?%w\x1B&%gOui&Non&w"));
//Granny Shopy
//RANDOTODO: Implement obscure/ambiguous hints
CustomMessageManager::Instance->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP,
- CustomMessage("%r{{item}}%w!&How about %g100 rupees%w?\x1B&%gYes&No%w",
- "%r{{item}}%w!&Wie wäre es mit %g100 Rubine?%w\x1B&%gJa!&Nein!%w",
- "%r{{item}}%w!&Que dis-tu de %g100 rubis?%w\x1B&%gOui&Non&w"));
+ CustomMessage("%g{{item}}%w!&How about %y100 rupees%w?\x1B&%gYes&No%w",
+ "%g{{item}}%w!&Wie wäre es mit %y100 Rubine?%w\x1B&%gJa!&Nein!%w",
+ "%g{{item}}%w!&Que dis-tu de %y100 rubis?%w\x1B&%gOui&Non&w"));
//Carpet Salesman
//RANDOTODO: Implement obscure/ambiguous hints
@@ -596,14 +596,14 @@ void Randomizer::LoadMerchantMessages(const char* spoilerFileName) {
CustomMessageManager::Instance->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_1,
CustomMessage("Welcome!^I am selling stuff, strange and rare, &from all over the world to "
- "everybody.&Today's special is...^%r{{item}}" +
- cgBoxTwoText[0] + "How about %g200 Rupees?%w\x1B&&%gYes&No%w",
+ "everybody.&Today's special is...^%g{{item}}" +
+ cgBoxTwoText[0] + "How about %y200 Rupees?%w\x1B&&%gYes&No%w",
"Sei gegrüßt!^Ich verkaufe allerlei Kuriorisäten.&Stets sonderliche und seltene Ware&aus "
- "aller Welt für jedermann.&Das heutige Angebot bleibt...^%r{{item}}" +
- cgBoxTwoText[1] + "Wie wäre es mit %g200 Rubinen?%w\x1B&&%gJa!&Nein!%w",
+ "aller Welt für jedermann.&Das heutige Angebot bleibt...^%g{{item}}" +
+ cgBoxTwoText[1] + "Wie wäre es mit %y200 Rubinen?%w\x1B&&%gJa!&Nein!%w",
"Bienvenue!^Je vends des trucs étranges et rares,&de partout dans le monde et à tout "
- "le&monde! L'objet du jour est...^%r{{item}}" +
- cgBoxTwoText[2] + "Alors, marché conclu pour %g200 rubis?%w\x1B&&%gOui&Non%w"));
+ "le&monde! L'objet du jour est...^%g{{item}}" +
+ cgBoxTwoText[2] + "Alors, marché conclu pour %y200 rubis?%w\x1B&&%gOui&Non%w"));
CustomMessageManager::Instance->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_2,
diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp
index ec663c6b4..d8cbefd0b 100644
--- a/soh/soh/SohMenuBar.cpp
+++ b/soh/soh/SohMenuBar.cpp
@@ -586,6 +586,8 @@ void DrawEnhancementsMenu() {
"Wearing the Bunny Hood grants a speed increase like in Majora's Mask. The longer jump option is not accounted for in randomizer logic.\n\n"
"Also disables NPC's reactions to wearing the Bunny Hood."
);
+ UIWidgets::PaddedEnhancementCheckbox("Bunny Hood Equippable as Adult", "gAdultBunnyHood", true, false, (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) == BUNNY_HOOD_VANILLA), "Only available with increased bunny hood speed", UIWidgets::CheckboxGraphics::Cross, false);
+ UIWidgets::Tooltip("Allows the bunny hood to be equipped normally from the pause menu as adult.");
UIWidgets::PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false);
UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks");
UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false);
@@ -672,6 +674,8 @@ void DrawEnhancementsMenu() {
UIWidgets::PaddedEnhancementCheckbox("Always Win Dampe Digging Game", "gDampeWin", true, false, SaveManager::Instance->IsRandoFile(),
"This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark);
UIWidgets::Tooltip("Always win the heart piece/purple rupee on the first dig in Dampe's grave digging game, just like in rando\nIn a rando file, this is unconditionally enabled");
+ UIWidgets::PaddedEnhancementCheckbox("All Dogs are Richard", "gAllDogsRichard", true, false);
+ UIWidgets::Tooltip("All dogs can be traded in and will count as Richard.");
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Potion Values"))
@@ -897,6 +901,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects.");
UIWidgets::PaddedEnhancementCheckbox("Disable Grotto Fixed Rotation", "gDisableGrottoRotation", true, false);
UIWidgets::Tooltip("Disables grottos rotating with the camera. To be used in conjunction with mods that want to replace grottos with 3D objects.");
+ UIWidgets::PaddedEnhancementCheckbox("Invisible Bunny Hood", "gHideBunnyHood", true, false);
+ UIWidgets::Tooltip("Turns Bunny Hood invisible while still maintaining its effects.");
ImGui::EndMenu();
}
diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c
index dfafbb7ff..fb4628834 100644
--- a/soh/src/code/z_play.c
+++ b/soh/src/code/z_play.c
@@ -653,7 +653,7 @@ void Play_Init(GameState* thisx) {
Fault_AddClient(&D_801614B8, ZeldaArena_Display, NULL, NULL);
// In order to keep bunny hood equipped on first load, we need to pre-set the age reqs for the item and slot
- if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || CVarGetInteger("gTimelessEquipment", 0)) {
+ if ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger("gTimelessEquipment", 0)) {
gItemAgeReqs[ITEM_MASK_BUNNY] = 9;
if(INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY)
gSlotAgeReqs[SLOT_TRADE_CHILD] = 9;
diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c
index 98dacc982..32a3e6e48 100644
--- a/soh/src/code/z_player_lib.c
+++ b/soh/src/code/z_player_lib.c
@@ -1369,7 +1369,7 @@ void Player_DrawHookshotReticle(PlayState* play, Player* this, f32 hookshotRange
const Color_RGBA8 color = CVarGetColor("gCosmetics.HookshotReticle_NonTarget.Value", defaultColor);
gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a);
}
- gSPVertex(WORLD_OVERLAY_DISP++, (uintptr_t)gLinkAdultHookshotRedicleVtx, 3, 0);
+ gSPVertex(WORLD_OVERLAY_DISP++, (uintptr_t)gLinkAdultHookshotReticleVtx, 3, 0);
gSP1Triangle(WORLD_OVERLAY_DISP++, 0, 1, 2, 0);
CLOSE_DISPS(play->state.gfxCtx);
diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c
index 819a432c0..e0ff7470d 100644
--- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c
+++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c
@@ -438,7 +438,7 @@ u16 func_80A6F810(PlayState* play, Actor* thisx) {
if (followingDog != 0) {
this->unk_215 = false;
- return (followingDog == 1) ? 0x709F : 0x709E;
+ return ((followingDog == 1) || (CVarGetInteger("gAllDogsRichard", 0))) ? 0x709F : 0x709E;
} else {
return 0x709D;
}
diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c
index 25c8887c3..a4d933c58 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -2972,33 +2972,9 @@ void func_80835F44(PlayState* play, Player* this, s32 item) {
return;
}
- if (actionParam >= PLAYER_IA_BOOTS_KOKIRI) {
- u16 bootsValue = actionParam - PLAYER_IA_BOOTS_KOKIRI + 1;
- if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) {
- Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_KOKIRI + 1);
- } else {
- Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue);
- }
- Player_SetEquipmentData(play, this);
- func_808328EC(this, CUR_EQUIP_VALUE(EQUIP_BOOTS) == PLAYER_BOOTS_IRON + 1 ? NA_SE_PL_WALK_HEAVYBOOTS
- : NA_SE_PL_CHANGE_ARMS);
- return;
- }
-
- if (actionParam >= PLAYER_IA_TUNIC_KOKIRI) {
- u16 tunicValue = actionParam - PLAYER_IA_TUNIC_KOKIRI + 1;
- if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) {
- Inventory_ChangeEquipment(EQUIP_TUNIC, PLAYER_TUNIC_KOKIRI + 1);
- } else {
- Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue);
- }
- Player_SetEquipmentData(play, this);
- func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
- return;
- }
-
if (actionParam >= PLAYER_IA_SHIELD_DEKU) {
// Changing shields through action commands is unimplemented
+ // Boots and tunics handled previously
return;
}
@@ -10597,6 +10573,45 @@ static Vec3f D_80854814 = { 0.0f, 0.0f, 200.0f };
static f32 D_80854820[] = { 2.0f, 4.0f, 7.0f };
static f32 D_8085482C[] = { 0.5f, 1.0f, 3.0f };
+void Player_UseTunicBoots(Player* this, PlayState* play) {
+ // Boots and tunics equip despite state
+ s32 i;
+ s32 item;
+ s32 actionParam;
+ if (!(this->stateFlags1 & PLAYER_STATE1_INPUT_DISABLED || this->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE || this->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN || this->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING)) {
+ for (i = 0; i < ARRAY_COUNT(D_80854388); i++) {
+ if (CHECK_BTN_ALL(sControlInput->press.button, D_80854388[i])) {
+ break;
+ }
+ }
+ item = func_80833CDC(play, i);
+ if (item >= ITEM_TUNIC_KOKIRI && item <= ITEM_BOOTS_HOVER) {
+ this->heldItemButton = i;
+ actionParam = Player_ItemToItemAction(item);
+ if (actionParam >= PLAYER_IA_BOOTS_KOKIRI) {
+ u16 bootsValue = actionParam - PLAYER_IA_BOOTS_KOKIRI + 1;
+ if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) {
+ Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_KOKIRI + 1);
+ } else {
+ Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue);
+ }
+ Player_SetEquipmentData(play, this);
+ func_808328EC(this, CUR_EQUIP_VALUE(EQUIP_BOOTS) == PLAYER_BOOTS_IRON + 1 ? NA_SE_PL_WALK_HEAVYBOOTS
+ : NA_SE_PL_CHANGE_ARMS);
+ } else if (actionParam >= PLAYER_IA_TUNIC_KOKIRI) {
+ u16 tunicValue = actionParam - PLAYER_IA_TUNIC_KOKIRI + 1;
+ if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) {
+ Inventory_ChangeEquipment(EQUIP_TUNIC, PLAYER_TUNIC_KOKIRI + 1);
+ } else {
+ Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue);
+ }
+ Player_SetEquipmentData(play, this);
+ func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
+ }
+ }
+ }
+}
+
void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
s32 pad;
@@ -10894,6 +10909,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
if (!(this->stateFlags3 & PLAYER_STATE3_PAUSE_ACTION_FUNC)) {
this->func_674(this, play);
+ Player_UseTunicBoots(this, play);
}
Player_UpdateCamAndSeqModes(play, this);
@@ -11171,7 +11187,11 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList,
MATRIX_TOMTX(sp70);
}
- gSPDisplayList(POLY_OPA_DISP++, sMaskDlists[this->currentMask - 1]);
+
+ if (this->currentMask != PLAYER_MASK_BUNNY || !CVarGetInteger("gHideBunnyHood", 0)) {
+ gSPDisplayList(POLY_OPA_DISP++, sMaskDlists[this->currentMask - 1]);
+ }
+
if (CVarGetInteger("gFixIceTrapWithBunnyHood", 1)) Matrix_Pop();
}
diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c
index 54b0abab3..2fe8fddb7 100644
--- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c
+++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c
@@ -538,7 +538,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) {
gSelectingMask = cursorSlot == SLOT_TRADE_CHILD;
gSlotAgeReqs[SLOT_TRADE_CHILD] = gItemAgeReqs[ITEM_MASK_BUNNY] =
- ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || CVarGetInteger("gTimelessEquipment", 0)) &&
+ ((((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger("gTimelessEquipment", 0)) &&
INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY)
? 9
: 1;