diff --git a/soh/soh/Enhancements/randomizer/LakeHyliaWaterControl.cpp b/soh/soh/Enhancements/randomizer/LakeHyliaWaterControl.cpp index 8b4cb26329..69ffbf134b 100644 --- a/soh/soh/Enhancements/randomizer/LakeHyliaWaterControl.cpp +++ b/soh/soh/Enhancements/randomizer/LakeHyliaWaterControl.cpp @@ -2,6 +2,7 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include extern "C" { extern PlayState* gPlayState; @@ -9,68 +10,50 @@ extern PlayState* gPlayState; #include "functions.h" #include "variables.h" #include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h" +#include "textures/map_grand_static/map_grand_static.h" -extern s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId); -extern void BgSpot06Objects_WaterPlaneCutsceneRise(BgSpot06Objects*, PlayState*); -extern void BgSpot06Objects_WaterPlaneCutsceneLower(BgSpot06Objects*, PlayState*); extern void BgSpot06Objects_LockFloat(BgSpot06Objects*, PlayState*); +extern void BgSpot06Objects_WaterControl_Lower(BgSpot06Objects*, PlayState*); +extern void BgSpot06Objects_WaterControl_Raise(BgSpot06Objects*, PlayState*); } #define WATER_LEVEL_RAISED (-1313) -// Main water control switch -static Actor* sSwitchMain = nullptr; -// Alternate control switch on fishing island -static Actor* sSwitchIsland = nullptr; -static Actor* sLock = nullptr; +static Actor* sSwitchMain = nullptr; // Main water control switch +static Actor* sSwitchIsland = nullptr; // Alternate control switch on fishing island +static Actor* sLock = nullptr; // Water Temple hookshot lock static u8 sPrevFlagState = 0; static void SpawnSwitches(PlayState* play) { - // Object containing floor switch data (and ice block data) - Object_Spawn(&play->objectCtx, OBJECT_GAMEPLAY_DANGEON_KEEP); - - bool waterTempleCleared = Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); - bool waterLowered = !Flags_GetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); - // Persist the water level across scene reloads. - if (waterTempleCleared && waterLowered) { - Flags_SetSwitch(play, 0x3E); - } - s16 switchParams; - if (waterTempleCleared) { - // Toggle-able floor switch - switchParams = 0x3E10; + + // If Water Temple cleared, spawn normal switches and sync current water level with switch status. + // Else, spawn frozen rusty switch that is glitched and can't be pressed + spawn Navi check spots + if (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { + // This eventchkinf flag is set and unset on switch press - the permanent flag of water level + if (!Flags_GetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER)) { + Flags_SetSwitch(play, 0x3E); // Temp switch flag set = lowered water level + } + switchParams = 0x3E10; // Toggle-able floor switch } else { - // Frozen rusty switch, same flag as above. It's glitched and can't be pressed switchParams = 0x3E81; + Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, -896.0f, -1243.0f, 6953.0f, 0, 0, 0, + 0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF)); // Navi check main + Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, 1320.0f, -1218.7f, 4025.0f, 0, 0, 0, + 0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF)); // Navi check fishing } + // Spawn floor switch and sign on main island and fishing pond island sSwitchMain = - // Spawn a floor switch Actor_Spawn(&play->actorCtx, play, ACTOR_OBJ_SWITCH, -896.0f, -1243.0f, 6953.0f, 0, 0, 0, switchParams); - // Spawn a sign Actor_Spawn(&play->actorCtx, play, ACTOR_EN_KANBAN, -970.0f, -1242.0f, 6954.0f, 0, 0, 0, 0x0000 | (TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN & 0xFF)); - if (!waterTempleCleared) { - // Spawn a Navi check spot when Water Temple isn't cleared - Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, -896.0f, -1243.0f, 6953.0f, 0, 0, 0, - 0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF)); - } - - // Second switch on the fishing pond island. Up against the wall sSwitchIsland = - // Spawn a floor switch Actor_Spawn(&play->actorCtx, play, ACTOR_OBJ_SWITCH, 1320.0f, -1218.7f, 4025.0f, 0, 0, 0, switchParams); - // Spawn a sign Actor_Spawn(&play->actorCtx, play, ACTOR_EN_KANBAN, 1320.0f, -1217.7f, 3951.0f, 0, -0x4000, 0, 0x0000 | (TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN & 0xFF)); - if (!waterTempleCleared) { - // Spawn a Navi check spot when Water Temple isn't cleared - Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, 1320.0f, -1218.7f, 4025.0f, 0, 0, 0, - 0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF)); - } - sPrevFlagState = Flags_GetSwitch(play, 0x3E) != 0; + sPrevFlagState = (Flags_GetSwitch(play, 0x3E) != 0); // For checking if switch has been pressed } void RegisterLakeHyliaWaterControl() { @@ -112,13 +95,22 @@ void RegisterLakeHyliaWaterControl() { } } - u8 flagState = Flags_GetSwitch(gPlayState, 0x3E) != 0; - if (sPrevFlagState == flagState) { - return; + // Check if switch has been pressed + u8 flagState = (Flags_GetSwitch(gPlayState, 0x3E) != 0); + if (sPrevFlagState != flagState) { + sPrevFlagState = flagState; + if (flagState) { + waterPlane->actionFunc = BgSpot06Objects_WaterControl_Lower; + Flags_UnsetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); + gPlayState->interfaceCtx.mapSegment[0] = (char*)ResourceGetDataByName(gDrainedLakeHyliaMinimapTex); + gPlayState->interfaceCtx.mapSegmentName[0] = (char*)gDrainedLakeHyliaMinimapTex; + } else { + waterPlane->actionFunc = BgSpot06Objects_WaterControl_Raise; + Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); + gPlayState->interfaceCtx.mapSegment[0] = (char*)ResourceGetDataByName(gLakeHyliaMinimapTex); + gPlayState->interfaceCtx.mapSegmentName[0] = (char*)gLakeHyliaMinimapTex; + } } - sPrevFlagState = flagState; - waterPlane->actionFunc = - flagState ? BgSpot06Objects_WaterPlaneCutsceneLower : BgSpot06Objects_WaterPlaneCutsceneRise; }); // Synchronize pressed states of both main and island switches diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 8860363527..681e20f05f 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -392,22 +392,22 @@ void Map_InitData(PlayState* play, s16 room) { extendedMapIndex = mapIndex; if (play->sceneNum == SCENE_GRAVEYARD) { if (CHECK_QUEST_ITEM(QUEST_SONG_NOCTURNE)) { - extendedMapIndex = 0x14; + extendedMapIndex = 0x14; // Entrance to Shadow Temple visible } } else if (play->sceneNum == SCENE_LAKE_HYLIA) { if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) || - (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)))) { - extendedMapIndex = 0x15; + (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER)))) { + extendedMapIndex = 0x15; // Lowered water level } } else if (play->sceneNum == SCENE_GERUDO_VALLEY) { if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && !GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) { - extendedMapIndex = 0x16; + extendedMapIndex = 0x16; // Bridge not built } } else if (play->sceneNum == SCENE_GERUDOS_FORTRESS) { if ((!IS_RANDO && GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) || (IS_RANDO && CHECK_QUEST_ITEM(QUEST_GERUDO_CARD))) { - extendedMapIndex = 0x17; + extendedMapIndex = 0x17; // Horseback archery visible } } osSyncPrintf(VT_FGCOL(BLUE)); 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 5e7523a819..1078a278d3 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 @@ -206,8 +206,11 @@ void BgSpot06Objects_Destroy(Actor* thisx, PlayState* play) { break; } - // Due to Ships resource caching, the water box collisions for the river have to be manually reset + // Due to Ships resource caching, the water boxes have to be manually reset + play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_RAISED; play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z; + play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = WATER_LEVEL_RAISED; + play->colCtx.colHeader->waterBoxes[LHWB_MAIN_2].ySurface = WATER_LEVEL_RAISED; } /** @@ -509,17 +512,8 @@ void BgSpot06Objects_WaterPlaneCutsceneRise(BgSpot06Objects* this, PlayState* pl if (this->lakeHyliaWaterLevel >= 0.0001f) { this->dyna.actor.world.pos.y = WATER_LEVEL_RAISED; this->actionFunc = BgSpot06Objects_DoNothing; - - // On rando, this is used with the water control system switch to finalize raising the water - if (IS_RANDO) { - this->lakeHyliaWaterLevel = 0; - play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_RAISED; - play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z; - Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); // Set the "raise lake hylia water" flag - 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, IS_RANDO ? 10.0f : 1.0f, 0.001f); + Math_SmoothStepToF(&this->lakeHyliaWaterLevel, 1.0f, 0.1f, 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; @@ -529,32 +523,51 @@ void BgSpot06Objects_WaterPlaneCutsceneRise(BgSpot06Objects* this, PlayState* pl } /** - * Custom action func to lower the Laker Hylia water plane from a switch. + * SoH: Randomizer, custom action function to raise the Laker Hylia water plane from a switch. */ -void BgSpot06Objects_WaterPlaneCutsceneLower(BgSpot06Objects* this, PlayState* play) { - f32 yPos = this->dyna.actor.world.pos.y = this->lakeHyliaWaterLevel + WATER_LEVEL_RAISED; +void BgSpot06Objects_WaterControl_Raise(BgSpot06Objects* this, PlayState* play) { + this->dyna.actor.world.pos.y = this->lakeHyliaWaterLevel + WATER_LEVEL_RAISED; - // A slightly smaller number thatn -680 (which is when textures change) + if (this->lakeHyliaWaterLevel >= 0.0001f) { + this->dyna.actor.world.pos.y = WATER_LEVEL_RAISED; + this->actionFunc = BgSpot06Objects_DoNothing; + this->lakeHyliaWaterLevel = 0; + play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_RAISED; + play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z; + 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, 10.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; + Actor_PlaySfx_FlaggedCentered2(&this->dyna.actor, NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG); + } +} + +/** + * SoH: Randomizer, custom action function to lower the Laker Hylia water plane from a switch. + */ +void BgSpot06Objects_WaterControl_Lower(BgSpot06Objects* this, PlayState* play) { + f32 yPos = this->dyna.actor.world.pos.y = this->lakeHyliaWaterLevel + WATER_LEVEL_RAISED; + play->roomCtx.unk_74[0] = 87; // Remove the moving under water texture from Lake Hylia ground + + // A slightly smaller number than -680.0f (which is when surface textures change) // Then we change the position since the "low water" texture has a different height if (this->lakeHyliaWaterLevel <= -679.9f) { this->dyna.actor.world.pos.y = (this->lakeHyliaWaterLevel + 680.0f) + WATER_LEVEL_RAISED; } - - Flags_UnsetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); // Unset the "raised lake hylia water" flag - play->roomCtx.unk_74[0] = 87; // Remove the moving under water texture from lake hylia ground - if (this->lakeHyliaWaterLevel <= -681.0f) { this->lakeHyliaWaterLevel = -681.0f; this->dyna.actor.world.pos.y = WATER_LEVEL_RAISED; 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) + // Go slightly beyond -681.0f so the smoothing doesn't slow down too much (matches the reverse of water rise + // func) 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; play->colCtx.colHeader->waterBoxes[LHWB_MAIN_2].ySurface = yPos; + Actor_PlaySfx_FlaggedCentered2(&this->dyna.actor, NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG); } - - Actor_PlaySfx_FlaggedCentered2(&this->dyna.actor, NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG); }