diff --git a/CMakeLists.txt b/CMakeLists.txt index f22967641..c81727820 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") -project(Ship VERSION 9.2.1 LANGUAGES C CXX) +project(Ship VERSION 9.2.2 LANGUAGES C CXX) include(CMake/soh-cvars.cmake) include(CMake/lus-cvars.cmake) set(SPDLOG_LEVEL_TRACE 0) diff --git a/soh/soh/Enhancements/ArrowCycle.cpp b/soh/soh/Enhancements/ArrowCycle.cpp index 45d8d3445..202f24c4e 100644 --- a/soh/soh/Enhancements/ArrowCycle.cpp +++ b/soh/soh/Enhancements/ArrowCycle.cpp @@ -8,8 +8,7 @@ extern "C" { #include "overlays/actors/ovl_En_Arrow/z_en_arrow.h" s32 func_808351D4(Player* thisx, PlayState* play); // Arrow nocked -s32 func_808353D8(Player* thisx, PlayState* play); // Aiming in first person -void Player_InitItemAction(PlayState* play, Player* thisx, PlayerItemAction itemAction); +void EnArrow_Init(Actor* thisx, PlayState* play); extern PlayState* gPlayState; } @@ -20,16 +19,6 @@ extern PlayState* gPlayState; static const s16 sMagicArrowCosts[] = { 4, 4, 8 }; -#define MINIGAME_STATUS_ACTIVE 1 - -static const s16 BUTTON_FLASH_DURATION = 3; -static const s16 BUTTON_FLASH_COUNT = 3; -static const s16 BUTTON_HIGHLIGHT_ALPHA = 128; - -static s16 sButtonFlashTimer = 0; -static s16 sButtonFlashCount = 0; -static s16 sJustCycledFrames = 0; - static const PlayerItemAction sArrowCycleOrder[] = { PLAYER_IA_BOW, PLAYER_IA_BOW_FIRE, @@ -54,11 +43,11 @@ static bool HasArrowType(PlayerItemAction itemAction) { case PLAYER_IA_BOW: return true; case PLAYER_IA_BOW_FIRE: - return (INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE); + return INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE; case PLAYER_IA_BOW_ICE: - return (INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE); + return INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE; case PLAYER_IA_BOW_LIGHT: - return (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT); + return INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT; default: return false; } @@ -77,15 +66,24 @@ static s32 GetBowItemForArrow(PlayerItemAction itemAction) { } } +static ArrowType GetArrowTypeForArrow(s8 itemAction) { + switch (itemAction) { + case PLAYER_IA_BOW_FIRE: + return ARROW_FIRE; + case PLAYER_IA_BOW_ICE: + return ARROW_ICE; + case PLAYER_IA_BOW_LIGHT: + return ARROW_LIGHT; + default: + return ARROW_NORMAL; + } +} + static bool CanCycleArrows() { Player* player = GET_PLAYER(gPlayState); - // don't allow cycling during minigames - if (gSaveContext.minigameState == MINIGAME_STATUS_ACTIVE) { - return false; - } - - return !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && player->rideActor == NULL && + return LINK_IS_ADULT && !gSaveContext.minigameState && gPlayState->sceneNum != SCENE_SHOOTING_GALLERY && + !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && player->rideActor == NULL && INV_CONTENT(SLOT_BOW) == ITEM_BOW && (INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE || INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE || INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT); @@ -113,66 +111,6 @@ static s8 GetNextArrowType(s8 currentArrowType) { static void UpdateButtonAlpha(s16 flashAlpha, bool isButtonBow, u16* buttonAlpha) { if (isButtonBow) { *buttonAlpha = flashAlpha; - if (sButtonFlashTimer == 0) { - *buttonAlpha = 255; - } - } -} - -static void UpdateFlashEffect(PlayState* play) { - if (sButtonFlashTimer <= 0) { - return; - } - - sButtonFlashTimer--; - s16 flashAlpha = (sButtonFlashTimer % 3) ? BUTTON_HIGHLIGHT_ALPHA : 255; - - if (sButtonFlashTimer == 0 && sButtonFlashCount < BUTTON_FLASH_COUNT - 1) { - sButtonFlashTimer = BUTTON_FLASH_DURATION; - sButtonFlashCount++; - } - UpdateButtonAlpha(flashAlpha, - (gSaveContext.equips.buttonItems[1] == ITEM_BOW) || - (gSaveContext.equips.buttonItems[1] >= ITEM_BOW_ARROW_FIRE && - gSaveContext.equips.buttonItems[1] <= ITEM_BOW_ARROW_LIGHT), - &play->interfaceCtx.cLeftAlpha); - - UpdateButtonAlpha(flashAlpha, - (gSaveContext.equips.buttonItems[2] == ITEM_BOW) || - (gSaveContext.equips.buttonItems[2] >= ITEM_BOW_ARROW_FIRE && - gSaveContext.equips.buttonItems[2] <= ITEM_BOW_ARROW_LIGHT), - &play->interfaceCtx.cDownAlpha); - - UpdateButtonAlpha(flashAlpha, - (gSaveContext.equips.buttonItems[3] == ITEM_BOW) || - (gSaveContext.equips.buttonItems[3] >= ITEM_BOW_ARROW_FIRE && - gSaveContext.equips.buttonItems[3] <= ITEM_BOW_ARROW_LIGHT), - &play->interfaceCtx.cRightAlpha); - - if (CVarGetInteger(CVAR_ENHANCEMENT("DpadEquips"), 0)) { - UpdateButtonAlpha(flashAlpha, - (gSaveContext.equips.buttonItems[4] == ITEM_BOW) || - (gSaveContext.equips.buttonItems[4] >= ITEM_BOW_ARROW_FIRE && - gSaveContext.equips.buttonItems[4] <= ITEM_BOW_ARROW_LIGHT), - &play->interfaceCtx.dpadRightAlpha); - - UpdateButtonAlpha(flashAlpha, - (gSaveContext.equips.buttonItems[5] == ITEM_BOW) || - (gSaveContext.equips.buttonItems[5] >= ITEM_BOW_ARROW_FIRE && - gSaveContext.equips.buttonItems[5] <= ITEM_BOW_ARROW_LIGHT), - &play->interfaceCtx.dpadLeftAlpha); - - UpdateButtonAlpha(flashAlpha, - (gSaveContext.equips.buttonItems[6] == ITEM_BOW) || - (gSaveContext.equips.buttonItems[6] >= ITEM_BOW_ARROW_FIRE && - gSaveContext.equips.buttonItems[6] <= ITEM_BOW_ARROW_LIGHT), - &play->interfaceCtx.dpadDownAlpha); - - UpdateButtonAlpha(flashAlpha, - (gSaveContext.equips.buttonItems[7] == ITEM_BOW) || - (gSaveContext.equips.buttonItems[7] >= ITEM_BOW_ARROW_FIRE && - gSaveContext.equips.buttonItems[7] <= ITEM_BOW_ARROW_LIGHT), - &play->interfaceCtx.dpadUpAlpha); } } @@ -193,72 +131,53 @@ static void UpdateEquippedBow(PlayState* play, s8 arrowType) { } gSaveContext.buttonStatus[i] = BTN_ENABLED; - sButtonFlashTimer = BUTTON_FLASH_DURATION; - sButtonFlashCount = 0; } } - - UpdateFlashEffect(play); } -static void CycleToNextArrow(PlayState* play, Player* player) { - s8 nextArrow = GetNextArrowType(player->heldItemAction); - - if (player->heldActor != NULL && player->heldActor->id == ACTOR_EN_ARROW) { - EnArrow* arrow = (EnArrow*)player->heldActor; - - if (arrow->actor.child != NULL) { - Actor_Kill(arrow->actor.child); - } - - Actor_Kill(&arrow->actor); - } - - Player_InitItemAction(play, player, (PlayerItemAction)nextArrow); - UpdateEquippedBow(play, nextArrow); - Audio_PlaySoundGeneral(NA_SE_PL_CHANGE_ARMS, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - sJustCycledFrames = 2; -} - -void ArrowCycleMain() { +bool ArrowCycleMain() { if (gPlayState == nullptr || !CanCycleArrows()) { - return; + return false; } - if (sJustCycledFrames > 0) { - sJustCycledFrames--; - } - - UpdateFlashEffect(gPlayState); - Player* player = GET_PLAYER(gPlayState); - Input* input = &gPlayState->state.input[0]; - - if (IsAimingBow(player) && CHECK_BTN_ANY(input->press.button, BTN_R)) { + if (player->heldActor != NULL && player->heldActor->id == ACTOR_EN_ARROW) { if (IsHoldingMagicBow(player) && gSaveContext.magicState != MAGIC_STATE_IDLE && player->heldActor == NULL) { Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - return; + return true; } // reset magic state to IDLE before cycling to prevent error sound gSaveContext.magicState = MAGIC_STATE_IDLE; - CycleToNextArrow(gPlayState, player); + s8 nextArrow = GetNextArrowType(player->heldItemAction); + player->heldItemAction = nextArrow; + player->itemAction = nextArrow; + Actor* arrow = player->heldActor; + + if (arrow->child != NULL) { + Actor_Kill(arrow->child); + arrow->child = NULL; + } + arrow->params = GetArrowTypeForArrow(nextArrow); + EnArrow_Init(arrow, gPlayState); + UpdateEquippedBow(gPlayState, nextArrow); + return true; } + return false; } void RegisterArrowCycle() { - COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, CVAR_ARROW_CYCLE_VALUE, [](void* actor) { ArrowCycleMain(); }); - // suppress shield input when R is held while aiming to allow arrow cycling COND_VB_SHOULD(VB_EXECUTE_PLAYER_ACTION_FUNC, CVAR_ARROW_CYCLE_VALUE, { Player* player = (Player*)va_arg(args, void*); Input* input = (Input*)va_arg(args, void*); - if ((IsAimingBow(player) || sJustCycledFrames > 0) && CHECK_BTN_ANY(input->cur.button, BTN_R)) { - input->cur.button &= ~BTN_R; - input->press.button &= ~BTN_R; + if (IsAimingBow(player) && CHECK_BTN_ANY(input->press.button, BTN_R)) { + if (ArrowCycleMain()) { + input->cur.button &= ~BTN_R; + input->press.button &= ~BTN_R; + } } }); @@ -270,9 +189,9 @@ void RegisterArrowCycle() { if (gSaveContext.magic < sMagicArrowCosts[magicArrowType]) { *arrowType = ARROW_NORMAL; + } else { + *should = false; } - - *should = false; }); COND_VB_SHOULD(VB_EN_ARROW_MAGIC_CONSUMPTION, CVAR_ARROW_CYCLE_VALUE, { diff --git a/soh/soh/Enhancements/ExtraTraps.cpp b/soh/soh/Enhancements/ExtraTraps.cpp index 0be9f2bd3..b506582df 100644 --- a/soh/soh/Enhancements/ExtraTraps.cpp +++ b/soh/soh/Enhancements/ExtraTraps.cpp @@ -32,6 +32,7 @@ typedef enum { static AltTrapType roll = ADD_TRAP_MAX; static int statusTimer = -1; static int eventTimer = -1; +static EntranceIndex teleportRoll = ENTR_MAX; const char* altTrapTypeCvars[] = { CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"), @@ -41,6 +42,12 @@ const char* altTrapTypeCvars[] = { CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"), }; +const std::array teleportDestinations = { + ENTR_LINKS_HOUSE_CHILD_SPAWN, ENTR_SACRED_FOREST_MEADOW_WARP_PAD, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD, + ENTR_LAKE_HYLIA_WARP_PAD, ENTR_DESERT_COLOSSUS_WARP_PAD, ENTR_GRAVEYARD_WARP_PAD, + ENTR_TEMPLE_OF_TIME_WARP_PAD, +}; + std::vector getEnabledAddTraps() { std::vector enabledAddTraps; for (int i = 0; i < ADD_TRAP_MAX; i++) { @@ -102,6 +109,7 @@ static void RollRandomTrap(uint64_t seed) { break; case ADD_TELEPORT_TRAP: eventTimer = 3; + teleportRoll = ShipUtils::RandomElement(teleportDestinations, &state); break; default: break; @@ -135,32 +143,7 @@ static void OnPlayerUpdate() { &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); break; case ADD_TELEPORT_TRAP: { - int entrance; - int index = Random(0, 7); - switch (index) { - case 0: - entrance = GI_TP_DEST_SERENADE; - break; - case 1: - entrance = GI_TP_DEST_REQUIEM; - break; - case 2: - entrance = GI_TP_DEST_BOLERO; - break; - case 3: - entrance = GI_TP_DEST_MINUET; - break; - case 4: - entrance = GI_TP_DEST_NOCTURNE; - break; - case 5: - entrance = GI_TP_DEST_PRELUDE; - break; - default: - entrance = GI_TP_DEST_LINKSHOUSE; - break; - } - GameInteractor::RawAction::TeleportPlayer(entrance); + GameInteractor::RawAction::TeleportPlayer(teleportRoll); break; } default: diff --git a/soh/soh/Enhancements/Graphics/DisableFixedCamera.cpp b/soh/soh/Enhancements/Graphics/DisableFixedCamera.cpp index b937a98b1..f6692ce29 100644 --- a/soh/soh/Enhancements/Graphics/DisableFixedCamera.cpp +++ b/soh/soh/Enhancements/Graphics/DisableFixedCamera.cpp @@ -84,7 +84,8 @@ static void DisableFixedCamera_RestoreAllCameraData() { // Helper to check if a camera type is a fixed camera static bool IsFixedCameraType(s16 type) { - return type == CAM_SET_PREREND_FIXED || type == CAM_SET_PREREND_PIVOT || type == CAM_SET_PIVOT_FROM_SIDE; + return type == CAM_SET_PREREND_FIXED || type == CAM_SET_PREREND_PIVOT || type == CAM_SET_PIVOT_FROM_SIDE || + type == CAM_SET_MARKET_BALCONY; } static void RegisterDisableFixedCamera() { diff --git a/soh/soh/Enhancements/TimeSavers/SkipTimerDelay.cpp b/soh/soh/Enhancements/TimeSavers/SkipTimerDelay.cpp deleted file mode 100644 index 733d420fd..000000000 --- a/soh/soh/Enhancements/TimeSavers/SkipTimerDelay.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "soh/Enhancements/game-interactor/GameInteractor.h" -#include "soh/ShipInit.hpp" - -extern "C" { -#include "src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.h" -#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h" -#include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.h" -extern PlayState* gPlayState; -} - -#define SKIP_MISC_INTERACTIONS_NAME CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions") -#define SKIP_MISC_INTERACTIONS_VALUE CVarGetInteger(SKIP_MISC_INTERACTIONS_NAME, IS_RANDO) - -static void RegisterSkipTimerDelay() { - // Skip Water Temple gate delay - COND_ID_HOOK(OnActorUpdate, ACTOR_BG_SPOT06_OBJECTS, SKIP_MISC_INTERACTIONS_VALUE, [](void* actor) { - auto spot06 = static_cast(actor); - if (spot06->dyna.actor.params == 0) { - spot06->timer = 0; - } - }); - - // Skip Spirit Sun on Floor activation delay - COND_ID_HOOK(OnActorUpdate, ACTOR_BG_JYA_BOMBCHUIWA, SKIP_MISC_INTERACTIONS_VALUE, [](void* actor) { - auto jya = static_cast(actor); - if (!(jya->drawFlags & 4) && jya->timer > 0 && jya->timer < 9) { - jya->timer = 9; - } - }); - - // Skip Spirit Sun on Floor & Sun on Block activation delay - COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_LIGHTSWITCH, SKIP_MISC_INTERACTIONS_VALUE, [](void* actor) { - if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE && - (gPlayState->roomCtx.curRoom.num == 4 || gPlayState->roomCtx.curRoom.num == 8)) { - auto sun = static_cast(actor); - sun->toggleDelay = 0; - } - }); -} - -static RegisterShipInitFunc initFunc_SkipTimerDelay(RegisterSkipTimerDelay, - { SKIP_MISC_INTERACTIONS_NAME, "IS_RANDO" }); diff --git a/soh/soh/Enhancements/TimeSavers/SkipWaterGateDelay.cpp b/soh/soh/Enhancements/TimeSavers/SkipWaterGateDelay.cpp new file mode 100644 index 000000000..22e7ed305 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipWaterGateDelay.cpp @@ -0,0 +1,18 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h" +extern SaveContext gSaveContext; +} + +static void RegisterSpot06GateSkip() { + COND_VB_SHOULD(VB_BG_SPOT06_OBJECTS_GATE_SKIP, + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO), { + BgSpot06Objects* actor = va_arg(args, BgSpot06Objects*); + actor->timer = 0; + *should = false; + }); +} + +static RegisterShipInitFunc initFunc(RegisterSpot06GateSkip, { CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index e82f85ee1..6139da7c0 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -109,19 +109,22 @@ void UpdateCurrentBGM(u16 seqKey, SeqType seqType) { } } -static uint64_t seeded_audio_state = 0; - void RandomizeGroup(SeqType type, bool manual = true) { std::vector values; + uint64_t localRngState = 0; + uint64_t* shuffleState = nullptr; + if (!manual) { - if (CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0) == RANDOMIZE_ON_FILE_LOAD_SEEDED || - CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0) == RANDOMIZE_ON_RANDO_GEN_ONLY) { + int randomizeMode = CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0); + if (randomizeMode == RANDOMIZE_ON_FILE_LOAD_SEEDED || randomizeMode == RANDOMIZE_ON_RANDO_GEN_ONLY) { uint32_t finalSeed = type + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : static_cast(gSaveContext.ship.stats.fileCreatedAt)); - ShipUtils::RandInit(finalSeed, &seeded_audio_state); + ShipUtils::RandInit(finalSeed, &localRngState); + shuffleState = &localRngState; } + // For RANDOMIZE_ON_NEW_SCENE, shuffleState remains nullptr, which uses the global RNG } // An empty IncludedSequences set means that the AudioEditor window has never been drawn @@ -141,7 +144,7 @@ void RandomizeGroup(SeqType type, bool manual = true) { if (!values.size()) return; } - ShipUtils::Shuffle(values, &seeded_audio_state); + ShipUtils::Shuffle(values, shuffleState); for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) { const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey); const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey); diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 90f2910cb..a02a65887 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1889,11 +1889,11 @@ void DrawSillyTab() { UIWidgets::Separator(true, true, 2.0f, 2.0f); - UIWidgets::CVarCheckbox("Let It Snow", CVAR_GENERAL("LetItSnow"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Makes snow fall, changes chest texture colors to red and green, etc, for " - "December holidays.\nWill reset on restart outside of December 23-25.")); + UIWidgets::CVarCheckbox( + "Let It Snow", CVAR_GENERAL("LetItSnow"), + UIWidgets::CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Makes snow fall for December holidays.\nWill reset on restart outside of December 23-25.")); UIWidgets::Separator(true, true, 2.0f, 2.0f); @@ -2104,24 +2104,28 @@ void ApplySideEffects(CosmeticOption& cosmeticOption) { } } -static uint64_t seeded_cosmetics_state = 0; - void RandomizeColor(CosmeticOption& cosmeticOption, bool manual = true) { ImVec4 randomColor; - if (!manual && CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0) == RANDOMIZE_ON_FILE_LOAD_SEEDED || - !manual && CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0) == RANDOMIZE_ON_RANDO_GEN_ONLY) { + uint64_t local_seed_state = 0; + uint64_t* randomState = nullptr; - uint32_t finalSeed = cosmeticOption.defaultColor.r + cosmeticOption.defaultColor.g + - cosmeticOption.defaultColor.b + cosmeticOption.defaultColor.a + - (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() - : static_cast(gSaveContext.ship.stats.fileCreatedAt)); + if (!manual) { + int randomizeMode = CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0); + if (randomizeMode == RANDOMIZE_ON_FILE_LOAD_SEEDED || randomizeMode == RANDOMIZE_ON_RANDO_GEN_ONLY) { - randomColor = GetRandomValue(finalSeed, &seeded_cosmetics_state); - } else { - randomColor = GetRandomValue(); + uint32_t finalSeed = cosmeticOption.defaultColor.r + cosmeticOption.defaultColor.g + + cosmeticOption.defaultColor.b + cosmeticOption.defaultColor.a + + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() + : static_cast(gSaveContext.ship.stats.fileCreatedAt)); + + randomState = &local_seed_state; + ShipUtils::RandInit(finalSeed, randomState); + } + // For RANDOMIZE_ON_NEW_SCENE, randomState remains nullptr, which uses the global RNG } + randomColor = GetRandomValue(randomState); Color_RGBA8 newColor; newColor.r = static_cast(randomColor.x * 255.0f); newColor.g = static_cast(randomColor.y * 255.0f); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 20267760b..8d2055fbe 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -52,16 +52,6 @@ typedef enum { /* 0x08 */ GI_COLOR_BLACK, } GIColors; -typedef enum { - /* */ GI_TP_DEST_LINKSHOUSE = ENTR_LINKS_HOUSE_CHILD_SPAWN, - /* */ GI_TP_DEST_MINUET = ENTR_SACRED_FOREST_MEADOW_WARP_PAD, - /* */ GI_TP_DEST_BOLERO = ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD, - /* */ GI_TP_DEST_SERENADE = ENTR_LAKE_HYLIA_WARP_PAD, - /* */ GI_TP_DEST_REQUIEM = ENTR_DESERT_COLOSSUS_WARP_PAD, - /* */ GI_TP_DEST_NOCTURNE = ENTR_GRAVEYARD_WARP_PAD, - /* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_WARP_PAD, -} GITeleportDestinations; - #ifdef __cplusplus extern "C" { #endif diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 06eff69cb..635656c8d 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -227,6 +227,14 @@ typedef enum { // - `*BgIceShelter` VB_BG_ICE_SHELTER_MELT, + // #### `result` + // ```c + // this->timer > 0 && this->timer <= 100 + // ``` + // #### `args` + // - `*BgSpot06Objects` + VB_BG_SPOT06_OBJECTS_GATE_SKIP, + // #### `result` // ```c // gSaveContext.bgsFlag @@ -1558,6 +1566,14 @@ typedef enum { // - `*BossGanondrof` VB_PHANTOM_GANON_DEATH_SCENE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - None + VB_PLAY_BEAN_PLANTING_CS, + // #### `result` // ##### In `DoorWarp1_ChildWarpOut` - `SCENE_DODONGOS_CAVERN_BOSS` // ```c diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index c0a7060cd..98eebc206 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2327,12 +2327,12 @@ void StaticData::HintTable_Init() { {QM_RED, QM_BLUE, QM_GREEN})); hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obstacle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^" - "Challenge the #Obstacle Course?#&\x1B&#Let's go&No thanks#", + "Challenge the #Obstacle Course?#\x1B#Let's go&No thanks#", /*german*/ "Warum versuchst Du Dich nicht mit Epona an dem #Hindernisparcours#?^" "Gelingt es Dir den Rekord zu brechen, bekommst Du meine #Lieblingskuh# Elsie^und ihr Lieblingsspielzeug, #[[1]]#!^" - "Wie sieht's aus?&Möchtest Du es versuchen?\x1B&#Ja!&Nein!#", + "Wie sieht's aus?&Möchtest Du es versuchen?\x1B#Ja!&Nein!#", /*french*/ "Que dirais-tu d'essayer le #Parcours d'Obstacles#? Si tu bats mon temps, je te donnerai ma vache préférée, Elsie, et son jouet #[[1]]#!^" - "Tenter le #Parcours d'Obstacles#?&\x1B&#Allons-y&Non merci#", + "Tenter le #Parcours d'Obstacles#?\x1B#Allons-y&Non merci#", {QM_RED, QM_BLUE, QM_GREEN, QM_RED, QM_GREEN})); hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obstacle Course#, and whoever gets the best time would win a #cow#!^" diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index dae35c0d0..56fa5c7b1 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -36,7 +36,8 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc, bool mysteriou itemName = CustomMessage(RAND_GET_OVERRIDE(rc).GetTrickName()); color = "%g"; } else { - itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); + const Rando::Item& item = Rando::StaticData::RetrieveItem(rgid); + itemName = item.GetHint().GetHintMessage().GetForCurrentLanguage(); } msg.Replace("[[color]]", color); msg.InsertNames({ itemName, CustomMessage(std::to_string(price)) }); diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 6f163c58d..56821bf60 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -140,7 +140,7 @@ void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) { "et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); msg.InsertNumber(count); msg.Replace("[[color]]", item.GetColor()); - msg.InsertNames({ item.GetName() }); + msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() }); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; @@ -155,12 +155,10 @@ void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore %y100 Araignées de la Malédiction%w " "et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); - msg.Replace("[[color]]", Rando::StaticData::RetrieveItem( - RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()) - .GetColor()); - msg.InsertNames( - { Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()) - .GetName() }); + Rando::Item& item = + Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()); + msg.Replace("[[color]]", item.GetColor()); + msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() }); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp index 8075b72be..47c7b46d9 100644 --- a/soh/soh/Enhancements/randomizer/hint.cpp +++ b/soh/soh/Enhancements/randomizer/hint.cpp @@ -513,17 +513,13 @@ const HintText Hint::GetItemHintText(uint8_t slot, bool mysterious) const { auto ctx = Rando::Context::GetInstance(); RandomizerCheck hintedCheck = locations[slot]; RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet(); - CustomMessage msg; if (mysterious) { return StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM]; - } else if (!ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS) && - targetRG == RG_ICE_TRAP) { // RANDOTODO store in item hint instead of item - msg = CustomMessage({ ctx->overrides[hintedCheck].GetTrickName() }); + } else if (targetRG == RG_ICE_TRAP) { // RANDOTODO store in item hint instead of item + return HintText(CustomMessage({ ctx->overrides[hintedCheck].GetTrickName() })); } else { - msg = ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetName(); + return ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetHint(); } - msg = CustomMessage(ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetArticle()) + msg; - return HintText(msg); } const HintText Hint::GetAreaHintText(uint8_t slot) const { diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 55d198432..fb2a00b16 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -13,6 +13,7 @@ #include "soh/SaveManager.h" #include "soh/ShipInit.hpp" #include "soh/ObjectExtension/ObjectExtension.h" +#include "item_category_adj.h" extern "C" { #include "macros.h" @@ -370,6 +371,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID(); GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet); + GetItemCategory getItemCategory = Randomizer_AdjustItemCategory(getItemEntry); if (loc->HasObtained()) { SPDLOG_INFO("RC {} already obtained, skipping", static_cast(rc)); @@ -393,13 +395,8 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { // crude fix to ensure map hints are readable. Ideally replace with better hint tracking. !(getItemEntry.getItemId >= RG_DEKU_TREE_MAP && getItemEntry.getItemId <= RG_ICE_CAVERN_MAP && getItemEntry.modIndex == MOD_RANDOMIZER) && - (getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK || - getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN || - getItemEntry.getItemCategory == ITEM_CATEGORY_HEALTH || - getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER || - // Treat small keys as junk if Skeleton Key is obtained. - (getItemEntry.getItemCategory == ITEM_CATEGORY_SMALL_KEY && - Flags_GetRandomizerInf(RAND_INF_HAS_SKELETON_KEY))))))) { + (getItemCategory == ITEM_CATEGORY_JUNK || getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN || + getItemCategory == ITEM_CATEGORY_HEALTH || getItemCategory == ITEM_CATEGORY_LESSER))))) { Item_DropCollectible(gPlayState, &spawnPos, static_cast(ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000)); } } @@ -446,6 +443,54 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { randomizerQueuedItemEntry = GET_ITEM_NONE; } + if (receivedItemEntry.modIndex == MOD_RANDOMIZER && receivedItemEntry.getItemId == RG_MAGIC_BEAN_PACK) { + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_PLANTING_BEANS)) { + gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_CRATER].swch |= (1 << 3); + if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_CRATER) { + Flags_SetSwitch(gPlayState, 3); + } + gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_TRAIL].swch |= (1 << 6); + if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL) { + Flags_SetSwitch(gPlayState, 6); + } + gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 24); + if (gPlayState->sceneNum == SCENE_DESERT_COLOSSUS) { + Flags_SetSwitch(gPlayState, 24); + } + gSaveContext.sceneFlags[SCENE_GERUDO_VALLEY].swch |= (1 << 3); + if (gPlayState->sceneNum == SCENE_GERUDO_VALLEY) { + Flags_SetSwitch(gPlayState, 3); + } + gSaveContext.sceneFlags[SCENE_GRAVEYARD].swch |= (1 << 3); + if (gPlayState->sceneNum == SCENE_GRAVEYARD) { + Flags_SetSwitch(gPlayState, 3); + } + gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 9); + if (gPlayState->sceneNum == SCENE_KOKIRI_FOREST) { + Flags_SetSwitch(gPlayState, 9); + } + gSaveContext.sceneFlags[SCENE_LAKE_HYLIA].swch |= (1 << 1); + if (gPlayState->sceneNum == SCENE_LAKE_HYLIA) { + Flags_SetSwitch(gPlayState, 1); + } + gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 4) | (1 << 18); + if (gPlayState->sceneNum == SCENE_LOST_WOODS) { + Flags_SetSwitch(gPlayState, 4); + Flags_SetSwitch(gPlayState, 18); + } + gSaveContext.sceneFlags[SCENE_ZORAS_RIVER].swch |= (1 << 3); + if (gPlayState->sceneNum == SCENE_ZORAS_RIVER) { + Flags_SetSwitch(gPlayState, 3); + } + ObjBean* bean = (ObjBean*)Actor_Find(&gPlayState->actorCtx, ACTOR_OBJ_BEAN, ACTORCAT_BG); + if (bean != nullptr) { + Flags_SetSwitch(gPlayState, bean->dyna.actor.params & 0x3F); + func_80B8FE00(bean); + } + AMMO(ITEM_BEAN) = 0; + } + } + if (receivedItemEntry.modIndex == MOD_NONE && (receivedItemEntry.itemId == ITEM_HEART_PIECE || receivedItemEntry.itemId == ITEM_HEART_PIECE_2 || receivedItemEntry.itemId == ITEM_HEART_CONTAINER)) { diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 892cc8ac0..877217606 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -1,7 +1,6 @@ #include "soh_assets.h" #include "static_data.h" #include "SeedContext.h" -#include "logic.h" #include "textures/icon_item_24_static/icon_item_24_static.h" #include "textures/icon_item_static/icon_item_static.h" #include "z64object.h" diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp index cc4c00db2..859eeeca2 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -496,7 +496,8 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR] = Region("Ganon's Castle MQ Fire Trial Open Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true) + ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true), + ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_OPEN, true), }); areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_OPEN] = Region("Ganon's Castle MQ Fire Trial From Open Door", SCENE_INSIDE_GANONS_CASTLE, { @@ -511,7 +512,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_BARRED] = Region("Ganon's Castle MQ Fire Trial From Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR, true) + ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR, true), }); areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR] = Region("Ganon's Castle MQ Fire Trial Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp index e3880e3e9..cce98c921 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp @@ -30,17 +30,17 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3), ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->DMCUpperToPots()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || - (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || - (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->TakeDamage()), + (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), }); areaTable[RR_DMC_ROCKS_GROTTO_ENTRY] = Region("DMC Rocks Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, { @@ -56,17 +56,17 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3), ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || - (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || - (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCUpperToPots()) || - (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->TakeDamage()), + (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), }); areaTable[RR_DMC_BLOCKED_ENTRY] = Region("DMC Blocked Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { @@ -92,13 +92,13 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 16 || logic->Hearts() >= 3), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && logic->CanClimbLadder())), + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder())), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && logic->CanClimbLadder()) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder()) || (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || - ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS))), + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS))), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), }); areaTable[RR_DMC_POTS_ENTRY] = Region("DMC Pots Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { @@ -124,11 +124,11 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_POTS, true), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && logic->CanClimbLadder())), + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder())), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), }); areaTable[RR_DMC_POT_GROTTO_ENTRY] = Region("DMC Pot Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { @@ -154,11 +154,11 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, true), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->TakeDamage() && logic->CanClimbLadder())), + ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder())), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), }); areaTable[RR_DMC_PAD_ENTRY] = Region("DMC Pad Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { @@ -188,7 +188,7 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_POT_GROTTO_EXIT, (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->DMCPadToPots() || ((logic->IsAdult && logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), ENTRANCE(RR_DMC_CENTRAL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), - ENTRANCE(RR_DMC_FAR_PLATFORM, ((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->CanClimbLadder() && logic->DMCPadToPots()) || + ENTRANCE(RR_DMC_FAR_PLATFORM, ((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder() && logic->DMCPadToPots()) || ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || (logic->IsAdult && (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))|| (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow())), @@ -232,7 +232,7 @@ void RegionTable_Init_DeathMountainCrater() { (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), ENTRANCE(RR_DMC_CENTRAL, logic->HasItem(RG_CLIMB) && (logic->FireTimer() >= 48 || logic->Hearts() >= 9)), ENTRANCE(RR_DMC_FAR_PLATFORM, logic->HasItem(RG_CLIMB) && - (((logic->FireTimer() >= 88 || logic->Hearts() >= 3) && logic->TakeDamage() && logic->CanClimbLadder() && logic->DMCPadToPots()) || + (((logic->FireTimer() >= 88 || logic->Hearts() >= 3) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder() && logic->DMCPadToPots()) || ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))|| (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow()))), diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5b2ca3549..e6dc71acc 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4555,51 +4555,6 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) { INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; AMMO(ITEM_BEAN) = 10; - if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_PLANTING_BEANS)) { - gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_CRATER].swch |= (1 << 3); - if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_CRATER) { - Flags_SetSwitch(gPlayState, 3); - } - gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_TRAIL].swch |= (1 << 6); - if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL) { - Flags_SetSwitch(gPlayState, 6); - } - gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 24); - if (gPlayState->sceneNum == SCENE_DESERT_COLOSSUS) { - Flags_SetSwitch(gPlayState, 24); - } - gSaveContext.sceneFlags[SCENE_GERUDO_VALLEY].swch |= (1 << 3); - if (gPlayState->sceneNum == SCENE_GERUDO_VALLEY) { - Flags_SetSwitch(gPlayState, 3); - } - gSaveContext.sceneFlags[SCENE_GRAVEYARD].swch |= (1 << 3); - if (gPlayState->sceneNum == SCENE_GRAVEYARD) { - Flags_SetSwitch(gPlayState, 3); - } - gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 9); - if (gPlayState->sceneNum == SCENE_KOKIRI_FOREST) { - Flags_SetSwitch(gPlayState, 9); - } - gSaveContext.sceneFlags[SCENE_LAKE_HYLIA].swch |= (1 << 1); - if (gPlayState->sceneNum == SCENE_LAKE_HYLIA) { - Flags_SetSwitch(gPlayState, 1); - } - gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 4) | (1 << 18); - if (gPlayState->sceneNum == SCENE_LOST_WOODS) { - Flags_SetSwitch(gPlayState, 4); - Flags_SetSwitch(gPlayState, 18); - } - gSaveContext.sceneFlags[SCENE_ZORAS_RIVER].swch |= (1 << 3); - if (gPlayState->sceneNum == SCENE_ZORAS_RIVER) { - Flags_SetSwitch(gPlayState, 3); - } - ObjBean* bean = (ObjBean*)Actor_Find(&gPlayState->actorCtx, ACTOR_OBJ_BEAN, ACTORCAT_BG); - if (bean != nullptr) { - Flags_SetSwitch(gPlayState, bean->dyna.actor.params & 0x3F); - func_80B8FE00(bean); - } - AMMO(ITEM_BEAN) = 0; - } } break; case RG_DOUBLE_DEFENSE: diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index fd5ed315b..e45656846 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -24,11 +24,14 @@ extern "C" { #include "src/overlays/actors/ovl_En_Jj/z_en_jj.h" #include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" +#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h" #include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" +#include "src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.h" +#include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.h" #include #include #include @@ -328,6 +331,15 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li RateLimitedSuccessChime(); break; } + case ACTOR_BG_JYA_BOMBCHUIWA: { + BgJyaBombchuiwa* bombchuiwa = (BgJyaBombchuiwa*)actor; + if (!(bombchuiwa->drawFlags & 4) && bombchuiwa->timer >= 0 && bombchuiwa->timer < 9) { + bombchuiwa->timer = 9; + } + *should = false; + RateLimitedSuccessChime(); + break; + } case ACTOR_EN_GO2: { EnGo2* biggoron = (EnGo2*)actor; biggoron->isAwake = true; @@ -376,8 +388,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li RateLimitedSuccessChime(); break; } + case ACTOR_OBJ_LIGHTSWITCH: { + ObjLightswitch* lightswitch = (ObjLightswitch*)actor; + lightswitch->toggleDelay = 0; + *should = false; + RateLimitedSuccessChime(); + break; + } case ACTOR_BG_ICE_SHUTTER: - case ACTOR_OBJ_LIGHTSWITCH: case ACTOR_OBJ_SYOKUDAI: case ACTOR_OBJ_TIMEBLOCK: case ACTOR_EN_PO_SISTERS: @@ -554,6 +572,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li } break; } + case VB_PLAY_BEAN_PLANTING_CS: case VB_PLAY_EYEDROP_CREATION_ANIM: case VB_PLAY_EYEDROPS_CS: case VB_PLAY_DROP_FISH_FOR_JABU_CS: diff --git a/soh/soh/Network/CrowdControl/CrowdControl.cpp b/soh/soh/Network/CrowdControl/CrowdControl.cpp index a308685a1..19ac74f27 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.cpp +++ b/soh/soh/Network/CrowdControl/CrowdControl.cpp @@ -5,8 +5,7 @@ #include #include #include -#include -#include "soh/OTRGlobals.h" +#include "soh/ShipInit.hpp" extern "C" { #include @@ -625,37 +624,37 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { case kEffectTpLinksHouse: effect->giEffect = std::make_unique(); dynamic_cast(effect->giEffect.get())->parameters[0] = - GI_TP_DEST_LINKSHOUSE; + ENTR_LINKS_HOUSE_CHILD_SPAWN; break; case kEffectTpMinuet: effect->giEffect = std::make_unique(); dynamic_cast(effect->giEffect.get())->parameters[0] = - GI_TP_DEST_MINUET; + ENTR_SACRED_FOREST_MEADOW_WARP_PAD; break; case kEffectTpBolero: effect->giEffect = std::make_unique(); dynamic_cast(effect->giEffect.get())->parameters[0] = - GI_TP_DEST_BOLERO; + ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD; break; case kEffectTpSerenade: effect->giEffect = std::make_unique(); dynamic_cast(effect->giEffect.get())->parameters[0] = - GI_TP_DEST_SERENADE; + ENTR_LAKE_HYLIA_WARP_PAD; break; case kEffectTpRequiem: effect->giEffect = std::make_unique(); dynamic_cast(effect->giEffect.get())->parameters[0] = - GI_TP_DEST_REQUIEM; + ENTR_DESERT_COLOSSUS_WARP_PAD; break; case kEffectTpNocturne: effect->giEffect = std::make_unique(); dynamic_cast(effect->giEffect.get())->parameters[0] = - GI_TP_DEST_NOCTURNE; + ENTR_GRAVEYARD_WARP_PAD; break; case kEffectTpPrelude: effect->giEffect = std::make_unique(); dynamic_cast(effect->giEffect.get())->parameters[0] = - GI_TP_DEST_PRELUDE; + ENTR_TEMPLE_OF_TIME_WARP_PAD; break; default: diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index e13dec4d5..697f6e30e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -405,7 +405,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) { std::vector args; if (argc > 1) { for (int i = 1; i < argc; i++) { - args.push_back(argv[argc]); + args.push_back(argv[i]); } } Extractor extract; @@ -464,7 +464,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) { #elif (defined(__WIIU__) || defined(__SWITCH__)) extractStep = ES_VERIFY; #else - extractStep = ES_EXTRACT; + extractStep = args.empty() ? ES_EXTRACT : ES_EXTRACT_ARGS; #endif } else { std::string msg; @@ -549,11 +549,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) { "OK", "", [&]() { exit(0); }); } else { windowsStep = WS_DONE; - if (args.size() > 0) { - extractStep = ES_EXTRACT_ARGS; - } else { - extractStep = ES_EXTRACT; - } + extractStep = args.empty() ? ES_EXTRACT : ES_EXTRACT_ARGS; } continue; } @@ -564,7 +560,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) { } case ES_EXTRACT_ARGS: { #if !defined(__SWITCH__) && !defined(__WIIU__) - if (args.size() == 0) { + if (args.empty()) { SohGui::RegisterPopup( "Run Ship of Harkinian", "All files have been processed. Run SoH?", "Yes", "No", [&]() { diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 461d2ca23..477bb6f70 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1806,7 +1806,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_CHEAT("SpeedModifier.DoesntChangeJump")); AddWidget(path, "Multiplier:", WIDGET_CVAR_SLIDER_FLOAT) .CVar(CVAR_CHEAT("SpeedModifier.Value")) - .Options(FloatSliderOptions().IsPercentage().Min(1.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true).Format( + .Options(FloatSliderOptions().IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true).Format( "%.0f%%")); AddWidget(path, "Button Combination:", WIDGET_CVAR_BTN_SELECTOR) .CVar(CVAR_CHEAT("SpeedModifier.Btn")) diff --git a/soh/soh/SohGui/UIWidgets.cpp b/soh/soh/SohGui/UIWidgets.cpp index b261b9c75..fb1049832 100644 --- a/soh/soh/SohGui/UIWidgets.cpp +++ b/soh/soh/SohGui/UIWidgets.cpp @@ -1255,16 +1255,7 @@ bool CVarBtnSelector(const char* label, const char* cvarName, const BtnSelectorO } } // namespace UIWidgets -ImVec4 GetRandomValue() { - ImVec4 NewColor; - NewColor.x = (float)ShipUtils::RandomDouble(); - NewColor.y = (float)ShipUtils::RandomDouble(); - NewColor.z = (float)ShipUtils::RandomDouble(); - return NewColor; -} - -ImVec4 GetRandomValue(uint32_t seed, uint64_t* state) { - ShipUtils::RandInit(seed, state); +ImVec4 GetRandomValue(uint64_t* state) { ImVec4 NewColor; NewColor.x = (float)ShipUtils::RandomDouble(state); NewColor.y = (float)ShipUtils::RandomDouble(state); diff --git a/soh/soh/SohGui/UIWidgets.hpp b/soh/soh/SohGui/UIWidgets.hpp index 6ab02248f..8d0f25b2f 100644 --- a/soh/soh/SohGui/UIWidgets.hpp +++ b/soh/soh/SohGui/UIWidgets.hpp @@ -1089,8 +1089,7 @@ void InsertHelpHoverText(const std::string& text); void InsertHelpHoverText(const char* text); } // namespace UIWidgets -ImVec4 GetRandomValue(); -ImVec4 GetRandomValue(uint32_t seed, uint64_t* state = nullptr); +ImVec4 GetRandomValue(uint64_t* state = nullptr); Color_RGBA8 RGBA8FromVec(ImVec4 vec); ImVec4 VecFromRGBA8(Color_RGBA8 color); diff --git a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c index 20425cdd0..7b7030ef4 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c @@ -7,6 +7,7 @@ #include "z_bg_spot06_objects.h" #include "objects/object_spot06_objects/object_spot06_objects.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_HOOKSHOT_PULLS_ACTOR @@ -266,7 +267,7 @@ void BgSpot06Objects_GateWaitForSwitch(BgSpot06Objects* this, PlayState* play) { * This is where the gate waits a few frames before rising after the switch is set. */ void BgSpot06Objects_GateWaitToOpen(BgSpot06Objects* this, PlayState* play) { - if (this->timer != 0) { + if (GameInteractor_Should(VB_BG_SPOT06_OBJECTS_GATE_SKIP, this->timer != 0, this)) { this->timer--; } @@ -604,7 +605,7 @@ void BgSpot06Objects_WaterPlaneCutsceneRise(BgSpot06Objects* this, PlayState* pl play->roomCtx.unk_74[0] = 0; // Apply the moving under water texture to lake hylia ground } } else { - Math_SmoothStepToF(&this->lakeHyliaWaterLevel, 1.0f, 0.1f, 1.0f, 0.001f); + Math_SmoothStepToF(&this->lakeHyliaWaterLevel, 1.0f, 0.1f, IS_RANDO ? 10.0f : 1.0f, 0.001f); play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_LOWERED; play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = this->dyna.actor.world.pos.y; play->colCtx.colHeader->waterBoxes[LHWB_MAIN_2].ySurface = this->dyna.actor.world.pos.y; @@ -634,7 +635,7 @@ void BgSpot06Objects_WaterPlaneCutsceneLower(BgSpot06Objects* this, PlayState* p this->actionFunc = BgSpot06Objects_DoNothing; } else { // Go slightly beyond -681 so the smoothing doesn't slow down too much (matches the reverse of water rise func) - Math_SmoothStepToF(&this->lakeHyliaWaterLevel, -682.0f, 0.1f, 1.0f, 0.001f); + Math_SmoothStepToF(&this->lakeHyliaWaterLevel, -682.0f, 0.1f, 10.0f, 0.01f); play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_LOWERED; play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z - 50; play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = yPos; diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index 416715f39..3f83322c4 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -4246,7 +4246,7 @@ void BossTw_BlastIce(BossTw* this, PlayState* play) { Math_ApproachF(&sKotakePtr->workf[UNK_F9], 80.0f, 1.0f, 3.0f); Math_ApproachF(&sKotakePtr->workf[UNK_F11], 255.0f, 1.0f, 10.0f); Math_ApproachF(&sKotakePtr->workf[UNK_F12], 0.04f, 0.1f, 0.002f); - Math_ApproachF(&sKotakePtr->workf[UNK_F16], 70.0f, 1.0f, 5.0f); + Math_ApproachF(&sKotakePtr->workf[UNK_F16], 70.0f, 1.0f, -5.0f); if ((this->timers[0] == 70) || (this->timers[0] == 30)) { sKotakePtr->workf[UNK_F16] = 10.0f; @@ -5037,9 +5037,8 @@ void BossTw_DrawEffects(PlayState* play) { if (sp18F == 0) { gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gTwinrovaIceSurroundingPlayerMaterialDL)); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, 255); - gSPSegment( - POLY_XLU_DISP++, 8, - Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, 0, 0x20, 0x20, 0, 0, 0, 0)); + gSPSegment(POLY_XLU_DISP++, 8, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, 0, 0x20, 0x20)); sp18F++; BossTw_InitRand(1, 0x71AC, 0x263A); } @@ -5091,9 +5090,8 @@ void BossTw_DrawEffects(PlayState* play) { } gSPSegment(POLY_XLU_DISP++, 8, - Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, (currentEffect->frame * 3) & 0x7F, - (-currentEffect->frame * 15) & 0xFF, 0x20, 0x40, 1, 0, 0, 0x20, 0x20, 3, -15, - 0, 0)); + Gfx_TwoTexScroll(play->state.gfxCtx, 0, (currentEffect->frame * 3) & 0x7F, + (-currentEffect->frame * 15) & 0xFF, 0x20, 0x40, 1, 0, 0, 0x20, 0x20)); Matrix_Translate(currentEffect->pos.x, currentEffect->pos.y, currentEffect->pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); Matrix_Scale(currentEffect->workf[EFF_SCALE], currentEffect->workf[EFF_SCALE], 1.0f, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_En_Fz/z_en_fz.c b/soh/src/overlays/actors/ovl_En_Fz/z_en_fz.c index ccc367fc5..fbfbf92b0 100644 --- a/soh/src/overlays/actors/ovl_En_Fz/z_en_fz.c +++ b/soh/src/overlays/actors/ovl_En_Fz/z_en_fz.c @@ -2,7 +2,6 @@ #include "objects/object_fz/object_fz.h" #include "soh/frame_interpolation.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" -#include "soh/ObjectExtension/ActorMaximumHealth.h" #define FLAGS \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ @@ -887,8 +886,8 @@ void EnFz_DrawIceSmoke(EnFz* this, PlayState* play) { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, iceSmoke->primAlpha); gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 3 * (iceSmoke->timer + (3 * i)), - 15 * (iceSmoke->timer + (3 * i)), 32, 64, 1, 0, 0, 32, 32, 3, 15, 0, 0)); + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 3 * (iceSmoke->timer + (3 * i)), + 15 * (iceSmoke->timer + (3 * i)), 32, 64, 1, 0, 0, 32, 32)); Matrix_Translate(iceSmoke->pos.x, iceSmoke->pos.y, iceSmoke->pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); Matrix_Scale(iceSmoke->xyScale, iceSmoke->xyScale, 1.0f, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_Obj_Bean/z_obj_bean.c b/soh/src/overlays/actors/ovl_Obj_Bean/z_obj_bean.c index 923defcdc..0510e93e2 100644 --- a/soh/src/overlays/actors/ovl_Obj_Bean/z_obj_bean.c +++ b/soh/src/overlays/actors/ovl_Obj_Bean/z_obj_bean.c @@ -551,7 +551,9 @@ void ObjBean_WaitForBean(ObjBean* this, PlayState* play) { void func_80B8FE00(ObjBean* this) { this->actionFunc = func_80B8FE3C; ObjBean_SetDrawMode(this, BEAN_STATE_DRAW_LEAVES); - this->timer = 60; + if (GameInteractor_Should(VB_PLAY_BEAN_PLANTING_CS, true)) { + this->timer = 60; + } } // Link is looking at the soft soil diff --git a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c index 03bca2f37..cba8feb08 100644 --- a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c +++ b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c @@ -256,9 +256,8 @@ void ObjSwitch_SetOn(ObjSwitch* this, PlayState* play) { } else { OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); } + this->cooldownOn = true; } - - this->cooldownOn = true; } } @@ -271,8 +270,8 @@ void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) { if ((this->dyna.actor.params >> 4 & 7) == 1) { if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + this->cooldownOn = true; } - this->cooldownOn = true; } } } 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 5cc309728..7ffe8af7f 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6062,7 +6062,9 @@ s32 Player_ActionHandler_13(Player* this, PlayState* play) { Inventory_ChangeAmmo(ITEM_BEAN, -1); Player_SetupActionPreserveItemAction(play, this, Player_Action_8084279C, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; - this->av2.actionVar2 = 0x50; + if (GameInteractor_Should(VB_PLAY_BEAN_PLANTING_CS, true)) { + this->av2.actionVar2 = 0x50; + } this->av1.actionVar1 = -1; } talkActor->flags |= ACTOR_FLAG_TALK; diff --git a/soh/src/overlays/effects/ovl_Effect_Ss_En_Ice/z_eff_ss_en_ice.c b/soh/src/overlays/effects/ovl_Effect_Ss_En_Ice/z_eff_ss_en_ice.c index f301a5d22..3ba96fa69 100644 --- a/soh/src/overlays/effects/ovl_Effect_Ss_En_Ice/z_eff_ss_en_ice.c +++ b/soh/src/overlays/effects/ovl_Effect_Ss_En_Ice/z_eff_ss_en_ice.c @@ -122,8 +122,8 @@ void EffectSsEnIce_Draw(PlayState* play, u32 index, EffectSs* this) { Gfx_SetupDL_25Xlu(play->state.gfxCtx); func_8002EB44(&this->pos, &play->view.eye, &hiliteLightDir, play->state.gfxCtx); gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 0, gameplayFrames & 0xFF, 0x20, 0x10, 1, 0, - (gameplayFrames * 2) & 0xFF, 0x40, 0x20, 0, 1, 0, 2)); + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, gameplayFrames & 0xFF, 0x20, 0x10, 1, 0, + (gameplayFrames * 2) & 0xFF, 0x40, 0x20)); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, this->rPrimColorR, this->rPrimColorG, this->rPrimColorB, this->rPrimColorA); gDPSetEnvColor(POLY_XLU_DISP++, this->rEnvColorR, this->rEnvColorG, this->rEnvColorB, (u32)alpha);