diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 35f30c26398..7bc91275c86 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -231,6 +231,7 @@ typedef struct ShipSaveContextData { ShipQuestSaveContextData quest; u8 maskMemory; u8 filenameLanguage; + u8 rbaPaddingBytes[4]; //TODO: Move non-rando specific flags to a new sohInf and move the remaining randomizerInf to ShipRandomizerSaveContextData u16 randomizerInf[(RAND_INF_MAX + 15) / 16]; } ShipSaveContextData; diff --git a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp index 22cc74e6799..b5066a5792e 100644 --- a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp +++ b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp @@ -2,6 +2,7 @@ #include "soh/ShipInit.hpp" extern "C" { +#include "macros.h" #include "variables.h" } @@ -382,12 +383,56 @@ void HandleRBASceneFlags(uint8_t itemToPutInBottle) { // padding bytes void HandleBAPaddingBytes() { - // Reading from padding bytes is not implemented - gSaveContext.equips.buttonItems[0] = 0; + u8 itemOnCRight = gSaveContext.equips.buttonItems[3]; + u8 index; + switch (itemOnCRight) { + case ITEM_MASK_GERUDO: + index = 0; + break; + case ITEM_MASK_TRUTH: + index = 1; + break; + case ITEM_SONG_NOCTURNE: + index = 2; + break; + case ITEM_SONG_PRELUDE: + index = 3; + break; + default: + SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemOnCRight ({})", itemOnCRight); + assert(false); + return; + } + + assert(index >= 0 && index <= 3); + + gSaveContext.equips.buttonItems[0] = gSaveContext.ship.rbaPaddingBytes[index]; } -void HandleRBAPaddingBytes() { - // Writing to padding bytes is not implemented +void HandleRBAPaddingBytes(uint8_t itemToPutInBottle) { + u8 index; + switch (itemToPutInBottle) { + case ITEM_MASK_GERUDO: + index = 0; + break; + case ITEM_MASK_TRUTH: + index = 1; + break; + case ITEM_SONG_NOCTURNE: + index = 2; + break; + case ITEM_SONG_PRELUDE: + index = 3; + break; + default: + SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemToPutInBottle ({})", itemToPutInBottle); + assert(false); + return; + } + + assert(index >= 0 && index <= 3); + + gSaveContext.ship.rbaPaddingBytes[index] = itemToPutInBottle; } // Bottle Adventure @@ -418,6 +463,9 @@ void DoBA() { HandleBAPaddingBytes(); } else if (itemOnCRight >= ITEM_SONG_LULLABY) { HandleBASceneFlags(); + } else { + SPDLOG_WARN("[DoBA] Invalid itemOnCRight ({})", itemOnCRight); + assert(false); } } @@ -426,29 +474,52 @@ void DoRBA(uint8_t itemToPutInBottle) { auto itemOnCRight = gSaveContext.equips.buttonItems[3]; if (itemOnCRight >= ITEM_STICK && itemOnCRight <= ITEM_POTION_BLUE) { - HandleRBAInventoryItems(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryItems(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_FAIRY && itemOnCRight <= ITEM_MASK_BUNNY) { - HandleRBAInventoryAmmo(itemToPutInBottle); + if (!IS_RANDO || itemOnCRight != ITEM_BEAN) { + HandleRBAInventoryAmmo(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_MASK_GORON || itemOnCRight == ITEM_MASK_ZORA) { - HandleRBAInventoryEquipment(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryEquipment(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_MASK_GERUDO || itemOnCRight == ITEM_MASK_TRUTH) { - HandleRBAPaddingBytes(); + HandleRBAPaddingBytes(itemToPutInBottle); } else if (itemOnCRight >= ITEM_SOLD_OUT && itemOnCRight <= ITEM_COJIRO) { - HandleRBAInventoryUpgrades(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryUpgrades(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_ODD_MUSHROOM && itemOnCRight <= ITEM_SWORD_BROKEN) { - HandleRBAInventoryQuestItems(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryQuestItems(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_PRESCRIPTION && itemOnCRight <= ITEM_BULLET_BAG_30) { - HandleRBAInventoryDungeonItems(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryDungeonItems(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_BULLET_BAG_40 && itemOnCRight <= ITEM_SWORD_KNIFE) { - HandleRBAInventoryDungeonKeys(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryDungeonKeys(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_SONG_BOLERO) { - HandleRBAInventoryDefenseHearts(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryDefenseHearts(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_SONG_SERENADE || itemOnCRight == ITEM_SONG_REQUIEM) { - HandleRBAInventoryGSTokens(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryGSTokens(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_SONG_NOCTURNE || itemOnCRight == ITEM_SONG_PRELUDE) { - HandleRBAPaddingBytes(); + HandleRBAPaddingBytes(itemToPutInBottle); } else if (itemOnCRight >= ITEM_SONG_LULLABY) { - HandleRBASceneFlags(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBASceneFlags(itemToPutInBottle); + } + } else { + SPDLOG_WARN("[DoRBA] Invalid itemOnCRight ({})", itemOnCRight); + assert(false); } } @@ -476,6 +547,27 @@ void RegisterBottleAdventure() { auto itemToPutInBottle = static_cast(va_arg(args, int32_t)); DoRBA(itemToPutInBottle); }); + + static Color_RGB8 sGauntletColors[] = { + // values matching OOB reads on N64 + { 0, 0, 6 }, + { 2, 89, 24 }, + { 6, 2, 90 }, + { 96, 6, 2 }, + }; + + REGISTER_VB_SHOULD(VB_SET_GAUNTLET_COLOR, { + Color_RGB8* color = va_arg(args, Color_RGB8*); + s32 strengthUpgrade = CUR_UPG_VALUE(UPG_STRENGTH); + + if (strengthUpgrade <= 3) { + return; + } + + color = &sGauntletColors[strengthUpgrade - 4]; + + *should = false; + }); } static RegisterShipInitFunc initFunc(RegisterBottleAdventure); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index d1ed4534100..541278b7a6c 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2965,7 +2965,15 @@ typedef enum { // ``` // #### `args` // - `*int32_t (camId)` - VB_SHOULD_LOAD_BG_IMAGE + VB_SHOULD_LOAD_BG_IMAGE, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*Color_RGB8` + VB_SET_GAUNTLET_COLOR, } GIVanillaBehavior; #endif diff --git a/soh/soh/config/ConfigUpdaters.cpp b/soh/soh/config/ConfigUpdaters.cpp index 8249bb48d31..e3e0235fb0f 100644 --- a/soh/soh/config/ConfigUpdaters.cpp +++ b/soh/soh/config/ConfigUpdaters.cpp @@ -263,7 +263,6 @@ static const Migration version3Migrations[] = { { "gRedGanonBlood", "gEnhancements.RedGanonBlood" }, { "gRememberSaveLocation", "gEnhancements.RememberSaveLocation" }, { "gRemoveExplosiveLimit", "gEnhancements.RemoveExplosiveLimit" }, - { "gRestoreRBAValues", "gEnhancements.RestoreRBAValues" }, { "gRupeeDash", "gEnhancements.RupeeDash" }, { "gSceneSpecificDirtPathFix", "gEnhancements.SceneSpecificDirtPathFix" }, { "gSeparateArrows", "gEnhancements.SeparateArrows" }, diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 34750ed2cc7..e67e30503b9 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1019,11 +1019,6 @@ Color_RGB8 sTunicColors[] = { Color_RGB8 sGauntletColors[] = { { 255, 255, 255 }, { 254, 207, 15 }, - // #region SOH [RBA] values matching OOB reads on N64 - { 0, 0, 6 }, - { 2, 89, 24 }, - { 6, 2, 90 }, - { 96, 6, 2 }, }; Gfx* sBootDListGroups[][2] = { @@ -1100,7 +1095,9 @@ void Player_DrawImpl(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dL if (strengthUpgrade >= 2) { // silver or gold gauntlets gDPPipeSync(POLY_OPA_DISP++); - color = &sGauntletColors[strengthUpgrade - 2]; + if (GameInteractor_Should(VB_SET_GAUNTLET_COLOR, true, color, strengthUpgrade)) { + color = &sGauntletColors[strengthUpgrade - 2]; + } if (strengthUpgrade == PLAYER_STR_SILVER_G && CVarGetInteger(CVAR_COSMETIC("Gloves.SilverGauntlets.Changed"), 0)) { sTemp = CVarGetColor24(CVAR_COSMETIC("Gloves.SilverGauntlets.Value"), *color);