diff --git a/CMake/FindOpusFile.cmake b/CMake/FindOpusFile.cmake index ed3b4b7ba..c7fcd2fb1 100644 --- a/CMake/FindOpusFile.cmake +++ b/CMake/FindOpusFile.cmake @@ -6,9 +6,16 @@ # OPUSFILE_LIBRARY - Path to the opusfile library # OPUSFILE_LIBRARIES - Full list of libraries to link (opusfile, opus, ogg) +# Use pkg-config to find opusfile if available +find_package(PkgConf) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_OPUSFILE QUIET opusfile) +endif() + # Search for the OpusFile header find_path(OPUSFILE_INCLUDE_DIR NAMES opusfile.h + HINTS ${PC_OPUSFILE_INCLUDE_DIRS} PATHS /usr/include/opus /usr/local/include/opus /opt/local/include/opus /opt/homebrew/include/opus DOC "Directory where opusfile.h is located" ) @@ -16,6 +23,7 @@ find_path(OPUSFILE_INCLUDE_DIR # Search for the OpusFile library find_library(OPUSFILE_LIBRARY NAMES opusfile + HINTS ${PC_OPUSFILE_LIBRARY_DIRS} DOC "Path to the libopusfile library" ) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9ffc1377..9ab7b6aa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,9 @@ set(GFX_DEBUG_DISASSEMBLER ON) set(GBI_UCODE F3DEX_GBI_2) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") +# Enable MPQ and OTR support +set(INCLUDE_MPQ_SUPPORT ON) + ################################################################################ # Set CONTROLLERBUTTONS_T ################################################################################ @@ -165,6 +168,7 @@ add_compile_definitions(CONTROLLERBUTTONS_T=uint32_t) ################################################################################ add_subdirectory(libultraship ${CMAKE_BINARY_DIR}/libultraship) target_compile_options(libultraship PRIVATE "${WARNING_OVERRIDE}") +target_compile_definitions(libultraship PUBLIC INCLUDE_MPQ_SUPPORT) add_subdirectory(ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD) add_subdirectory(OTRExporter) add_subdirectory(soh) @@ -194,7 +198,7 @@ add_custom_target( # copy LUS default shaders into assets/custom COMMAND ${CMAKE_COMMAND} -E rm -r -f ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/ - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/graphic/Fast3D/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/ + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/fast/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/ COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$" --non-interactive --xml-root assets/xml --custom-otr-file soh.o2r "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}" COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake @@ -220,7 +224,7 @@ add_custom_target( # copy LUS default shaders into assets/custom COMMAND ${CMAKE_COMMAND} -E rm -r -f ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/ - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/graphic/Fast3D/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/ + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/fast/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/ COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$" --norom --custom-otr-file soh.o2r "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}" COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -DONLYSOHOTR=On -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake diff --git a/OTRExporter b/OTRExporter index 461ab19a3..32e088e28 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit 461ab19a36cde807591543397e136cae19aa6e7c +Subproject commit 32e088e28c8cdd055d4bb8f3f219d33ad37963f3 diff --git a/docs/BUILDING.md b/docs/BUILDING.md index f8347b9b6..72a1863b0 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -119,6 +119,72 @@ zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel lib # or using clang zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel ``` +#### Nix +You can use a `flake.nix` file to instantly setup a development environment using [Nix](https://nixos.org/). Write this `flake.nix` file in the root directory: + +```nix +{ + description = "Shipwright development environment"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + # Build tools + clang + git + cmake + ninja + lsb-release + pkg-config + + # SDL2 libraries + SDL2 + SDL2.dev + SDL2_net + + # Other libraries + libpng + libzip + nlohmann_json + tinyxml-2 + spdlog + libGL + libGL.dev + bzip2 + + # X11 libraries + xorg.libX11 + + # Audio libraries + libogg + libogg.dev + libvorbis + libvorbis.dev + libopus + libopus.dev + opusfile + opusfile.dev + ]; + shellHook = '' + echo "Shipwright development environment loaded" + echo "Available tools: clang, git, cmake, ninja" + ''; + }; + }); +} +``` + +Now type `nix develop` and you will be dropped into a shell with all dependencies, ensuring that all build commands work. ### Build @@ -231,7 +297,7 @@ cmake --build build-cmake --target ExtractAssetHeaders ## Switch 1. Requires that your build machine is setup with the tools necessary for your platform above -2. Requires that you have the switch build tools installed +2. Requires that you have the switch build tools installed 3. Clone the Ship of Harkinian repository 4. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice @@ -252,7 +318,7 @@ cmake --build build-switch --target soh_nro ## Wii U 1. Requires that your build machine is setup with the tools necessary for your platform above -2. Requires that you have the Wii U build tools installed +2. Requires that you have the Wii U build tools installed 3. Clone the Ship of Harkinian repository 4. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice @@ -265,7 +331,7 @@ cmake --build build-cmake --target ExtractAssets # Setup cmake project for building for Wii U cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake # -DCMAKE_BUILD_TYPE:STRING=Release (if you're packaging) # Build project and generate rpx -cmake --build build-wiiu --target soh # --target soh_wuhb (for building .wuhb) +cmake --build build-wiiu --target soh # --target soh_wuhb (for building .wuhb) # Now you can run the executable in ./build-wiiu/soh/soh.rpx or the Wii U Homebrew Bundle in ./build-wiiu/soh/soh.wuhb # To develop the project open the repository in VSCode (or your preferred editor) diff --git a/docs/GAME_CONTROLLER_DB.md b/docs/GAME_CONTROLLER_DB.md index 3867f5a63..fe8c9285c 100644 --- a/docs/GAME_CONTROLLER_DB.md +++ b/docs/GAME_CONTROLLER_DB.md @@ -1,38 +1,38 @@ # SDL GameControllerDB The Ship of Harkinian utilizes a text file with SDL controller mappings for extended controller hardware support. -This file is pulled from https://github.com/gabomdq/SDL_GameControllerDB during the build process as [a part of CMakeLists.txt](https://github.com/HarbourMasters/Shipwright/blob/bb643661f62865dfc757c185d0daaebb32f2d53d/soh/CMakeLists.txt#L760). +This file is pulled from https://github.com/mdqinc/SDL_GameControllerDB during the build process as [a part of CMakeLists.txt](https://github.com/HarbourMasters/Shipwright/blob/bb643661f62865dfc757c185d0daaebb32f2d53d/soh/CMakeLists.txt#L760). ## Released versions | Release | sha | diff | | - | - | - | -| Zhora Alfa 4.0.0 | [967daa8](https://github.com/gabomdq/SDL_GameControllerDB/tree/967daa8f89c48b01ed0f9c6a86ac849930442fc6) | | -| Zhora Bravo 4.0.1 | [ccac7cd](https://github.com/gabomdq/SDL_GameControllerDB/tree/ccac7cd97f445955d4437e21c5f82123d9b4349b) | [+1](https://github.com/gabomdq/SDL_GameControllerDB/compare/967daa8...ccac7cd) | -| Zhora Charlie 4.0.2 | [ff26eb0](https://github.com/gabomdq/SDL_GameControllerDB/tree/ff26eb04d0fe18356985d968119429d6012e7d75) | [+8/-3](https://github.com/gabomdq/SDL_GameControllerDB/compare/ccac7cd...ff26eb0) | -| Zhora Delta 4.0.3 | [ad02da5](https://github.com/gabomdq/SDL_GameControllerDB/tree/ad02da5a95ca8005f2c1facc11a5a52f8522f0ee) | [+4/-5](https://github.com/gabomdq/SDL_GameControllerDB/compare/ff26eb0...ad02da5) | -| Zohra Echo 4.0.4 | [c203690](https://github.com/gabomdq/SDL_GameControllerDB/tree/c203690b1e13980699802918d362cd9dadf89bd0) | [+8/-4](https://github.com/gabomdq/SDL_GameControllerDB/compare/ad02da5...c203690) | -| Zhora Foxtrot 4.0.5 | [9db8101](https://github.com/gabomdq/SDL_GameControllerDB/tree/9db8101a5780d1b0721bf6de385e6ffe0d07dfc7) | [+6](https://github.com/gabomdq/SDL_GameControllerDB/compare/c203690...9db8101) | -| Flynn Alfa 5.0.0 | [163cc5d](https://github.com/gabomdq/SDL_GameControllerDB/tree/163cc5d45e9fc2f1bb2b95ea7eee4bbc9a57955c) | [+29/-8](https://github.com/gabomdq/SDL_GameControllerDB/compare/9db8101...163cc5d) | -| Flynn Bravo 5.0.1 | [7efce7d](https://github.com/gabomdq/SDL_GameControllerDB/tree/7efce7d3f309ec1fa409b1af09153f9eb77fbedf) | [-1](https://github.com/gabomdq/SDL_GameControllerDB/compare/163cc5d...7efce7d) | -| Flynn Charlie 5.0.2 | [e607703](https://github.com/gabomdq/SDL_GameControllerDB/tree/e607703392145343e8aca42be052121c0b7bd1c9) | [+40/-17](https://github.com/gabomdq/SDL_GameControllerDB/compare/7efce7d...e607703) | -| Bradley Alfa 5.1.0 | [2ba9676](https://github.com/gabomdq/SDL_GameControllerDB/tree/2ba96761af795c15e916cc97790b51e09dc0cd54) | [+1/-1](https://github.com/gabomdq/SDL_GameControllerDB/compare/e607703...2ba9676) | -| Bradley Charlie 5.1.2 | [4f5d1d4](https://github.com/gabomdq/SDL_GameControllerDB/tree/4f5d1d497985b75f4a83a5de46f596dc4d7f002e) | [+5/-1](https://github.com/gabomdq/SDL_GameControllerDB/compare/2ba9676...4f5d1d4) | -| Bradley Delta 5.1.3 | [9b73049](https://github.com/gabomdq/SDL_GameControllerDB/tree/9b73049ee62a2cc862d6ad94c2c777f2e8363a48) | [+4/-1](https://github.com/gabomdq/SDL_GameControllerDB/compare/4f5d1d4...9b73049) | -| Bradley Echo 5.1.4 | [6d3801f](https://github.com/gabomdq/SDL_GameControllerDB/tree/6d3801fcfe74b1989de96403b7b560eba72a175c) | [+56/-21](https://github.com/gabomdq/SDL_GameControllerDB/compare/9b73049...6d3801f) | -| Gibbs Alfa 6.0.0 | [0562b00](https://github.com/gabomdq/SDL_GameControllerDB/tree/0562b00eaf5c0308c49d329b79263d2dae1c3a85) | [+8/-2](https://github.com/gabomdq/SDL_GameControllerDB/compare/6d3801f...0562b00) | -| Khan Alfa 6.1.0 | [436c7e3](https://github.com/gabomdq/SDL_GameControllerDB/tree/436c7e3d54a57189ea0ab44d05f36b7cc7ea496c) | [+31/-16](https://github.com/gabomdq/SDL_GameControllerDB/compare/0562b00...436c7e3) | -| Khan Bravo 6.1.1 | [01cca2e](https://github.com/gabomdq/SDL_GameControllerDB/tree/01cca2e77f9bf9f1432be04f876f287eb78297fe) | [+23/-6](https://github.com/gabomdq/SDL_GameControllerDB/compare/436c7e3...01cca2e) | -| Khan Charlie 6.1.2 | [6852946](https://github.com/gabomdq/SDL_GameControllerDB/tree/6852946487534c69b7d228fd4eb8c87cf6966475) | [+25/-15](https://github.com/gabomdq/SDL_GameControllerDB/compare/01cca2e...6852946) | -| Spock Alfa 7.0.0 | [38bda81](https://github.com/gabomdq/SDL_GameControllerDB/tree/38bda816dc786f18493876f7bc30bc12dfd2636a) | [+15/-1](https://github.com/gabomdq/SDL_GameControllerDB/compare/6852946...38bda81) | -| Spock Bravo 7.0.1 | [228d980](https://github.com/gabomdq/SDL_GameControllerDB/tree/228d980d3d791e9df3b096472f6b97459f8709fe) | [+7/-3](https://github.com/gabomdq/SDL_GameControllerDB/compare/38bda81...228d980) | -| Spock Charlie 7.0.2 | [c5b4df0](https://github.com/gabomdq/SDL_GameControllerDB/tree/c5b4df0e1061175cb11e3ebbf8045178339864a5) | [+3](https://github.com/gabomdq/SDL_GameControllerDB/compare/228d980...c5b4df0) | -| Sulu Alfa 7.1.0 | [a2cf171](https://github.com/gabomdq/SDL_GameControllerDB/tree/a2cf1711b4ebc646a3814705d2fb6aac5707bcae) | [+4/-1](https://github.com/gabomdq/SDL_GameControllerDB/compare/c5b4df0...a2cf171) | -| Sulu Bravo 7.1.1 | [cc9f777](https://github.com/gabomdq/SDL_GameControllerDB/tree/cc9f777721f0cb30058d9eef52a295130b734a4a) | [+29/-9](https://github.com/gabomdq/SDL_GameControllerDB/compare/a2cf171...cc9f777) | -| MacReady Alfa 8.0.0 | [c56329f](https://github.com/gabomdq/SDL_GameControllerDB/tree/c56329f4df93fc7a780bdbeae47a9c91447b629c) | [+67/-23](https://github.com/gabomdq/SDL_GameControllerDB/compare/cc9f777...c56329f) | -| MacReady Bravo 8.0.1 | [721b575](https://github.com/gabomdq/SDL_GameControllerDB/tree/721b575d3053b21d6d30419bf74afb5b1d0fa7a4) | [+5/-5](https://github.com/gabomdq/SDL_GameControllerDB/compare/c56329f...721b575) | -| MacReady Charlie 8.0.2 | [721b575](https://github.com/gabomdq/SDL_GameControllerDB/tree/721b575d3053b21d6d30419bf74afb5b1d0fa7a4) | [+0/-0](https://github.com/gabomdq/SDL_GameControllerDB/compare/721b575...721b575) | -| MacReady Delta 8.0.3 | [d4ab609](https://github.com/gabomdq/SDL_GameControllerDB/tree/d4ab609121ee6e687bc3d3a7e80244b3b26d1164) | [+5/-3](https://github.com/gabomdq/SDL_GameControllerDB/compare/721b575...d4ab609) | -| MacReady Echo 8.0.4 | [6555d47](https://github.com/gabomdq/SDL_GameControllerDB/tree/6555d47ecb5d9eebac0e3d8cd19a545e9d946c40) | [+2/-0](https://github.com/gabomdq/SDL_GameControllerDB/compare/d4ab609...6555d47) | -| MacReady Foxtrot 8.0.5 | [037d6a1](https://github.com/gabomdq/SDL_GameControllerDB/tree/037d6a1533ed94fbc6a8c71e6f1f9aff1e46208a) | [+47/-14](https://github.com/gabomdq/SDL_GameControllerDB/compare/6555d47...037d6a1) | -| MacReady Golf 8.0.6 | [075c154](https://github.com/gabomdq/SDL_GameControllerDB/tree/075c1549075ef89a397fd7e0663d21e53a2485fd) | [+340/-301](https://github.com/gabomdq/SDL_GameControllerDB/compare/037d6a1...075c154) | +| Zhora Alfa 4.0.0 | [967daa8](https://github.com/mdqinc/SDL_GameControllerDB/tree/967daa8f89c48b01ed0f9c6a86ac849930442fc6) | | +| Zhora Bravo 4.0.1 | [ccac7cd](https://github.com/mdqinc/SDL_GameControllerDB/tree/ccac7cd97f445955d4437e21c5f82123d9b4349b) | [+1](https://github.com/mdqinc/SDL_GameControllerDB/compare/967daa8...ccac7cd) | +| Zhora Charlie 4.0.2 | [ff26eb0](https://github.com/mdqinc/SDL_GameControllerDB/tree/ff26eb04d0fe18356985d968119429d6012e7d75) | [+8/-3](https://github.com/mdqinc/SDL_GameControllerDB/compare/ccac7cd...ff26eb0) | +| Zhora Delta 4.0.3 | [ad02da5](https://github.com/mdqinc/SDL_GameControllerDB/tree/ad02da5a95ca8005f2c1facc11a5a52f8522f0ee) | [+4/-5](https://github.com/mdqinc/SDL_GameControllerDB/compare/ff26eb0...ad02da5) | +| Zohra Echo 4.0.4 | [c203690](https://github.com/mdqinc/SDL_GameControllerDB/tree/c203690b1e13980699802918d362cd9dadf89bd0) | [+8/-4](https://github.com/mdqinc/SDL_GameControllerDB/compare/ad02da5...c203690) | +| Zhora Foxtrot 4.0.5 | [9db8101](https://github.com/mdqinc/SDL_GameControllerDB/tree/9db8101a5780d1b0721bf6de385e6ffe0d07dfc7) | [+6](https://github.com/mdqinc/SDL_GameControllerDB/compare/c203690...9db8101) | +| Flynn Alfa 5.0.0 | [163cc5d](https://github.com/mdqinc/SDL_GameControllerDB/tree/163cc5d45e9fc2f1bb2b95ea7eee4bbc9a57955c) | [+29/-8](https://github.com/mdqinc/SDL_GameControllerDB/compare/9db8101...163cc5d) | +| Flynn Bravo 5.0.1 | [7efce7d](https://github.com/mdqinc/SDL_GameControllerDB/tree/7efce7d3f309ec1fa409b1af09153f9eb77fbedf) | [-1](https://github.com/mdqinc/SDL_GameControllerDB/compare/163cc5d...7efce7d) | +| Flynn Charlie 5.0.2 | [e607703](https://github.com/mdqinc/SDL_GameControllerDB/tree/e607703392145343e8aca42be052121c0b7bd1c9) | [+40/-17](https://github.com/mdqinc/SDL_GameControllerDB/compare/7efce7d...e607703) | +| Bradley Alfa 5.1.0 | [2ba9676](https://github.com/mdqinc/SDL_GameControllerDB/tree/2ba96761af795c15e916cc97790b51e09dc0cd54) | [+1/-1](https://github.com/mdqinc/SDL_GameControllerDB/compare/e607703...2ba9676) | +| Bradley Charlie 5.1.2 | [4f5d1d4](https://github.com/mdqinc/SDL_GameControllerDB/tree/4f5d1d497985b75f4a83a5de46f596dc4d7f002e) | [+5/-1](https://github.com/mdqinc/SDL_GameControllerDB/compare/2ba9676...4f5d1d4) | +| Bradley Delta 5.1.3 | [9b73049](https://github.com/mdqinc/SDL_GameControllerDB/tree/9b73049ee62a2cc862d6ad94c2c777f2e8363a48) | [+4/-1](https://github.com/mdqinc/SDL_GameControllerDB/compare/4f5d1d4...9b73049) | +| Bradley Echo 5.1.4 | [6d3801f](https://github.com/mdqinc/SDL_GameControllerDB/tree/6d3801fcfe74b1989de96403b7b560eba72a175c) | [+56/-21](https://github.com/mdqinc/SDL_GameControllerDB/compare/9b73049...6d3801f) | +| Gibbs Alfa 6.0.0 | [0562b00](https://github.com/mdqinc/SDL_GameControllerDB/tree/0562b00eaf5c0308c49d329b79263d2dae1c3a85) | [+8/-2](https://github.com/mdqinc/SDL_GameControllerDB/compare/6d3801f...0562b00) | +| Khan Alfa 6.1.0 | [436c7e3](https://github.com/mdqinc/SDL_GameControllerDB/tree/436c7e3d54a57189ea0ab44d05f36b7cc7ea496c) | [+31/-16](https://github.com/mdqinc/SDL_GameControllerDB/compare/0562b00...436c7e3) | +| Khan Bravo 6.1.1 | [01cca2e](https://github.com/mdqinc/SDL_GameControllerDB/tree/01cca2e77f9bf9f1432be04f876f287eb78297fe) | [+23/-6](https://github.com/mdqinc/SDL_GameControllerDB/compare/436c7e3...01cca2e) | +| Khan Charlie 6.1.2 | [6852946](https://github.com/mdqinc/SDL_GameControllerDB/tree/6852946487534c69b7d228fd4eb8c87cf6966475) | [+25/-15](https://github.com/mdqinc/SDL_GameControllerDB/compare/01cca2e...6852946) | +| Spock Alfa 7.0.0 | [38bda81](https://github.com/mdqinc/SDL_GameControllerDB/tree/38bda816dc786f18493876f7bc30bc12dfd2636a) | [+15/-1](https://github.com/mdqinc/SDL_GameControllerDB/compare/6852946...38bda81) | +| Spock Bravo 7.0.1 | [228d980](https://github.com/mdqinc/SDL_GameControllerDB/tree/228d980d3d791e9df3b096472f6b97459f8709fe) | [+7/-3](https://github.com/mdqinc/SDL_GameControllerDB/compare/38bda81...228d980) | +| Spock Charlie 7.0.2 | [c5b4df0](https://github.com/mdqinc/SDL_GameControllerDB/tree/c5b4df0e1061175cb11e3ebbf8045178339864a5) | [+3](https://github.com/mdqinc/SDL_GameControllerDB/compare/228d980...c5b4df0) | +| Sulu Alfa 7.1.0 | [a2cf171](https://github.com/mdqinc/SDL_GameControllerDB/tree/a2cf1711b4ebc646a3814705d2fb6aac5707bcae) | [+4/-1](https://github.com/mdqinc/SDL_GameControllerDB/compare/c5b4df0...a2cf171) | +| Sulu Bravo 7.1.1 | [cc9f777](https://github.com/mdqinc/SDL_GameControllerDB/tree/cc9f777721f0cb30058d9eef52a295130b734a4a) | [+29/-9](https://github.com/mdqinc/SDL_GameControllerDB/compare/a2cf171...cc9f777) | +| MacReady Alfa 8.0.0 | [c56329f](https://github.com/mdqinc/SDL_GameControllerDB/tree/c56329f4df93fc7a780bdbeae47a9c91447b629c) | [+67/-23](https://github.com/mdqinc/SDL_GameControllerDB/compare/cc9f777...c56329f) | +| MacReady Bravo 8.0.1 | [721b575](https://github.com/mdqinc/SDL_GameControllerDB/tree/721b575d3053b21d6d30419bf74afb5b1d0fa7a4) | [+5/-5](https://github.com/mdqinc/SDL_GameControllerDB/compare/c56329f...721b575) | +| MacReady Charlie 8.0.2 | [721b575](https://github.com/mdqinc/SDL_GameControllerDB/tree/721b575d3053b21d6d30419bf74afb5b1d0fa7a4) | [+0/-0](https://github.com/mdqinc/SDL_GameControllerDB/compare/721b575...721b575) | +| MacReady Delta 8.0.3 | [d4ab609](https://github.com/mdqinc/SDL_GameControllerDB/tree/d4ab609121ee6e687bc3d3a7e80244b3b26d1164) | [+5/-3](https://github.com/mdqinc/SDL_GameControllerDB/compare/721b575...d4ab609) | +| MacReady Echo 8.0.4 | [6555d47](https://github.com/mdqinc/SDL_GameControllerDB/tree/6555d47ecb5d9eebac0e3d8cd19a545e9d946c40) | [+2/-0](https://github.com/mdqinc/SDL_GameControllerDB/compare/d4ab609...6555d47) | +| MacReady Foxtrot 8.0.5 | [037d6a1](https://github.com/mdqinc/SDL_GameControllerDB/tree/037d6a1533ed94fbc6a8c71e6f1f9aff1e46208a) | [+47/-14](https://github.com/mdqinc/SDL_GameControllerDB/compare/6555d47...037d6a1) | +| MacReady Golf 8.0.6 | [075c154](https://github.com/mdqinc/SDL_GameControllerDB/tree/075c1549075ef89a397fd7e0663d21e53a2485fd) | [+340/-301](https://github.com/mdqinc/SDL_GameControllerDB/compare/037d6a1...075c154) | diff --git a/libultraship b/libultraship index 6a3f6cd32..a64f9f9d9 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 6a3f6cd327b99f617b623e5b9a3afeae460aac2b +Subproject commit a64f9f9d989ad0640736de6408fb7bc2456c7730 diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 200ff6ff0..aa979f6ed 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -413,31 +413,7 @@ endif() target_include_directories(${PROJECT_NAME} PRIVATE assets ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${CMAKE_CURRENT_SOURCE_DIR}/src/ - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/include - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/log - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/debug - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/menu - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/utils - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/utils/binarytools - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/config - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/resource - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/resource/type - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/resource/factory - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/audio - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/window - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/window/gui - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/config - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/public - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/public/libultra - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/public/bridge - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/extern - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/extern/tinyxml2 - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/ - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/libjpeg/include/ - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic/Fast3D/U64/PR - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic ${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD/resource/type ${SDL2-INCLUDE} ${SDL2-NET-INCLUDE} @@ -597,6 +573,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wno-error + -Wformat-security -Wno-return-type -Wno-unused-parameter -Wno-unused-function @@ -624,6 +601,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") elseif (CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch") target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wno-error + -Wformat-security -Wno-return-type -Wno-unused-parameter -Wno-unused-function @@ -674,6 +652,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wno-error + -Wformat-security -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable @@ -839,7 +818,7 @@ INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.o2r DESTINATION . COMPONENT ship) endif() find_program(CURL NAMES curl DOC "Path to the curl program. Used to download files.") -execute_process(COMMAND ${CURL} -sSfL https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt -o ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt OUTPUT_VARIABLE RESULT) +execute_process(COMMAND ${CURL} -sSfL https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt -o ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt OUTPUT_VARIABLE RESULT) if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/macosx/Info.plist.in ${CMAKE_BINARY_DIR}/macosx/Info.plist @ONLY) diff --git a/soh/Resource.rc b/soh/Resource.rc index 7d9f356d0..59702663f 100644 --- a/soh/Resource.rc +++ b/soh/Resource.rc @@ -1,6 +1,6 @@ // Microsoft Visual C++ generated resource script. // -#include "resource.h" +#include #include "properties.h" #define APSTUDIO_READONLY_SYMBOLS diff --git a/soh/assets/custom/accessibility/texts/filechoose_ger.json b/soh/assets/custom/accessibility/texts/filechoose_ger.json index 2ad1322fd..b0fd8b899 100644 --- a/soh/assets/custom/accessibility/texts/filechoose_ger.json +++ b/soh/assets/custom/accessibility/texts/filechoose_ger.json @@ -25,5 +25,5 @@ "quest_sel_vanilla": "Quest - Original", "quest_sel_mq": "Quest - Master Quest", "quest_sel_randomizer": "Quest - Randomizer", - "quest_sel_boss_rush": "Quest - Bosse Rush" -} \ No newline at end of file + "quest_sel_boss_rush": "Quest - Boss Rush" +} diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json index f66b82736..95fb567b6 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json @@ -47,7 +47,7 @@ "28": "Blaues Feuer", "29": "Käfer", "30": "Nachtschwärmer", - "31": "Milch (1/2)", + "31": "Milch (Halbe Füllung)", "32": "Irrlicht", "33": "Seltsames Ei", "34": "Huhn", @@ -67,7 +67,7 @@ "48": "Schimmelpilz", "49": "Modertrank", "50": "Säge", - "51": "Goronen-Schwert (zerbrochen)", + "51": "Zerbr. Goronen-Schwert", "52": "Rezept", "53": "Glotzfrosch", "54": "Augentropfen", @@ -78,7 +78,7 @@ "59": "Kokiri-Schwert", "60": "Master-Schwert", "61": "Langschwert", - "62": "Deku-schild", + "62": "Deku-Schild", "63": "Hylia-Schild", "64": "Spiegel-Schild", "65": "Kokiri-Rüstung", @@ -99,13 +99,13 @@ "80": "Goronen-Armband", "81": "Krafthandschuh", "82": "Titanhandschuh", - "83": "Silberschuppe", - "84": "Goldschuppe", - "85": "Langschwert (gebrochen)", + "83": "Silberne Schuppe", + "84": "Goldene Schuppe", + "85": "Zerbr. Langschwert", "86": "Große Börse", "87": "Riesenbörse", "88": "Deku-Kerne", - "89": "Angel", + "89": "Angelrute", "90": "Menuett des Waldes", "91": "Bolero des Feuers", "92": "Serenade des Wassers", @@ -117,7 +117,7 @@ "98": "Salias Lied", "99": "Hymne der Sonne", "100": "Hymne der Zeit", - "101": "Song of Storms", + "101": "Hymne des Sturms", "102": "Amulett des Waldes", "103": "Amulett des Feuers", "104": "Amulett des Wassers", @@ -125,7 +125,7 @@ "106": "Amulett des Schattens", "107": "Amulett des Lichts", "108": "Kokiri-Smaragd", - "109": "Goronen-Opal", + "109": "Goronen-Rubin", "110": "Zora-Saphir", "111": "Stein des Wissens", "112": "Gerudo-Paß", @@ -136,8 +136,8 @@ "117": "Kompaß", "118": "Labyrinth-Karte", "119": "Kleiner Schlüssel", - "120": "MAGIE KLEIN", - "121": "MAGIE GROß", + "120": "Kleine Magieflasche", + "121": "Große Magieflasche", "122": "Biggoron-Schwert", "123": "UNGÜLTIG 1", "124": "UNGÜLTIG 2", @@ -154,24 +154,24 @@ "135": "50 Rubine", "136": "200 Rubine", "137": "UNGÜLTIG 8", - "138": "STÄBE 5", - "139": "STÄBE 10", - "140": "NÜSSE 5", - "141": "NÜSSE 10", + "138": "DEKU-STÄBE 5", + "139": "DEKU-STÄBE 10", + "140": "DEKU-NÜSSE 5", + "141": "DEKU-NÜSSE 10", "142": "BOMBEN 5", "143": "BOMBEN 10", "144": "BOMBEN 20", "145": "BOMBEN 30", - "146": "PFEILE KLEIN", - "147": "PFEILE MITTEL", - "148": "PFEILE GROß", - "149": "KERNE 30", + "146": "PFEILE 5", + "147": "PFEILE 10", + "148": "PFEILE 30", + "149": "DEKU-KERNE 30", "150": "KRABBELMINEN 5", "151": "KRABBELMINEN 20", - "152": "STAB UPGRADE 20", - "153": "STAB UPGRADE 30", - "154": "NUß UPGRADE 30", - "155": "NUß UPGRADE 40", + "152": "DEKU-STAB-KAPAZITÄT 20", + "153": "DEKU-STAB-KAPAZITÄT 30", + "154": "DEKU-NUẞ-KAPAZITÄT 30", + "155": "DEKU-NUẞ-KAPAZITÄT 40", "255": "", "256": "Gespensterwüste", "257": "Gerudo-Festung", diff --git a/soh/assets/custom/accessibility/texts/scenes_ger.json b/soh/assets/custom/accessibility/texts/scenes_ger.json index a3f7370e0..5f7da173c 100644 --- a/soh/assets/custom/accessibility/texts/scenes_ger.json +++ b/soh/assets/custom/accessibility/texts/scenes_ger.json @@ -9,7 +9,7 @@ "7": "Schattentempel", "8": "Grund des Brunnens", "9": "Eishöhle", - "10": "", // Treppe zu Ganondorfs Verließ (Keine Title-Card) + "10": "", // Treppe zu Ganondorfs Verlies (Keine Title-Card) "11": "Gerudo-Arena", "12": "Diebesversteck", "13": "Ganons Schloß", @@ -22,7 +22,7 @@ "20": "Reitendes Unheil - Phantom-Ganon", "21": "Subterraner Lavadrachoid - Volvagia", "22": "Aquamöbes Wassertentakel - Morpha", - "23": "Höllische Hexenarmada - Killa Ohmaz", + "23": "Höllische Hexenarmada - Twinrova", "24": "Bestialische Schattenmonstrosität - Bongo Bongo", "25": "Großmeister des Bösen - Ganondorf", "26": "", @@ -109,4 +109,4 @@ "107": "", "108": "", // Debug: SRD Raum (Keine Title-Card) "109": "" // Debug: Schatzkisten Teleport (Keine Title-Card) -} \ No newline at end of file +} diff --git a/soh/assets/custom/presets/Main Enhanced.json b/soh/assets/custom/presets/Main Enhanced.json index 5e63d651f..eabda809f 100644 --- a/soh/assets/custom/presets/Main Enhanced.json +++ b/soh/assets/custom/presets/Main Enhanced.json @@ -16,6 +16,7 @@ "EnemySpawnsOverWaterboxes": 1, "FasterRupeeAccumulator": 1, "FixBrokenGiantsKnife": 1, + "FixDampeGoingBackwards": 1, "FixDaruniaDanceSpeed": 1, "FixDungeonMinimapIcon": 1, "FixEyesOpenWhileSleeping": 1, diff --git a/soh/assets/custom/presets/Main Randomizer.json b/soh/assets/custom/presets/Main Randomizer.json index 7ece7315a..2982a8b72 100644 --- a/soh/assets/custom/presets/Main Randomizer.json +++ b/soh/assets/custom/presets/Main Randomizer.json @@ -45,6 +45,7 @@ "FishNeverEscape": 1, "FixBrokenGiantsKnife": 1, "FixDaruniaDanceSpeed": 1, + "FixDampeGoingBackwards": 1, "FixDungeonMinimapIcon": 1, "FixFloorSwitches": 1, "FixHammerHand": 1, diff --git a/soh/assets/custom/presets/Main Vanilla+.json b/soh/assets/custom/presets/Main Vanilla+.json index 0f6c1741a..1ac97a567 100644 --- a/soh/assets/custom/presets/Main Vanilla+.json +++ b/soh/assets/custom/presets/Main Vanilla+.json @@ -17,6 +17,7 @@ "FasterRupeeAccumulator": 1, "FixBrokenGiantsKnife": 1, "FixDaruniaDanceSpeed": 1, + "FixDampeGoingBackwards": 1, "FixDungeonMinimapIcon": 1, "FixEyesOpenWhileSleeping": 1, "FixFloorSwitches": 1, diff --git a/soh/assets/custom/presets/Rando Hell Mode.json b/soh/assets/custom/presets/Rando Hell Mode.json index d42727127..cdcceb451 100644 --- a/soh/assets/custom/presets/Rando Hell Mode.json +++ b/soh/assets/custom/presets/Rando Hell Mode.json @@ -34,6 +34,7 @@ "ShopsanityPrices": 2, "Shuffle100GSReward": 1, "ShuffleAdultTrade": 1, + "ShuffleBeanFairies": 1, "ShuffleBeehives": 1, "ShuffleBossEntrances": 2, "ShuffleBossSouls": 2, @@ -43,8 +44,9 @@ "ShuffleDekuNutBag": 1, "ShuffleDekuStickBag": 1, "ShuffleDungeonsEntrances": 2, - "ShuffleFairies": 1, + "ShuffleFairySpots": 1, "ShuffleFishingPole": 1, + "ShuffleFountainFairies": 1, "ShuffleFreestanding": 3, "ShuffleFrogSongRupees": 1, "ShuffleGanonBossKey": 9, @@ -63,6 +65,7 @@ "ShufflePots": 3, "ShuffleScrubs": 2, "ShuffleSongs": 2, + "ShuffleStoneFairies": 1, "ShuffleSwim": 1, "ShuffleTokens": 3, "ShuffleWarpSongs": 1, diff --git a/soh/include/functions.h b/soh/include/functions.h index a53a463fb..c3d7b4c30 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -10,7 +10,7 @@ extern "C" { #endif -#include "luslog.h" +#include #include #if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG) diff --git a/soh/include/macros.h b/soh/include/macros.h index 325fb91b6..acac5cd49 100644 --- a/soh/include/macros.h +++ b/soh/include/macros.h @@ -1,7 +1,7 @@ #ifndef MACROS_H #define MACROS_H -#include +#include // Upstream TODO: Document reasoning for change // #ifndef __GNUC__ diff --git a/soh/include/z64.h b/soh/include/z64.h index 511c06cd3..acb693ac5 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -1522,7 +1522,7 @@ typedef struct { /* 0x34 */ s32 isEnabled; } StickDirectionPrompt; -typedef struct { +typedef struct FileChooseContext { /* 0x00000 */ GameState state; /* 0x000A4 */ Vtx* windowVtx; /* 0x000A8 */ u8* staticSegment; diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index c562b820f..cbd82fcf2 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -5,7 +5,7 @@ extern "C" { #endif -#include +#include #define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 1ddf34750..8fd253b5d 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -7,7 +7,7 @@ #include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/gameplaystats.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" -#include "soh/Enhancements/boss-rush/BossRushTypes.h" +#include "soh/Enhancements/boss-rush/BossRush.h" typedef enum { /* 0x0 */ MAGIC_STATE_IDLE, // Regular gameplay diff --git a/soh/soh/CrashHandlerExt.cpp b/soh/soh/CrashHandlerExt.cpp index cc9c7b1ee..3ca821460 100644 --- a/soh/soh/CrashHandlerExt.cpp +++ b/soh/soh/CrashHandlerExt.cpp @@ -19,7 +19,7 @@ static std::array sCatToStrArray{ "SWITCH", "BG", "PLAYER", "EXPLOSIVE", "NPC", "ENEMY", "PROP", "ITEMACTION", "MISC", "BOSS", "DOOR", "CHEST", }; -#define DEFINE_SCENE(_1, _2, enumName, _4, _5, _6) #enumName +#define DEFINE_SCENE(_1, _2, enumName, _4, _5, _6) #enumName, static std::array sSceneIdToStrArray{ #include "tables/scene_table.h" diff --git a/soh/soh/Enhancements/BonkDamage.cpp b/soh/soh/Enhancements/BonkDamage.cpp new file mode 100644 index 000000000..c9e5e089a --- /dev/null +++ b/soh/soh/Enhancements/BonkDamage.cpp @@ -0,0 +1,51 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "./enhancementTypes.h" + +extern "C" { +#include "functions.h" +#include "macros.h" +extern PlayState* gPlayState; +extern SaveContext gSaveContext; +} + +void RegisterBonkDamage() { + COND_HOOK(OnPlayerBonk, CVarGetInteger(CVAR_ENHANCEMENT("BonkDamageMult"), BONK_DAMAGE_NONE) != BONK_DAMAGE_NONE, + [] { + uint16_t bonkDamage = 0; + switch (CVarGetInteger(CVAR_ENHANCEMENT("BonkDamageMult"), BONK_DAMAGE_NONE)) { + case BONK_DAMAGE_NONE: + return; + case BONK_DAMAGE_OHKO: + gSaveContext.health = 0; + return; + case BONK_DAMAGE_QUARTER_HEART: + bonkDamage = 4; + break; + case BONK_DAMAGE_HALF_HEART: + bonkDamage = 8; + break; + case BONK_DAMAGE_1_HEART: + bonkDamage = 16; + break; + case BONK_DAMAGE_2_HEARTS: + bonkDamage = 32; + break; + case BONK_DAMAGE_4_HEARTS: + bonkDamage = 64; + break; + case BONK_DAMAGE_8_HEARTS: + bonkDamage = 128; + break; + default: + break; + } + + Health_ChangeBy(gPlayState, -bonkDamage); + // Set invincibility to make Link flash red as a visual damage indicator. + Player* player = GET_PLAYER(gPlayState); + player->invincibilityTimer = 28; + }); +} + +static RegisterShipInitFunc initFunc(RegisterBonkDamage, { CVAR_ENHANCEMENT("BonkDamageMult") }); diff --git a/soh/soh/Enhancements/BootToDebugWarpScreen.cpp b/soh/soh/Enhancements/BootToDebugWarpScreen.cpp index a2b8c6b60..dc0f1899b 100644 --- a/soh/soh/Enhancements/BootToDebugWarpScreen.cpp +++ b/soh/soh/Enhancements/BootToDebugWarpScreen.cpp @@ -42,6 +42,5 @@ void RegisterBootToDebugWarpScreen() { OnZTitleUpdateBootToDebugWarpScreen); } -static RegisterShipInitFunc initFunc_BootToDebugWarpScreen(RegisterBootToDebugWarpScreen, - { CVAR_DEBUG_ENABLED_NAME, - CVAR_BOOT_TO_DEBUG_WARP_SCREEN_NAME }); +static RegisterShipInitFunc initFunc(RegisterBootToDebugWarpScreen, + { CVAR_DEBUG_ENABLED_NAME, CVAR_BOOT_TO_DEBUG_WARP_SCREEN_NAME }); diff --git a/soh/soh/Enhancements/Cheats/NoKeeseGuayTarget.cpp b/soh/soh/Enhancements/Cheats/NoKeeseGuayTarget.cpp index 911f3cd25..3616191ca 100644 --- a/soh/soh/Enhancements/Cheats/NoKeeseGuayTarget.cpp +++ b/soh/soh/Enhancements/Cheats/NoKeeseGuayTarget.cpp @@ -20,4 +20,4 @@ void RegisterNoKeeseGuayTarget() { COND_VB_SHOULD(VB_GUAY_FORCE_FLY_AWAY, CVAR_NOKEESEGUAYTARGET_VALUE, { *should = true; }); } -static RegisterShipInitFunc initFunc_NoKeeseGuayTarget(RegisterNoKeeseGuayTarget, { CVAR_NOKEESEGUAYTARGET_NAME }); +static RegisterShipInitFunc initFunc(RegisterNoKeeseGuayTarget, { CVAR_NOKEESEGUAYTARGET_NAME }); diff --git a/soh/soh/Enhancements/Cheats/NoRedeadFreeze.cpp b/soh/soh/Enhancements/Cheats/NoRedeadFreeze.cpp index ccc406104..7ed245234 100644 --- a/soh/soh/Enhancements/Cheats/NoRedeadFreeze.cpp +++ b/soh/soh/Enhancements/Cheats/NoRedeadFreeze.cpp @@ -14,4 +14,4 @@ void RegisterNoRedeadFreeze() { COND_VB_SHOULD(VB_REDEAD_GIBDO_FREEZE_LINK, CVAR_NOREDEADFREEZE_VALUE, { *should = false; }); } -static RegisterShipInitFunc initFunc_NoRedeadFreeze(RegisterNoRedeadFreeze, { CVAR_NOREDEADFREEZE_NAME }); +static RegisterShipInitFunc initFunc(RegisterNoRedeadFreeze, { CVAR_NOREDEADFREEZE_NAME }); diff --git a/soh/soh/Enhancements/DisableSandstorm.cpp b/soh/soh/Enhancements/DisableSandstorm.cpp new file mode 100644 index 000000000..a13fd4fb5 --- /dev/null +++ b/soh/soh/Enhancements/DisableSandstorm.cpp @@ -0,0 +1,16 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ShipInit.hpp" + +extern "C" PlayState* gPlayState; + +void DisableSandstormAfterTransition(int16_t sceneNum) { + if (sceneNum == SCENE_HAUNTED_WASTELAND) { + gPlayState->envCtx.sandstormState = SANDSTORM_OFF; + } +} + +void RegisterDisableSandstorm() { + COND_HOOK(OnTransitionEnd, CVarGetInteger(CVAR_CHEAT("DisableSandstorm"), 0), DisableSandstormAfterTransition); +} + +static RegisterShipInitFunc initFunc(RegisterDisableSandstorm, { CVAR_CHEAT("DisableSandstorm") }); diff --git a/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp b/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp index 277868b20..20bdc16bc 100644 --- a/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp +++ b/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp @@ -40,4 +40,4 @@ void RegisterRupeeDash() { COND_HOOK(OnPlayerUpdate, CVAR_RUPEE_DASH_VALUE, UpdateRupeeDash); } -static RegisterShipInitFunc initFunc_RupeeDash(RegisterRupeeDash, { CVAR_RUPEE_DASH_NAME }); +static RegisterShipInitFunc initFunc(RegisterRupeeDash, { CVAR_RUPEE_DASH_NAME }); diff --git a/soh/soh/Enhancements/ExtraModes/ShadowTag.cpp b/soh/soh/Enhancements/ExtraModes/ShadowTag.cpp index dc85534c8..1b03b6c77 100644 --- a/soh/soh/Enhancements/ExtraModes/ShadowTag.cpp +++ b/soh/soh/Enhancements/ExtraModes/ShadowTag.cpp @@ -47,4 +47,4 @@ void RegisterShadowTag() { COND_HOOK(OnSceneInit, true, [](int16_t) { ResetShadowTagSpawnTimer(); }); } -static RegisterShipInitFunc initFunc_ShadowTag(RegisterShadowTag, { CVAR_SHADOW_TAG_NAME }); +static RegisterShipInitFunc initFunc(RegisterShadowTag, { CVAR_SHADOW_TAG_NAME }); diff --git a/soh/soh/Enhancements/Graphics/Disable2DBackgrounds.cpp b/soh/soh/Enhancements/Graphics/Disable2DBackgrounds.cpp new file mode 100644 index 000000000..253e0abd2 --- /dev/null +++ b/soh/soh/Enhancements/Graphics/Disable2DBackgrounds.cpp @@ -0,0 +1,161 @@ +#include +#include "soh/Enhancements/enhancementTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +#include "macros.h" +#include "variables.h" +} + +#define CVAR_NAME CVAR_ENHANCEMENT("3DSceneRender") +#define CVAR_VALUE CVarGetInteger(CVAR_NAME, 0) + +std::vector fogControlList = { + SCENE_MARKET_ENTRANCE_DAY, + SCENE_MARKET_ENTRANCE_NIGHT, + SCENE_MARKET_ENTRANCE_RUINS, + SCENE_BACK_ALLEY_DAY, + SCENE_BACK_ALLEY_NIGHT, + SCENE_MARKET_DAY, + SCENE_MARKET_NIGHT, + SCENE_MARKET_RUINS, + SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, + SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT, + SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS, + SCENE_KNOW_IT_ALL_BROS_HOUSE, + SCENE_TWINS_HOUSE, + SCENE_MIDOS_HOUSE, + SCENE_SARIAS_HOUSE, + SCENE_BACK_ALLEY_HOUSE, + SCENE_BAZAAR, + SCENE_KOKIRI_SHOP, + SCENE_GORON_SHOP, + SCENE_ZORA_SHOP, + SCENE_POTION_SHOP_KAKARIKO, + SCENE_POTION_SHOP_MARKET, + SCENE_BOMBCHU_SHOP, + SCENE_HAPPY_MASK_SHOP, + SCENE_LINKS_HOUSE, + SCENE_DOG_LADY_HOUSE, + SCENE_STABLE, + SCENE_IMPAS_HOUSE, + SCENE_CARPENTERS_TENT, + SCENE_GRAVEKEEPERS_HUT, +}; + +std::vector skyboxSceneControlList = { + SCENE_MARKET_ENTRANCE_DAY, + SCENE_MARKET_ENTRANCE_NIGHT, + SCENE_MARKET_ENTRANCE_RUINS, + SCENE_BACK_ALLEY_DAY, + SCENE_BACK_ALLEY_NIGHT, + SCENE_MARKET_DAY, + SCENE_MARKET_NIGHT, + SCENE_MARKET_RUINS, + SCENE_CASTLE_COURTYARD_ZELDA, + SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, + SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT, + SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS, + SCENE_FOREST_TEMPLE, +}; + +std::vector skyboxIdControlList = { + SKYBOX_BAZAAR, + SKYBOX_HOUSE_LINK, + SKYBOX_MARKET_ADULT, + SKYBOX_MARKET_CHILD_DAY, + SKYBOX_MARKET_CHILD_NIGHT, + SKYBOX_HAPPY_MASK_SHOP, + SKYBOX_HOUSE_KNOW_IT_ALL_BROTHERS, + SKYBOX_HOUSE_OF_TWINS, + SKYBOX_STABLES, + SKYBOX_HOUSE_KAKARIKO, + SKYBOX_KOKIRI_SHOP, + SKYBOX_GORON_SHOP, + SKYBOX_ZORA_SHOP, + SKYBOX_POTION_SHOP_KAKARIKO, + SKYBOX_POTION_SHOP_MARKET, + SKYBOX_HOUSE_RICHARD, + SKYBOX_HOUSE_IMPA, + SKYBOX_TENT, + SKYBOX_HOUSE_MIDO, + SKYBOX_HOUSE_SARIA, + SKYBOX_HOUSE_ALLEY, +}; + +void Register3DPreRenderedScenes() { + COND_HOOK(AfterSceneCommands, CVAR_VALUE, [](int16_t sceneNum) { + // Check if this scene is in the skyboxControlList + bool shouldControlSkybox = false; + for (const auto& scene : skyboxSceneControlList) { + if (sceneNum == scene) { + shouldControlSkybox = true; + break; + } + } + + if (shouldControlSkybox) { + // Add a skybox on scenes from skyboxSceneControlList + gPlayState->envCtx.skyboxDisabled = false; + + // Replace skybox with normal sky + gPlayState->skyboxId = SKYBOX_NORMAL_SKY; + // Apply the always cloudy skybox as an adult for Temple of Time and the Market + if (sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS || sceneNum == SCENE_MARKET_RUINS || + sceneNum == SCENE_MARKET_ENTRANCE_RUINS) { + gWeatherMode = 3; + } + } + }); + + COND_HOOK(OnPlayDrawBegin, CVAR_VALUE, []() { + if (!CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0)) { + return; + } + + for (auto& scene : fogControlList) { + if (scene == gPlayState->sceneNum) { + if ((HREG(80) != 10) || (HREG(82) != 0)) { + // Furthest possible fog and zFar + gPlayState->view.zFar = 12800; + gPlayState->lightCtx.fogNear = 996; // Set to 1000 to complete disable fog entirely + gPlayState->lightCtx.fogFar = 12800; + // General gray fog color + gPlayState->lightCtx.fogColor[0] = 100; + gPlayState->lightCtx.fogColor[1] = 100; + gPlayState->lightCtx.fogColor[2] = 100; + } + break; + } + } + }); + REGISTER_VB_SHOULD(VB_DRAW_2D_BACKGROUND, { + if (CVAR_VALUE) { + *should = false; + return; + } + }); + + REGISTER_VB_SHOULD(VB_LOAD_SKYBOX, { + if (!gPlayState) { + return; + } + + if (!CVAR_VALUE) { + return; + } + + for (auto& skybox : skyboxIdControlList) { + if (gPlayState->skyboxCtx.skyboxId == skybox) { + gPlayState->skyboxCtx.unk_140 = 0; + *should = false; + return; + } + } + }); +} + +static RegisterShipInitFunc initFunc(Register3DPreRenderedScenes, { CVAR_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/Presets/Presets.cpp b/soh/soh/Enhancements/Presets/Presets.cpp index b84cb95ca..058d5a2cd 100644 --- a/soh/soh/Enhancements/Presets/Presets.cpp +++ b/soh/soh/Enhancements/Presets/Presets.cpp @@ -2,11 +2,11 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include "soh/OTRGlobals.h" #include "soh/SohGui/MenuTypes.h" #include "soh/SohGui/SohMenu.h" @@ -395,7 +395,7 @@ void PresetsCustomWidget(WidgetInfo& info) { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::AlignTextToFramePadding(); - ImGui::Text(name.c_str()); + ImGui::Text("%s", name.c_str()); for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) { ImGui::TableNextColumn(); DrawSectionCheck(name, !info.presetValues["blocks"].contains(blockInfo[i].names[1]), &info.apply[i], @@ -437,10 +437,12 @@ void PresetsCustomWidget(WidgetInfo& info) { void RegisterPresetsWidgets() { SohGui::mSohMenu->AddSidebarEntry("Settings", "Presets", 1); WidgetPath path = { "Settings", "Presets", SECTION_COLUMN_1 }; - SohGui::mSohMenu->AddWidget(path, "PresetsWidget", WIDGET_CUSTOM).CustomFunction(PresetsCustomWidget); + SohGui::mSohMenu->AddWidget(path, "PresetsWidget", WIDGET_CUSTOM) + .CustomFunction(PresetsCustomWidget) + .HideInSearch(true); presetFolder = Ship::Context::GetInstance()->GetPathRelativeToAppDirectory("presets"); std::fill_n(saveSection, PRESET_SECTION_MAX, true); LoadPresets(); } -static RegisterMenuInitFunc initFunc(RegisterPresetsWidgets); +static RegisterMenuInitFunc menuInitFunc(RegisterPresetsWidgets); diff --git a/soh/soh/Enhancements/QoL/DaytimeGS.cpp b/soh/soh/Enhancements/QoL/DaytimeGS.cpp index fabf7457b..6d4474274 100644 --- a/soh/soh/Enhancements/QoL/DaytimeGS.cpp +++ b/soh/soh/Enhancements/QoL/DaytimeGS.cpp @@ -66,4 +66,4 @@ void RegisterDaytimeGoldSkultullas() { COND_HOOK(OnSceneSpawnActors, CVAR_DAYTIME_GS_VALUE, OnSpawnNighttimeGoldSkulltula); } -static RegisterShipInitFunc initFunc_DaytimeGoldSkulltulas(RegisterDaytimeGoldSkultullas, { CVAR_DAYTIME_GS_NAME }); +static RegisterShipInitFunc initFunc(RegisterDaytimeGoldSkultullas, { CVAR_DAYTIME_GS_NAME }); diff --git a/soh/soh/Enhancements/Restorations/GraveHoleJumps.cpp b/soh/soh/Enhancements/Restorations/GraveHoleJumps.cpp new file mode 100644 index 000000000..525d30dc2 --- /dev/null +++ b/soh/soh/Enhancements/Restorations/GraveHoleJumps.cpp @@ -0,0 +1,72 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "functions.h" +#include "soh/Enhancements/enhancementTypes.h" +#include "soh/resource/type/Scene.h" +#include "soh/resource/type/scenecommand/SceneCommand.h" +#include "soh/resource/type/scenecommand/SetCollisionHeader.h" + +#define CVAR_GRAVE_HOLE_NAME CVAR_ENHANCEMENT("GraveHoles") +#define GRAVE_HOLES_DEFAULT 0 +#define CVAR_GRAVE_HOLE_VALUE CVarGetInteger(CVAR_GRAVE_HOLE_NAME, GRAVE_HOLES_DEFAULT) +#define GRAVEYARD_SCENE_FILEPATH "scenes/shared/spot02_scene/spot02_scene" +#define CUSTOM_SURFACE_TYPE 32 + +const static std::array, std::pair>, 6> graveyardGeometryPatches = { { + // { { startPolygon, endPolygon }, { originalSurfaceType, patchedSurfaceType } } + { { 487, 509 }, { 20, CUSTOM_SURFACE_TYPE } }, // Floor around graves + { { 651, 658 }, { 20, CUSTOM_SURFACE_TYPE } }, // Floor around Royal Family Tomb + { { 613, 620 }, { 0, 15 } }, // Grave ledges (Hylian Shield) + { { 623, 630 }, { 0, 15 } }, // Grave ledges (Redead) + { { 633, 640 }, { 0, 15 } }, // Grave ledges (Dampe) + { { 643, 650 }, { 0, 15 } }, // Grave ledges (Royal Family) +} }; + +CollisionHeader* getGraveyardCollisionHeader() { + /* + * Load the graveyard collision header manually. Since its position varies between versions, we cannot directly use + * dspot02_sceneCollisionHeader_003C54. We have to scroll through the scene cmds to get the header the same way the + * game does. + */ + SOH::Scene* scene = + (SOH::Scene*)Ship::Context::GetInstance()->GetResourceManager()->LoadResource(GRAVEYARD_SCENE_FILEPATH).get(); + SOH::ISceneCommand* sceneCmd = nullptr; + for (int i = 0; i < scene->commands.size(); i++) { + auto cmd = scene->commands[i]; + if (cmd->cmdId == SOH::SceneCommandID::SetCollisionHeader) { + sceneCmd = cmd.get(); + break; + } + } + CollisionHeader* graveyardColHeader = (CollisionHeader*)((SOH::SetCollisionHeader*)sceneCmd)->GetRawPointer(); + + /* + * Copy the surface type list and give ourselves some extra space to create another surface type for Link to fall + * into graves. NTSC 1.0's graveyard has 31 surface types, while later versions have 32. The contents of the lists + * are shifted somewhat between versions, so to be safe we just create an extra slot that is not in any version. + */ + static SurfaceType newSurfaceTypes[33]; + memcpy(newSurfaceTypes, graveyardColHeader->surfaceTypeList, sizeof(SurfaceType) * 33); + newSurfaceTypes[CUSTOM_SURFACE_TYPE].data[0] = 0x24000004; + newSurfaceTypes[CUSTOM_SURFACE_TYPE].data[1] = 0xFC8; + graveyardColHeader->surfaceTypeList = newSurfaceTypes; + + return graveyardColHeader; +} + +void ApplyGraveyardGeometryPatches() { + static CollisionHeader* graveyardColHeader = getGraveyardCollisionHeader(); + for (auto& mappingPatch : graveyardGeometryPatches) { + for (int i = mappingPatch.first.first; i <= mappingPatch.first.second; i++) { + CollisionPoly* poly = &graveyardColHeader->polyList[i]; + poly->type = CVAR_GRAVE_HOLE_VALUE ? mappingPatch.second.first : mappingPatch.second.second; + } + } +} + +void RegisterGraveHoleJumps() { + ApplyGraveyardGeometryPatches(); +} + +static RegisterShipInitFunc initFunc(RegisterGraveHoleJumps, { CVAR_GRAVE_HOLE_NAME }); diff --git a/soh/soh/Enhancements/Restorations/N64WeirdFrames/N64WeirdFrames.cpp b/soh/soh/Enhancements/Restorations/N64WeirdFrames/N64WeirdFrames.cpp index 0e6b1cbf3..33bf12c3c 100644 --- a/soh/soh/Enhancements/Restorations/N64WeirdFrames/N64WeirdFrames.cpp +++ b/soh/soh/Enhancements/Restorations/N64WeirdFrames/N64WeirdFrames.cpp @@ -1,4 +1,4 @@ -#include "public/bridge/consolevariablebridge.h" +#include #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/ShipInit.hpp" diff --git a/soh/soh/Enhancements/Restorations/N64WeirdFrames/WeirdAnimation.cpp b/soh/soh/Enhancements/Restorations/N64WeirdFrames/WeirdAnimation.cpp index bd812c658..c4cbc4bfe 100644 --- a/soh/soh/Enhancements/Restorations/N64WeirdFrames/WeirdAnimation.cpp +++ b/soh/soh/Enhancements/Restorations/N64WeirdFrames/WeirdAnimation.cpp @@ -1,7 +1,7 @@ #include "WeirdAnimation.h" -#include "resource/ResourceManager.h" -#include "Context.h" +#include +#include #include #include diff --git a/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp b/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp new file mode 100644 index 000000000..7c56fab24 --- /dev/null +++ b/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp @@ -0,0 +1,30 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h" +} + +#define CVAR_WIDE_SHUTTER_DOOR_RANGE CVAR_ENHANCEMENT("WideShutterDoorRange") +#define WIDE_SHUTTER_DOOR_RANGE_DEFAULT 0 +#define CVAR_WIDE_SHUTTER_DOOR_RANGE_VALUE CVarGetInteger(CVAR_WIDE_SHUTTER_DOOR_RANGE, WIDE_SHUTTER_DOOR_RANGE_DEFAULT) + +// The X range is 70 on NTSC 1.0 and 50 in later versions. The Y range is 15 in any version. +// https://github.com/zeldaret/oot/blob/6ecb84097c1a9a8426f3815c84aa6a5d49ad5804/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c#L248-L259 +#define SHUTTER_DOOR_RANGE_X 70 +#define SHUTTER_DOOR_RANGE_Y 15 + +void RegisterWideShutterDoorRange() { + COND_VB_SHOULD(VB_BE_NEAR_DOOR_SHUTTER, CVAR_WIDE_SHUTTER_DOOR_RANGE_VALUE, { + DoorShutter* doorShutter = va_arg(args, DoorShutter*); + Vec3f relPlayerPos = *va_arg(args, Vec3f*); + // Jabu-Jabu door, Phantom Ganon bars, Gohma door, or boss door + if (doorShutter->unk_16C == 3 || doorShutter->unk_16C == 4 || doorShutter->unk_16C == 5 || + doorShutter->unk_16C == 7) { + *should = (SHUTTER_DOOR_RANGE_X < fabsf(relPlayerPos.x) || SHUTTER_DOOR_RANGE_Y < fabsf(relPlayerPos.y)); + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterWideShutterDoorRange, { CVAR_WIDE_SHUTTER_DOOR_RANGE }); diff --git a/soh/soh/Enhancements/TimeSavers/CrawlSpeed.cpp b/soh/soh/Enhancements/TimeSavers/CrawlSpeed.cpp index 896f07973..2b8794978 100644 --- a/soh/soh/Enhancements/TimeSavers/CrawlSpeed.cpp +++ b/soh/soh/Enhancements/TimeSavers/CrawlSpeed.cpp @@ -1,4 +1,5 @@ #include +#include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" #include "global.h" @@ -102,9 +103,18 @@ void CrawlSpeed_Register() { COND_VB_SHOULD(VB_CRAWL_SPEED_INCREASE, shouldRegister, { Player* player = GET_PLAYER(gPlayState); - IncreaseCrawlSpeed(player, gPlayState); - *should = false; + bool isMQ = ResourceMgr_IsGameMasterQuest(); + bool boulderExists = !Flags_GetSwitch(gPlayState, 5); + bool excludeSpiritMQBoulder = + (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE && player->actor.world.pos.z < -545.0f && + player->actor.world.pos.z > -630.0f && isMQ && boulderExists); + if (excludeSpiritMQBoulder) { + *should = true; + } else { + IncreaseCrawlSpeed(player, gPlayState); + *should = false; + } }); } -static RegisterShipInitFunc initSpeed(CrawlSpeed_Register, { CVAR_CRAWL_SPEED_NAME }); \ No newline at end of file +static RegisterShipInitFunc initFunc(CrawlSpeed_Register, { CVAR_CRAWL_SPEED_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp index cc136b14f..29b56e87b 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp @@ -2,6 +2,7 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/randomizer/context.h" #include "soh/ShipInit.hpp" +#include "soh/Enhancements/timesaver_hook_handlers.h" extern "C" { #include "macros.h" @@ -10,7 +11,9 @@ extern "C" { #include "functions.h" #include "variables.h" } +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get() +extern "C" PlayState* gPlayState; static bool sEnteredBlueWarp = false; // Todo: Move item queueing here @@ -64,7 +67,16 @@ void RegisterSkipBlueWarp() { * to the player instead. */ COND_VB_SHOULD(VB_GIVE_ITEM_FROM_BLUE_WARP, - CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), { *should = false; }); + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), { + if (IS_VANILLA) { + if (gPlayState->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { + TimeSaverQueueItem(RG_SHADOW_MEDALLION); + } else if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { + TimeSaverQueueItem(RG_SPIRIT_MEDALLION); + } + } + *should = false; + }); } void RegisterShouldPlayBlueWarp() { @@ -156,8 +168,9 @@ void RegisterShouldPlayBlueWarp() { } // This is outside the above condition because we want to handle both first and following visits to the blue - // warp - if (sEnteredBlueWarp && overrideBlueWarpDestinations) { + // warp. Jabu's blue warp doesn't call VB_PLAY_BLUE_WARP_CS without Ruto + if ((sEnteredBlueWarp || gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP) && + overrideBlueWarpDestinations) { Entrance_OverrideBlueWarp(); } } diff --git a/soh/soh/Enhancements/audio/AudioCollection.cpp b/soh/soh/Enhancements/audio/AudioCollection.cpp index d3f69dad8..ab7a8d95a 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.cpp +++ b/soh/soh/Enhancements/audio/AudioCollection.cpp @@ -2,8 +2,9 @@ #include "sequence.h" #include "sfx.h" #include "soh/cvar_prefixes.h" +#include "soh/Notification/Notification.h" #include -#include +#include #include #include #include @@ -458,3 +459,11 @@ extern "C" bool AudioCollection_HasSequenceNum(uint16_t seqId) { extern "C" size_t AudioCollection_SequenceMapSize() { return AudioCollection::Instance->SequenceMapSize(); } + +extern "C" void AudioCollection_EmitSongNameNotification(s32 seqId) { + const char* sequenceName = AudioCollection_GetSequenceName(seqId); + if (sequenceName != NULL) { + Notification::Emit({ .message = "Currently playing: " + std::string(sequenceName), + .remainingTime = (float)CVarGetInteger(CVAR_AUDIO("SeqNameOverlayDuration"), 5) }); + } +} \ No newline at end of file diff --git a/soh/soh/Enhancements/audio/AudioCollection.h b/soh/soh/Enhancements/audio/AudioCollection.h index 2cdb02e21..51a6902cf 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.h +++ b/soh/soh/Enhancements/audio/AudioCollection.h @@ -73,4 +73,5 @@ void AudioCollection_AddToCollection(char* otrPath, uint16_t seqNum); const char* AudioCollection_GetSequenceName(uint16_t seqId); bool AudioCollection_HasSequenceNum(uint16_t seqId); size_t AudioCollection_SequenceMapSize(); +void AudioCollection_EmitSongNameNotification(s32 seqId); #endif \ No newline at end of file diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index 6660bee7d..be6acae73 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -10,8 +10,8 @@ #include "../randomizer/3drando/random.hpp" #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" -#include -#include "soh/SohGui/UIWidgets.hpp" +#include +#include "soh/SohGui/SohMenu.h" #include "soh/SohGui/SohGui.hpp" #include "AudioCollection.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" @@ -25,6 +25,23 @@ Vec3f pos = { 0.0f, 0.0f, 0.0f }; f32 freqScale = 1.0f; s8 reverbAdd = 0; +using namespace UIWidgets; + +static WidgetInfo lowHpAlarm; +static WidgetInfo naviCall; +static WidgetInfo enemyProx; +static WidgetInfo leadingMusic; +static WidgetInfo displaySeqName; +static WidgetInfo ovlDuration; +static WidgetInfo voicePitch; +static WidgetInfo randoMusicOnSceneChange; +static WidgetInfo randomAudioOnSeedGen; +static WidgetInfo lowerOctaves; + +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + // Authentic sequence counts // used to ensure we have enough to shuffle #define SEQ_COUNT_BGM_WORLD 30 @@ -468,8 +485,17 @@ void AudioEditorRegisterOnSceneInitHook() { }); } +void AudioEditorRegisterOnGenerationCompletionHook() { + GameInteractor::Instance->RegisterGameHook([]() { + if (CVarGetInteger(CVAR_AUDIO("RandomizeAllOnRandoGen"), 0)) { + AudioEditor_RandomizeAll(); + } + }); +} + void AudioEditor::InitElement() { AudioEditorRegisterOnSceneInitHook(); + AudioEditorRegisterOnGenerationCompletionHook(); } void AudioEditor::DrawElement() { @@ -518,69 +544,22 @@ void AudioEditor::DrawElement() { ImGui::TableNextRow(); ImGui::TableNextColumn(); if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) { - UIWidgets::CVarCheckbox( - "Mute Low HP Alarm", CVAR_AUDIO("LowHpAlarm"), - UIWidgets::CheckboxOptions().Color(THEME_COLOR).Tooltip("Disable the low HP beeping sound.")); - UIWidgets::CVarCheckbox("Disable Navi Call Audio", CVAR_AUDIO("DisableNaviCallAudio"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Disables the voice audio when Navi calls you.")); - UIWidgets::CVarCheckbox( - "Disable Enemy Proximity Music", CVAR_AUDIO("EnemyBGMDisable"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Disables the music change when getting close to enemies. Useful for hearing " - "your custom music for each scene more often.")); - UIWidgets::CVarCheckbox( - "Disable Leading Music in Lost Woods", CVAR_AUDIO("LostWoodsConsistentVolume"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Disables the volume shifting in the Lost Woods. Useful for hearing " - "your custom music in the Lost Woods if you don't need the navigation assitance " - "the volume changing provides. If toggling this while in the Lost Woods, reload " - "the area for the effect to kick in.")); - UIWidgets::CVarCheckbox( - "Display Sequence Name on Overlay", CVAR_AUDIO("SeqNameOverlay"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Displays the name of the current sequence in the corner of the screen whenever a new " - "sequence " - "is loaded to the main sequence player (does not apply to fanfares or enemy BGM).")); - UIWidgets::CVarSliderInt("Overlay Duration: %d seconds", CVAR_AUDIO("SeqNameOverlayDuration"), - UIWidgets::IntSliderOptions() - .Min(1) - .Max(10) - .DefaultValue(5) - .Size(ImVec2(300.0f, 0.0f)) - .Color(THEME_COLOR)); - UIWidgets::CVarSliderFloat("Link's voice pitch multiplier", CVAR_AUDIO("LinkVoiceFreqMultiplier"), - UIWidgets::FloatSliderOptions() - .IsPercentage() - .Min(0.4f) - .Max(2.5f) - .DefaultValue(1.0f) - .Size(ImVec2(300.0f, 0.0f)) - .Color(THEME_COLOR)); + SohGui::mSohMenu->MenuDrawItem(lowHpAlarm, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(naviCall, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(enemyProx, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(leadingMusic, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(displaySeqName, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(ovlDuration, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(voicePitch, ImGui::GetContentRegionAvail().x, THEME_COLOR); ImGui::SameLine(); ImGui::SetCursorPosY(ImGui::GetCursorPos().y + 40.f); if (UIWidgets::Button("Reset##linkVoiceFreqMultiplier", UIWidgets::ButtonOptions().Size(ImVec2(80, 36)).Padding(ImVec2(5.0f, 0.0f)))) { CVarSetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0f); } - UIWidgets::CVarCheckbox( - "Randomize All Music and Sound Effects on New Scene", CVAR_AUDIO("RandomizeAllOnNewScene"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip( - "Enables randomizing all unlocked music and sound effects when you enter a new scene.")); - UIWidgets::CVarCheckbox( - "Lower Octaves of Unplayable High Notes", CVAR_AUDIO("ExperimentalOctaveDrop"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Some custom sequences may have notes that are too high for the game's audio " - "engine to play. Enabling this checkbox will cause these notes to drop a " - "couple of octaves so they can still harmonize with the other notes of the " - "sequence.")); + SohGui::mSohMenu->MenuDrawItem(randoMusicOnSceneChange, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(randomAudioOnSeedGen, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(lowerOctaves, ImGui::GetContentRegionAvail().x, THEME_COLOR); } ImGui::EndChild(); ImGui::EndTable(); @@ -834,3 +813,85 @@ void AudioEditor_UnlockAll() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); } + +void RegisterAudioWidgets() { + lowHpAlarm = { .name = "Mute Low HP Alarm", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + lowHpAlarm.CVar(CVAR_AUDIO("LowHpAlarm")) + .Options(CheckboxOptions().Color(THEME_COLOR).Tooltip("Disable the low HP beeping sound.")); + SohGui::mSohMenu->AddSearchWidget({ lowHpAlarm, "Enhancements", "Audio Editor", "Audio Options" }); + + naviCall = { .name = "Disable Navi Call Audio", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + naviCall.CVar(CVAR_AUDIO("DisableNaviCallAudio")) + .Options(CheckboxOptions().Color(THEME_COLOR).Tooltip("Disables the voice audio when Navi calls you.")); + SohGui::mSohMenu->AddSearchWidget({ naviCall, "Enhancements", "Audio Editor", "Audio Options" }); + + enemyProx = { .name = "Disable Enemy Proximity Music", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + enemyProx.CVar(CVAR_AUDIO("EnemyBGMDisable")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Disables the music change when getting close to enemies. Useful for hearing " + "your custom music for each scene more often.")); + + leadingMusic = { .name = "Disable Leading Music in Lost Woods", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + leadingMusic.CVar(CVAR_AUDIO("LostWoodsConsistentVolume")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Disables the volume shifting in the Lost Woods. Useful for hearing " + "your custom music in the Lost Woods if you don't need the navigation assitance " + "the volume changing provides. If toggling this while in the Lost Woods, reload " + "the area for the effect to kick in.")); + SohGui::mSohMenu->AddSearchWidget({ leadingMusic, "Enhancements", "Audio Editor", "Audio Options" }); + + displaySeqName = { .name = "Display Sequence Name in Notifications", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + displaySeqName.CVar(CVAR_AUDIO("SeqNameNotification")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Emits a notification with the current song name whenever it changes. " + "(does not apply to fanfares or enemy BGM).")); + SohGui::mSohMenu->AddSearchWidget({ displaySeqName, "Enhancements", "Audio Editor", "Audio Options" }); + + ovlDuration = { .name = "Sequence Notification Duration: %d seconds", .type = WidgetType::WIDGET_CVAR_SLIDER_INT }; + ovlDuration.CVar(CVAR_AUDIO("SeqNameNotificationDuration")) + .Options(IntSliderOptions().Color(THEME_COLOR).Min(1).Max(20).DefaultValue(10).Size(ImVec2(300.0f, 0.0f))); + SohGui::mSohMenu->AddSearchWidget({ ovlDuration, "Enhancements", "Audio Editor", "Audio Options" }); + + voicePitch = { .name = "Link's Voice Pitch Multiplier", .type = WidgetType::WIDGET_CVAR_SLIDER_FLOAT }; + voicePitch.CVar(CVAR_AUDIO("LinkVoiceFreqMultiplier")) + .Options(FloatSliderOptions() + .Color(THEME_COLOR) + .IsPercentage() + .Min(0.4f) + .Max(2.5f) + .DefaultValue(1.0f) + .Size(ImVec2(300.0f, 0.0f))); + SohGui::mSohMenu->AddSearchWidget({ voicePitch, "Enhancements", "Audio Editor", "Audio Options" }); + + randoMusicOnSceneChange = { .name = "Randomize All Music and Sound Effects on New Scene", + .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + randoMusicOnSceneChange.CVar(CVAR_AUDIO("RandomizeAllOnNewScene")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene.")); + SohGui::mSohMenu->AddSearchWidget({ randoMusicOnSceneChange, "Enhancements", "Audio Editor", "Audio Options" }); + + randomAudioOnSeedGen = { .name = "Randomize All Music and Sound Effects on Randomizer Generation", + .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + randomAudioOnSeedGen.CVar(CVAR_AUDIO("RandomizeAllOnRandoGen")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Enables randomizing all unlocked music and sound effects when you generate a new " + "randomizer. Respects locks already in place.")); + SohGui::mSohMenu->AddSearchWidget({ randomAudioOnSeedGen, "Enhancements", "Audio Editor", "Audio Options" }); + + lowerOctaves = { .name = "Lower Octaves of Unplayable High Notes", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + lowerOctaves.CVar(CVAR_AUDIO("ExperimentalOctaveDrop")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Some custom sequences may have notes that are too high for the game's audio " + "engine to play. Enabling this checkbox will cause these notes to drop a " + "couple of octaves so they can still harmonize with the other notes of the " + "sequence.")); + SohGui::mSohMenu->AddSearchWidget({ lowerOctaves, "Enhancements", "Audio Editor", "Audio Options" }); +} + +static RegisterMenuInitFunc menuInitFunc(RegisterAudioWidgets); diff --git a/soh/soh/Enhancements/audio/AudioHooks.cpp b/soh/soh/Enhancements/audio/AudioHooks.cpp new file mode 100644 index 000000000..f035eb0d1 --- /dev/null +++ b/soh/soh/Enhancements/audio/AudioHooks.cpp @@ -0,0 +1,43 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "AudioCollection.h" +#include +#include + +extern "C" { +#include "variables.h" + +extern PlayState* gPlayState; +} + +#define CVAR_SEQOVERLAY_NAME CVAR_AUDIO("SeqNameNotification") +#define CVAR_SEQOVERLAY_DEFAULT 0 +#define CVAR_SEQOVERLAY_VALUE CVarGetInteger(CVAR_SEQOVERLAY_NAME, CVAR_SEQOVERLAY_DEFAULT) + +void NotifySequenceName(int32_t playerIdx, int32_t seqId) { + // Keep track of the previous sequence/scene so we don't repeat notifications + static uint16_t previousSeqId = UINT16_MAX; + static int16_t previousSceneNum = INT16_MAX; + if (playerIdx == SEQ_PLAYER_BGM_MAIN && + (seqId != previousSeqId || (gPlayState != NULL && gPlayState->sceneNum != previousSceneNum))) { + + previousSeqId = seqId; + if (gPlayState != NULL) { + previousSceneNum = gPlayState->sceneNum; + } + const char* sequenceName = AudioCollection::Instance->GetSequenceName(seqId); + if (sequenceName != NULL) { + Notification::Emit({ + .message = ICON_FA_MUSIC " " + std::string(sequenceName), + .remainingTime = static_cast(CVarGetInteger(CVAR_AUDIO("SeqNameNotificationDuration"), 10)), + .mute = true, + }); + } + } +} + +void RegisterAudioNotificationHooks() { + COND_HOOK(OnSeqPlayerInit, CVAR_SEQOVERLAY_VALUE, NotifySequenceName); +} + +static RegisterShipInitFunc initFunc(RegisterAudioNotificationHooks, { CVAR_SEQOVERLAY_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/boss-rush/BossRush.cpp b/soh/soh/Enhancements/boss-rush/BossRush.cpp index 979f0ad6a..c74f9dfa8 100644 --- a/soh/soh/Enhancements/boss-rush/BossRush.cpp +++ b/soh/soh/Enhancements/boss-rush/BossRush.cpp @@ -2,6 +2,8 @@ #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" +#include "soh/frame_interpolation.h" #include #include @@ -14,14 +16,87 @@ extern "C" { #include "src/overlays/actors/ovl_Boss_Goma/z_boss_goma.h" #include "src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h" #include "src/overlays/actors/ovl_Door_Warp1/z_door_warp1.h" -extern PlayState* gPlayState; - -Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point); +#include "src/overlays/gamestates/ovl_file_choose/file_choose.h" +#include "objects/gameplay_keep/gameplay_keep.h" #include "textures/icon_item_nes_static/icon_item_nes_static.h" #include "textures/icon_item_ger_static/icon_item_ger_static.h" #include "textures/icon_item_fra_static/icon_item_fra_static.h" + +extern PlayState* gPlayState; + +Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point); +void FileChoose_UpdateStickDirectionPromptAnim(GameState* thisx); +void FileChoose_DrawTextRec(GraphicsContext* gfxCtx, s32 r, s32 g, s32 b, s32 a, f32 x, f32 y, f32 z, s32 s, s32 t, + f32 dx, f32 dy); } +typedef enum { + BR_CHOICE_BOSSES_ALL, + BR_CHOICE_BOSSES_CHILD, + BR_CHOICE_BOSSES_ADULT, + BR_CHOICE_BOSSES_GANONDORF_GANON +} BossRushBossesChoices; + +typedef enum { + BR_CHOICE_HEARTS_10, + BR_CHOICE_HEARTS_15, + BR_CHOICE_HEARTS_20, + BR_CHOICE_HEARTS_3, + BR_CHOICE_HEARTS_5, + BR_CHOICE_HEARTS_7 +} BossRushHeartsChoices; + +typedef enum { + BR_CHOICE_AMMO_LIMITED, + BR_CHOICE_AMMO_FULL, + BR_CHOICE_AMMO_MAXED, +} BossRushAmmoChoices; + +typedef enum { + BR_CHOICE_HEAL_GANONDORF, + BR_CHOICE_HEAL_EVERYBOSS, + BR_CHOICE_HEAL_NEVER, +} BossRushHealChoices; + +typedef enum { + BR_CHOICE_MAGIC_SINGLE, + BR_CHOICE_MAGIC_DOUBLE, +} BossRushMagicChoices; + +typedef enum { + BR_CHOICE_BGS_NO, + BR_CHOICE_BGS_YES, +} BossRushBgsChoices; + +typedef enum { + BR_CHOICE_BOTTLE_NO, + BR_CHOICE_BOTTLE_EMPTY, + BR_CHOICE_BOTTLE_FAIRY, + BR_CHOICE_BOTTLE_REDPOTION, + BR_CHOICE_BOTTLE_GREENPOTION, + BR_CHOICE_BOTTLE_BLUEPOTION +} BossRushBottleChoices; + +typedef enum { + BR_CHOICE_LONGSHOT_NO, + BR_CHOICE_LONGSHOT_YES, +} BossRushLongshotChoices; + +typedef enum { + BR_CHOICE_HOVERBOOTS_NO, + BR_CHOICE_HOVERBOOTS_YES, +} BossRushHoverBootsChoices; + +typedef enum { + BR_CHOICE_BUNNYHOOD_NO, + BR_CHOICE_BUNNYHOOD_YES, +} BossRushBunnyHoodChoices; + +typedef enum { + BR_CHOICE_TIMER_YES, + BR_CHOICE_TIMER_NO, +} BossRushTimerChoices; + typedef struct BossRushSetting { std::array name; std::vector> choices; @@ -114,6 +189,180 @@ u8 BossRush_GetSettingOptionsAmount(u8 optionIndex) { return static_cast(BossRushOptions[optionIndex].choices.size()); } +void FileChoose_UpdateBossRushMenu(GameState* gameState) { + static s8 sLastBossRushOptionIndex = -1; + static s8 sLastBossRushOptionValue = -1; + + FileChoose_UpdateStickDirectionPromptAnim(gameState); + FileChooseContext* fileChooseContext = (FileChooseContext*)gameState; + Input* input = &fileChooseContext->state.input[0]; + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); + + // Fade in elements after opening Boss Rush options menu + fileChooseContext->bossRushUIAlpha += 25; + if (fileChooseContext->bossRushUIAlpha > 255) { + fileChooseContext->bossRushUIAlpha = 255; + } + + // Animate up/down arrows. + fileChooseContext->bossRushArrowOffset += 1; + if (fileChooseContext->bossRushArrowOffset >= 30) { + fileChooseContext->bossRushArrowOffset = 0; + } + + // Move menu selection up or down. + if (ABS(fileChooseContext->stickRelY) > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) { + // Move down + if (fileChooseContext->stickRelY < -30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN))) { + // When selecting past the last option, cycle back to the first option. + if ((fileChooseContext->bossRushIndex + 1) > BR_OPTIONS_MAX - 1) { + fileChooseContext->bossRushIndex = 0; + fileChooseContext->bossRushOffset = 0; + } else { + fileChooseContext->bossRushIndex++; + // When last visible option is selected when moving down, offset the list down by one. + if (fileChooseContext->bossRushIndex - fileChooseContext->bossRushOffset > + BOSSRUSH_MAX_OPTIONS_ON_SCREEN - 1) { + fileChooseContext->bossRushOffset++; + } + } + } else if (fileChooseContext->stickRelY > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DUP))) { + // When selecting past the first option, cycle back to the last option and offset the list to view it + // properly. + if ((fileChooseContext->bossRushIndex - 1) < 0) { + fileChooseContext->bossRushIndex = BR_OPTIONS_MAX - 1; + fileChooseContext->bossRushOffset = + fileChooseContext->bossRushIndex - BOSSRUSH_MAX_OPTIONS_ON_SCREEN + 1; + } else { + // When first visible option is selected when moving up, offset the list up by one. + if (fileChooseContext->bossRushIndex - fileChooseContext->bossRushOffset == 0) { + fileChooseContext->bossRushOffset--; + } + fileChooseContext->bossRushIndex--; + } + } + + Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + + // Cycle through choices for currently selected option. + if (ABS(fileChooseContext->stickRelX) > 30 || + (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DRIGHT))) { + if (fileChooseContext->stickRelX > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DRIGHT))) { + // If exceeding the amount of choices for the selected option, cycle back to the first. + if ((gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex] + 1) == + BossRush_GetSettingOptionsAmount(fileChooseContext->bossRushIndex)) { + gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex] = 0; + } else { + gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex]++; + } + } else if (fileChooseContext->stickRelX < -30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT))) { + // If cycling back when already at the first choice for the selected option, cycle back to the last choice. + if ((gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex] - 1) < 0) { + gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex] = + BossRush_GetSettingOptionsAmount(fileChooseContext->bossRushIndex) - 1; + } else { + gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex]--; + } + } + + Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + + if (sLastBossRushOptionIndex != fileChooseContext->bossRushIndex || + sLastBossRushOptionValue != gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex]) { + GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection( + fileChooseContext->bossRushIndex, + gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex]); + sLastBossRushOptionIndex = fileChooseContext->bossRushIndex; + sLastBossRushOptionValue = gSaveContext.ship.quest.data.bossRush.options[fileChooseContext->bossRushIndex]; + } + + if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + fileChooseContext->configMode = CM_BOSS_RUSH_TO_QUEST; + return; + } + + // Load into the game. + if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) { + Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + fileChooseContext->buttonIndex = 0xFE; + fileChooseContext->menuMode = FS_MENU_MODE_SELECT; + fileChooseContext->selectMode = SM_FADE_OUT; + fileChooseContext->prevConfigMode = fileChooseContext->configMode; + return; + } +} + +void FileChoose_DrawBossRushMenuWindowContents(FileChooseContext* fileChooseContext) { + OPEN_DISPS(fileChooseContext->state.gfxCtx); + + uint8_t language = (gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language; + uint8_t listOffset = fileChooseContext->bossRushOffset; + uint8_t textAlpha = fileChooseContext->bossRushUIAlpha; + + // Draw arrows to indicate that the list can scroll up or down. + // Arrow up + if (listOffset > 0) { + uint16_t arrowUpX = 140; + uint16_t arrowUpY = 76 - (fileChooseContext->bossRushArrowOffset / 10); + gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowUpTex, G_IM_FMT_IA, G_IM_SIZ_16b, 16, 16, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, + G_TX_NOLOD); + gSPWideTextureRectangle(POLY_OPA_DISP++, arrowUpX << 2, arrowUpY << 2, (arrowUpX + 8) << 2, (arrowUpY + 8) << 2, + G_TX_RENDERTILE, 0, 0, (1 << 11), (1 << 11)); + } + // Arrow down + if (BR_OPTIONS_MAX - listOffset > BOSSRUSH_MAX_OPTIONS_ON_SCREEN) { + uint16_t arrowDownX = 140; + uint16_t arrowDownY = 181 + (fileChooseContext->bossRushArrowOffset / 10); + gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowDownTex, G_IM_FMT_IA, G_IM_SIZ_16b, 16, 16, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, + G_TX_NOLOD); + gSPWideTextureRectangle(POLY_OPA_DISP++, arrowDownX << 2, arrowDownY << 2, (arrowDownX + 8) << 2, + (arrowDownY + 8) << 2, G_TX_RENDERTILE, 0, 0, (1 << 11), (1 << 11)); + } + + // Draw options. There's more options than what fits on the screen, so the visible options + // depend on the current offset of the list. Currently selected option pulses in + // color and has arrows surrounding the option. + for (uint8_t i = listOffset; i - listOffset < BOSSRUSH_MAX_OPTIONS_ON_SCREEN; i++) { + uint16_t textYOffset = (i - listOffset) * 16; + + // Option name. + Interface_DrawTextLine(fileChooseContext->state.gfxCtx, (char*)BossRush_GetSettingName(i, language), 65, + (87 + textYOffset), 255, 255, 80, textAlpha, 0.8f, true); + + // Selected choice for option. + uint16_t finalKerning = Interface_DrawTextLine( + fileChooseContext->state.gfxCtx, + (char*)BossRush_GetSettingChoiceName(i, gSaveContext.ship.quest.data.bossRush.options[i], language), 165, + (87 + textYOffset), 255, 255, 255, textAlpha, 0.8f, true); + + // Draw arrows around selected option. + if (fileChooseContext->bossRushIndex == i) { + Gfx_SetupDL_39Opa(fileChooseContext->state.gfxCtx); + gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowCursorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 24, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD, + G_TX_NOLOD); + FileChoose_DrawTextRec(fileChooseContext->state.gfxCtx, fileChooseContext->stickLeftPrompt.arrowColorR, + fileChooseContext->stickLeftPrompt.arrowColorG, + fileChooseContext->stickLeftPrompt.arrowColorB, textAlpha, 160, (92 + textYOffset), + 0.42f, 0, 0, -1.0f, 1.0f); + FileChoose_DrawTextRec(fileChooseContext->state.gfxCtx, fileChooseContext->stickRightPrompt.arrowColorR, + fileChooseContext->stickRightPrompt.arrowColorG, + fileChooseContext->stickRightPrompt.arrowColorB, textAlpha, (171 + finalKerning), + (92 + textYOffset), 0.42f, 0, 0, 1.0f, 1.0f); + } + } + + CLOSE_DISPS(fileChooseContext->state.gfxCtx); +} + void BossRush_SpawnBlueWarps(PlayState* play) { // Spawn blue warps in Chamber of Sages based on what bosses have been defeated. @@ -316,7 +565,7 @@ void BossRush_HandleCompleteBoss(PlayState* play) { } } -void BossRush_InitSave() { +extern "C" void BossRush_InitSave() { // Set player name to Lonk for the few textboxes that show up during Boss Rush. Player can't input their own name. std::array brPlayerName = { 21, 50, 49, 46, 62, 62, 62, 62 }; @@ -502,6 +751,10 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li } break; } + case VB_PLAY_BLUE_WARP_CS: { + *should = false; + break; + } // Spawn clean blue warps (no ruto, adult animation, etc) case VB_SPAWN_BLUE_WARP: { switch (gPlayState->sceneNum) { @@ -609,6 +862,17 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li *should = false; break; } + // Handle the heal on blue warp + case VB_BLUE_WARP_CONSIDER_ADULT_IN_RANGE: { + if (*should) { + BossRush_HandleBlueWarpHeal(gPlayState); + } + break; + } + case VB_SHOW_GAMEPLAY_TIMER: { + *should |= gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_TIMER] == BR_CHOICE_TIMER_YES; + break; + } // Prevent saving case VB_BE_ABLE_TO_SAVE: // Disable doors so the player can't leave the boss rooms backwards. @@ -629,25 +893,6 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li va_end(args); } -void BossRush_OnActorInitHandler(void* actorRef) { - Actor* actor = static_cast(actorRef); - - if (actor->id == ACTOR_DEMO_SA && gPlayState->sceneNum == SCENE_CHAMBER_OF_THE_SAGES) { - BossRush_SpawnBlueWarps(gPlayState); - Actor_Kill(actor); - GET_PLAYER(gPlayState)->actor.world.rot.y = GET_PLAYER(gPlayState)->actor.shape.rot.y = 27306; - return; - } - - // Remove chests, mainly for the chest in King Dodongo's boss room. - // Remove bushes, used in Gohma's arena. - // Remove pots, used in Barinade's and Ganondorf's arenas. - if (actor->id == ACTOR_EN_KUSA || actor->id == ACTOR_OBJ_TSUBO || actor->id == ACTOR_EN_BOX) { - Actor_Kill(actor); - return; - } -} - void BossRush_OnSceneInitHandler(s16 sceneNum) { // Unpause the timer when the scene loaded isn't the Chamber of Sages. if (sceneNum != SCENE_CHAMBER_OF_THE_SAGES) { @@ -667,38 +912,32 @@ void BossRush_OnBlueWarpUpdate(void* actor) { } } -void BossRush_RegisterHooks() { - static u32 onVanillaBehaviorHook = 0; - static u32 onSceneInitHook = 0; - static u32 onActorInitHook = 0; - static u32 onBossDefeatHook = 0; - static u32 onActorUpdate = 0; +void RegisterBossRush() { + COND_HOOK(OnLoadGame, true, [](int32_t fileNum) { + COND_ID_HOOK(OnActorInit, ACTOR_DEMO_SA, IS_BOSS_RUSH, [](void* actorPtr) { + BossRush_SpawnBlueWarps(gPlayState); + Actor_Kill((Actor*)actorPtr); + GET_PLAYER(gPlayState)->actor.world.rot.y = 27306; + GET_PLAYER(gPlayState)->actor.shape.rot.y = 27306; + }); - GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) { - GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook); - GameInteractor::Instance->UnregisterGameHook(onSceneInitHook); - GameInteractor::Instance->UnregisterGameHook(onActorInitHook); - GameInteractor::Instance->UnregisterGameHook(onBossDefeatHook); - GameInteractor::Instance->UnregisterGameHookForID(onActorUpdate); + // Remove bushes, used in Gohma's arena + COND_ID_HOOK(OnActorInit, ACTOR_EN_KUSA, IS_BOSS_RUSH, [](void* actorPtr) { Actor_Kill((Actor*)actorPtr); }); - onVanillaBehaviorHook = 0; - onSceneInitHook = 0; - onActorInitHook = 0; - onBossDefeatHook = 0; - onActorUpdate = 0; + // Remove pots, used in Barinade's and Ganondorf's arenas + COND_ID_HOOK(OnActorInit, ACTOR_OBJ_TSUBO, IS_BOSS_RUSH, [](void* actorPtr) { Actor_Kill((Actor*)actorPtr); }); - if (!IS_BOSS_RUSH) - return; + // Remove chests, mainly for the chest in King Dodongo's boss room + COND_ID_HOOK(OnActorInit, ACTOR_EN_BOX, IS_BOSS_RUSH, [](void* actorPtr) { Actor_Kill((Actor*)actorPtr); }); - onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook( - BossRush_OnVanillaBehaviorHandler); - onSceneInitHook = - GameInteractor::Instance->RegisterGameHook(BossRush_OnSceneInitHandler); - onActorInitHook = - GameInteractor::Instance->RegisterGameHook(BossRush_OnActorInitHandler); - onBossDefeatHook = - GameInteractor::Instance->RegisterGameHook(BossRush_OnBossDefeatHandler); - onActorUpdate = GameInteractor::Instance->RegisterGameHookForID( - ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate); + COND_HOOK(OnVanillaBehavior, IS_BOSS_RUSH, BossRush_OnVanillaBehaviorHandler); + + COND_HOOK(OnSceneInit, IS_BOSS_RUSH, BossRush_OnSceneInitHandler); + + COND_HOOK(OnBossDefeat, IS_BOSS_RUSH, BossRush_OnBossDefeatHandler); + + COND_ID_HOOK(OnActorUpdate, ACTOR_DOOR_WARP1, IS_BOSS_RUSH, BossRush_OnBlueWarpUpdate); }); } + +static RegisterShipInitFunc initFunc(RegisterBossRush); \ No newline at end of file diff --git a/soh/soh/Enhancements/boss-rush/BossRush.h b/soh/soh/Enhancements/boss-rush/BossRush.h index 881d8d53f..4a47f4f5b 100644 --- a/soh/soh/Enhancements/boss-rush/BossRush.h +++ b/soh/soh/Enhancements/boss-rush/BossRush.h @@ -1,16 +1,41 @@ #pragma once -#include "z64.h" +#include #ifdef __cplusplus extern "C" { #endif -void BossRush_HandleBlueWarpHeal(PlayState* play); -void BossRush_InitSave(); +struct GameState; +struct FileChooseContext; + +void FileChoose_UpdateBossRushMenu(struct GameState* gameState); +void FileChoose_DrawBossRushMenuWindowContents(struct FileChooseContext* fileChooseContext); const char* BossRush_GetSettingName(u8 optionIndex, u8 language); const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 language); u8 BossRush_GetSettingOptionsAmount(u8 optionIndex); -void BossRush_RegisterHooks(); #ifdef __cplusplus }; #endif + +#define BOSSRUSH_MAX_OPTIONS_ON_SCREEN 6 + +typedef enum { + BR_OPTIONS_BOSSES, + BR_OPTIONS_HEARTS, + BR_OPTIONS_AMMO, + BR_OPTIONS_HEAL, + BR_OPTIONS_HYPERBOSSES, + BR_OPTIONS_MAGIC, + BR_OPTIONS_BGS, + BR_OPTIONS_BOTTLE, + BR_OPTIONS_LONGSHOT, + BR_OPTIONS_HOVERBOOTS, + BR_OPTIONS_BUNNYHOOD, + BR_OPTIONS_TIMER, + BR_OPTIONS_MAX, +} BossRushOptionEnums; + +typedef enum { + BR_CHOICE_HYPERBOSSES_NO, + BR_CHOICE_HYPERBOSSES_YES, +} BossRushHyperBossesChoices; \ No newline at end of file diff --git a/soh/soh/Enhancements/boss-rush/BossRushTypes.h b/soh/soh/Enhancements/boss-rush/BossRushTypes.h deleted file mode 100644 index 973f1599f..000000000 --- a/soh/soh/Enhancements/boss-rush/BossRushTypes.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#define BOSSRUSH_MAX_OPTIONS_ON_SCREEN 6 - -typedef enum { - BR_OPTIONS_BOSSES, - BR_OPTIONS_HEARTS, - BR_OPTIONS_AMMO, - BR_OPTIONS_HEAL, - BR_OPTIONS_HYPERBOSSES, - BR_OPTIONS_MAGIC, - BR_OPTIONS_BGS, - BR_OPTIONS_BOTTLE, - BR_OPTIONS_LONGSHOT, - BR_OPTIONS_HOVERBOOTS, - BR_OPTIONS_BUNNYHOOD, - BR_OPTIONS_TIMER, - BR_OPTIONS_MAX, -} BossRushOptionEnums; - -typedef enum { - BR_CHOICE_BOSSES_ALL, - BR_CHOICE_BOSSES_CHILD, - BR_CHOICE_BOSSES_ADULT, - BR_CHOICE_BOSSES_GANONDORF_GANON -} BossRushBossesChoices; - -typedef enum { - BR_CHOICE_HEARTS_10, - BR_CHOICE_HEARTS_15, - BR_CHOICE_HEARTS_20, - BR_CHOICE_HEARTS_3, - BR_CHOICE_HEARTS_5, - BR_CHOICE_HEARTS_7 -} BossRushHeartsChoices; - -typedef enum { - BR_CHOICE_AMMO_LIMITED, - BR_CHOICE_AMMO_FULL, - BR_CHOICE_AMMO_MAXED, -} BossRushAmmoChoices; - -typedef enum { - BR_CHOICE_HEAL_GANONDORF, - BR_CHOICE_HEAL_EVERYBOSS, - BR_CHOICE_HEAL_NEVER, -} BossRushHealChoices; - -typedef enum { - BR_CHOICE_HYPERBOSSES_NO, - BR_CHOICE_HYPERBOSSES_YES, -} BossRushHyperBossesChoices; - -typedef enum { - BR_CHOICE_MAGIC_SINGLE, - BR_CHOICE_MAGIC_DOUBLE, -} BossRushMagicChoices; - -typedef enum { - BR_CHOICE_BGS_NO, - BR_CHOICE_BGS_YES, -} BossRushBgsChoices; - -typedef enum { - BR_CHOICE_BOTTLE_NO, - BR_CHOICE_BOTTLE_EMPTY, - BR_CHOICE_BOTTLE_FAIRY, - BR_CHOICE_BOTTLE_REDPOTION, - BR_CHOICE_BOTTLE_GREENPOTION, - BR_CHOICE_BOTTLE_BLUEPOTION -} BossRushBottleChoices; - -typedef enum { - BR_CHOICE_LONGSHOT_NO, - BR_CHOICE_LONGSHOT_YES, -} BossRushLongshotChoices; - -typedef enum { - BR_CHOICE_HOVERBOOTS_NO, - BR_CHOICE_HOVERBOOTS_YES, -} BossRushHoverBootsChoices; - -typedef enum { - BR_CHOICE_BUNNYHOOD_NO, - BR_CHOICE_BUNNYHOOD_YES, -} BossRushBunnyHoodChoices; - -typedef enum { - BR_CHOICE_TIMER_YES, - BR_CHOICE_TIMER_NO, -} BossRushTimerChoices; diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index 1fbab40c2..2f73fb057 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -1,8 +1,9 @@ #include "InputViewer.h" -#include "public/bridge/consolevariablebridge.h" +#include #include "libultraship/libultra/controller.h" -#include "Context.h" +#include +#include #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" #include diff --git a/soh/soh/Enhancements/controls/Mouse.cpp b/soh/soh/Enhancements/controls/Mouse.cpp index 4ad9d11d0..26e122504 100644 --- a/soh/soh/Enhancements/controls/Mouse.cpp +++ b/soh/soh/Enhancements/controls/Mouse.cpp @@ -2,7 +2,7 @@ #include "soh/OTRGlobals.h" #include "z64player.h" #include "global.h" -#include +#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" @@ -148,9 +148,9 @@ void Mouse_RegisterHandleQuickspin() { REGISTER_VB_SHOULD(VB_SHOULD_QUICKSPIN, { Mouse_HandleQuickspin(should, va_arg(args, s8*), va_arg(args, s8*)); }); } -static RegisterShipInitFunc initFunc_shieldRecenter(Mouse_RegisterRecenterCursorOnShield, { CVAR_ENABLE_MOUSE_NAME }); -static RegisterShipInitFunc initFunc_firstPerson(Mouse_RegisterHandleFirstPerson, { CVAR_ENABLE_MOUSE_NAME }); -static RegisterShipInitFunc initFunc_quickspinCount(Mouse_RegisterUpdateQuickspinCount, { CVAR_ENABLE_MOUSE_NAME }); -static RegisterShipInitFunc initFunc_quickspin(Mouse_RegisterHandleQuickspin, { CVAR_ENABLE_MOUSE_NAME }); -static RegisterShipInitFunc initFunc_shieldMove(Mouse_RegisterHandleShield, { CVAR_ENABLE_MOUSE_NAME }); +static RegisterShipInitFunc registerShieldRecenter(Mouse_RegisterRecenterCursorOnShield, { CVAR_ENABLE_MOUSE_NAME }); +static RegisterShipInitFunc registerFirstPerson(Mouse_RegisterHandleFirstPerson, { CVAR_ENABLE_MOUSE_NAME }); +static RegisterShipInitFunc registerQuickspinCount(Mouse_RegisterUpdateQuickspinCount, { CVAR_ENABLE_MOUSE_NAME }); +static RegisterShipInitFunc registerQuickspin(Mouse_RegisterHandleQuickspin, { CVAR_ENABLE_MOUSE_NAME }); +static RegisterShipInitFunc registerShieldMove(Mouse_RegisterHandleShield, { CVAR_ENABLE_MOUSE_NAME }); } // extern "C" diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 41a31f8be..208833d61 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1,18 +1,31 @@ #include "SohInputEditorWindow.h" -#include +#include +#include #include "soh/OTRGlobals.h" -#include "soh/SohGui/UIWidgets.hpp" +#include "soh/SohGui/SohMenu.h" #include "soh/SohGui/SohGui.hpp" #include "z64.h" #include "soh/cvar_prefixes.h" #ifndef __WIIU__ -#include "controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.h" +#include #endif #define SCALE_IMGUI_SIZE(value) ((value / 13.0f) * ImGui::GetFontSize()) using namespace UIWidgets; +static WidgetInfo freeLook; +static WidgetInfo mouseControl; +static WidgetInfo mouseAutoCapture; +static WidgetInfo rightStickOcarina; +static WidgetInfo dpadOcarina; +static WidgetInfo dpadPause; +static WidgetInfo dpadText; + +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + SohInputEditorWindow::~SohInputEditorWindow() { } @@ -1321,8 +1334,8 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { ImGui::SetCursorPos(ImVec2(cursor.x, cursor.y + 5)); CheckboxOptions checkOpt = CheckboxOptions().Color(THEME_COLOR); - CVarCheckbox("Dpad Ocarina Playback", CVAR_SETTING("CustomOcarina.Dpad"), checkOpt); - CVarCheckbox("Right Stick Ocarina Playback", CVAR_SETTING("CustomOcarina.RightStick"), checkOpt); + SohGui::mSohMenu->MenuDrawItem(dpadOcarina, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(rightStickOcarina, ImGui::GetContentRegionAvail().x, THEME_COLOR); CVarCheckbox("Customize Ocarina Controls", CVAR_SETTING("CustomOcarina.Enabled"), checkOpt); if (!CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) { @@ -1354,12 +1367,11 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { void SohInputEditorWindow::DrawCameraControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - CVarCheckbox( - "Enable Mouse Controls", CVAR_SETTING("EnableMouse"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Allows for using the mouse to control the camera (must enable Free Look), " - "aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)")); + SohGui::mSohMenu->MenuDrawItem(mouseControl, ImGui::GetContentRegionAvail().x, THEME_COLOR); + cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); + SohGui::mSohMenu->MenuDrawItem(mouseAutoCapture, ImGui::GetContentRegionAvail().x, THEME_COLOR); + Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"), CheckboxOptions() @@ -1427,14 +1439,7 @@ void SohInputEditorWindow::DrawCameraControlPanel() { ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); - CVarCheckbox( - "Free Look", CVAR_SETTING("FreeLook.Enabled"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the " - "controller config menu, and map the camera stick to the right stick.\n" - "Doesn't work in areas were the game locks the camera.\n" - "Scene reload may be necessary to enable.")); + SohGui::mSohMenu->MenuDrawItem(freeLook, ImGui::GetContentRegionAvail().x, THEME_COLOR); CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look")); CVarCheckbox( @@ -1467,16 +1472,8 @@ void SohInputEditorWindow::DrawDpadControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); - CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold " - "C-Up to equip instead of navigate")); - CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry " - "screens with the D-pad")); + SohGui::mSohMenu->MenuDrawItem(dpadPause, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(dpadText, ImGui::GetContentRegionAvail().x, THEME_COLOR); if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) { ImGui::BeginDisabled(); @@ -1902,3 +1899,74 @@ void SohInputEditorWindow::DrawElement() { ImGui::PopStyleColor(3); ImGui::PopFont(); } + +void RegisterInputEditorWidgets() { + dpadOcarina = { .name = "Dpad Ocarina Playback", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dpadOcarina.CVar(CVAR_SETTING("CustomOcarina.Dpad")).Options(CheckboxOptions().Color(THEME_COLOR)); + SohGui::mSohMenu->AddSearchWidget({ dpadOcarina, "Settings", "Controls", "Ocarina Controls", "" }); + + freeLook = { .name = "Free Look", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + freeLook.CVar(CVAR_SETTING("FreeLook.Enabled")) + .Options( + CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip( + "Enables free look camera control\nNote: You must remap C buttons off of the right stick in the " + "controller config menu, and map the camera stick to the right stick.\n" + "Doesn't work in areas were the game locks the camera.\n" + "Scene reload may be necessary to enable.")); + SohGui::mSohMenu->AddSearchWidget({ freeLook, "Settings", "Controls", "Camera Controls" }); + + mouseControl = { .name = "Enable Mouse Controls", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + mouseControl.CVar(CVAR_SETTING("EnableMouse")) + .Callback([](WidgetInfo& info) { + bool enabled = + CVarGetInteger(CVAR_SETTING("EnableMouse"), 0) && CVarGetInteger(CVAR_SETTING("AutoCaptureMouse"), 1); + auto wnd = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()); + wnd->SetAutoCaptureMouse(enabled); + }) + .Options( + CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Allows for using the mouse to control the camera (must enable Free Look), " + "aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)\n" + "Press F2 to toggle mouse capture manually.")); + SohGui::mSohMenu->AddSearchWidget({ mouseControl, "Settings", "Controls", "Camera Controls" }); + + mouseAutoCapture = { .name = "Auto Capture Mouse Input", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + mouseAutoCapture.CVar(CVAR_SETTING("AutoCaptureMouse")) + .Callback([](WidgetInfo& info) { + bool enabled = + CVarGetInteger(CVAR_SETTING("EnableMouse"), 0) && CVarGetInteger(CVAR_SETTING("AutoCaptureMouse"), 1); + auto wnd = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()); + wnd->SetAutoCaptureMouse(enabled); + }) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("When Mouse Controls are enabled, this toggles whether the program will automatically " + "hide the cursor " + "and capture mouse input when closing the menu.")); + SohGui::mSohMenu->AddSearchWidget({ mouseAutoCapture, "Settings", "Controls", "Camera Controls" }); + + rightStickOcarina = { .name = "Right Stick Ocarina Playback", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + rightStickOcarina.CVar(CVAR_SETTING("CustomOcarina.RightStick")).Options(CheckboxOptions().Color(THEME_COLOR)); + SohGui::mSohMenu->AddSearchWidget({ rightStickOcarina, "Settings", "Controls", "Ocarina Controls" }); + + dpadPause = { .name = "D-pad Support on Pause Screen", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dpadPause.CVar(CVAR_SETTING("DPadOnPause")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold " + "C-Up to equip instead of navigate")); + SohGui::mSohMenu->AddSearchWidget({ dpadPause, "Settings", "Controls", "Dpad Controls" }); + + dpadText = { .name = "D-pad Support in Text Boxes", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dpadText.CVar(CVAR_SETTING("DpadInText")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry " + "screens with the D-pad")); + SohGui::mSohMenu->AddSearchWidget({ dpadText, "Settings", "Controls", "Dpad Controls" }); +} + +static RegisterMenuInitFunc menuInitFunc(RegisterInputEditorWidgets); diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 8074fa707..314b92b40 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -2382,6 +2382,11 @@ void CosmeticsEditorWindow::DrawElement() { .Color(THEME_COLOR) .Tooltip("Enables randomizing all unlocked cosmetics when you enter a new scene.")); ImGui::EndDisabled(); + UIWidgets::CVarCheckbox( + "Randomize All on Randomizer Generation", CVAR_COSMETIC("RandomizeAllOnRandoGen"), + UIWidgets::CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Enables randomizing all unlocked cosmetics when you generate a new randomizer.")); UIWidgets::CVarCheckbox( "Advanced Mode", CVAR_COSMETIC("AdvancedMode"), UIWidgets::CheckboxOptions() @@ -2589,6 +2594,14 @@ void Cosmetics_RegisterOnSceneInitHook() { }); } +void CosmeticsEditorRegisterOnGenerationCompletionHook() { + GameInteractor::Instance->RegisterGameHook([]() { + if (CVarGetInteger(CVAR_COSMETIC("RandomizeAllOnRandoGen"), 0)) { + CosmeticsEditor_RandomizeAll(); + } + }); +} + void CosmeticsEditorWindow::InitElement() { // Convert the `current color` into the format that the ImGui color picker expects for (auto& [id, cosmeticOption] : cosmeticOptions) { @@ -2608,6 +2621,7 @@ void CosmeticsEditorWindow::InitElement() { RegisterOnLoadGameHook(); RegisterOnGameFrameUpdateHook(); Cosmetics_RegisterOnSceneInitHook(); + CosmeticsEditorRegisterOnGenerationCompletionHook(); } void CosmeticsEditor_RandomizeAll() { diff --git a/soh/soh/Enhancements/cosmetics/CustomLogoTitle.cpp b/soh/soh/Enhancements/cosmetics/CustomLogoTitle.cpp index 029284fa4..3ec872368 100644 --- a/soh/soh/Enhancements/cosmetics/CustomLogoTitle.cpp +++ b/soh/soh/Enhancements/cosmetics/CustomLogoTitle.cpp @@ -195,7 +195,7 @@ void RegisterCustomLogoTitle() { COND_HOOK(OnZTitleUpdate, true, OnZTitleUpdatePressButtonToSkip); } -static RegisterShipInitFunc initFuncAlways(RegisterCustomLogoTitle); +static RegisterShipInitFunc registerCustomLogo(RegisterCustomLogoTitle); // // // // // // // Bootsequence @@ -216,7 +216,7 @@ void RegisterCustomLogoTitleBootsequence() { COND_HOOK(OnZTitleUpdate, CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_FILESELECT, OnZTitleUpdateSkipToFileSelect); } -static RegisterShipInitFunc initFuncBootsequence(RegisterCustomLogoTitleBootsequence, { CVAR_BOOTSEQUENCE_NAME }); +static RegisterShipInitFunc registerTitleBootSequence(RegisterCustomLogoTitleBootsequence, { CVAR_BOOTSEQUENCE_NAME }); // // // // // // // Let it Snow @@ -230,4 +230,4 @@ void RegisterCustomLogoTitleLetItSnow() { shouldDrawIceOnSpinningLogo = CVAR_LETITSNOW_VALUE != CVAR_LETITSNOW_DEFAULT; } -static RegisterShipInitFunc initFuncLetItSnow(RegisterCustomLogoTitleLetItSnow, { CVAR_LETITSNOW_NAME }); +static RegisterShipInitFunc registerLetItSnow(RegisterCustomLogoTitleLetItSnow, { CVAR_LETITSNOW_NAME }); diff --git a/soh/soh/Enhancements/cosmetics/TimeFlowFileSelect.cpp b/soh/soh/Enhancements/cosmetics/TimeFlowFileSelect.cpp index d33f4f7e8..bd99ca1b1 100644 --- a/soh/soh/Enhancements/cosmetics/TimeFlowFileSelect.cpp +++ b/soh/soh/Enhancements/cosmetics/TimeFlowFileSelect.cpp @@ -17,4 +17,4 @@ void RegisterTimeFlowFileSelect() { COND_HOOK(OnFileChooseMain, CVAR_TIMEFLOWFILESELECT_VALUE, OnFileChooseMainTimeFlowFileSelect); } -static RegisterShipInitFunc initFunc_TimeFlowFileSelect(RegisterTimeFlowFileSelect, { CVAR_TIMEFLOWFILESELECT_NAME }); +static RegisterShipInitFunc initFunc(RegisterTimeFlowFileSelect, { CVAR_TIMEFLOWFILESELECT_NAME }); diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index b5bc0fd6e..1b04e5780 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -79,8 +79,41 @@ typedef enum { TEXT_SARIAS_SONG_CHANNELING_POWER = 0x016D, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x01B3, // 0x1yy for Navi msg range TEXT_MASK_SHOP_SIGN = 0x0207, + TEXT_WATERFALL = 0x022D, TEXT_FROGS_UNDERWATER = 0x022E, + TEXT_OUTSIDE_FISHING_POND = 0x023A, + TEXT_HF_SIGN = 0x0301, + TEXT_HC_GREAT_FAIRY_SIGN = 0x0304, + TEXT_DMT_KAK_SIGN = 0x0305, + TEXT_KAK_TO_GY_SIGN = 0x0306, + TEXT_KAK_WELL_SIGN = 0x0307, + TEXT_KAK_DMT_SIGN = 0x0308, + TEXT_DMT_SIGN = 0x309, + TEXT_DMT_DC_SIGN = 0x030A, + TEXT_GC_SIGN = 0x030B, + TEXT_HF_ZR_SIGN = 0x030C, + TEXT_ZD_SIGN = 0x030E, + TEXT_ZF_JABU_SIGN = 0x030F, + TEXT_KF_LW_SIGN = 0x0314, + TEXT_HF_LON_LON_SIGN = 0x0315, + TEXT_LA_SIGN = 0x0317, + TEXT_LA_LAB_SIGN = 0x0318, + TEXT_GV_SIGN = 0x0319, TEXT_GF_HBA_SIGN = 0x031A, + TEXT_KF_SHOP_SIGN = 0x031E, + TEXT_LINKS_HOUSE_SIGN = 0x031F, + TEXT_KOKIRI_EXIT_SIGN = 0x0320, + TEXT_DMT_GC_SIGN = 0x0321, + TEXT_DMT_DMC_SIGN = 0x0323, + TEXT_DMT_SUMMIT_SIGN = 0x032D, + TEXT_ZD_SHOP_SIGN = 0x0333, + TEXT_OUTSIDE_KOKIRI_SIGN = 0x0339, + TEXT_OUTSIDE_MARKET_SIGN = 0x033A, + TEXT_MIDO_HOUSE_SIGN = 0x033C, + TEXT_KNOW_IT_ALL_HOUSE_SIGN = 0x033D, + TEXT_TWINS_HOUSE_SIGN = 0x033E, + TEXT_SARIAS_HOUSE_SIGN = 0x033F, + TEXT_NO_DIVING_SIGN = 0x0342, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x0346, // 0x3yy for cuttable sign range TEXT_WARP_MINUET_OF_FOREST = 0x088D, TEXT_WARP_BOLERO_OF_FIRE = 0x088E, @@ -88,6 +121,10 @@ typedef enum { TEXT_WARP_REQUIEM_OF_SPIRIT = 0x0890, TEXT_WARP_NOCTURNE_OF_SHADOW = 0x0891, TEXT_WARP_PRELUDE_OF_LIGHT = 0x0892, + TEXT_MIDO_HOME_AFTER_ZELDAS_LETTER = 0x1028, + TEXT_MIDO_SPEAK_TO_MIDO_FIRST_TIME = 0x102F, + TEXT_MIDO_SPEAK_TO_MIDO_AGAIN = 0x1030, + TEXT_MIDO_HOME_BEFORE_ZELDAS_LETTER = 0x1046, TEXT_SCRUB_POH = 0x10A2, TEXT_SARIA_SFM = 0x10AD, TEXT_SCRUB_STICK_UPGRADE = 0x10DC, diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 7713b48b8..ff40f149a 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1,5 +1,5 @@ #include "debugconsole.h" -#include +#include #include "savestates.h" #include "soh/ActorDB.h" @@ -15,10 +15,10 @@ #define Path _Path #define PATH_HACK -#include +#include -#include -#include +#include +#include #include #include #undef PATH_HACK diff --git a/soh/soh/Enhancements/debugger/MessageViewer.h b/soh/soh/Enhancements/debugger/MessageViewer.h index 9ce8eab05..1d2c8fa83 100644 --- a/soh/soh/Enhancements/debugger/MessageViewer.h +++ b/soh/soh/Enhancements/debugger/MessageViewer.h @@ -3,7 +3,7 @@ #include "z64.h" #ifdef __cplusplus -#include "GuiWindow.h" +#include #include extern "C" { #endif diff --git a/soh/soh/Enhancements/debugger/SohConsoleWindow.h b/soh/soh/Enhancements/debugger/SohConsoleWindow.h index db039625b..b84399ad6 100644 --- a/soh/soh/Enhancements/debugger/SohConsoleWindow.h +++ b/soh/soh/Enhancements/debugger/SohConsoleWindow.h @@ -1,8 +1,8 @@ #ifndef SOH_CONSOLE_H #define SOH_CONSOLE_H -#include "window/gui/GuiWindow.h" -#include "window/gui/ConsoleWindow.h" +#include +#include class SohConsoleWindow : public Ship::ConsoleWindow { public: diff --git a/soh/soh/Enhancements/debugger/SohGfxDebuggerWindow.h b/soh/soh/Enhancements/debugger/SohGfxDebuggerWindow.h index 789173b88..7b9267693 100644 --- a/soh/soh/Enhancements/debugger/SohGfxDebuggerWindow.h +++ b/soh/soh/Enhancements/debugger/SohGfxDebuggerWindow.h @@ -1,8 +1,8 @@ #ifndef SOH_GFX_DEBUGGER_H #define SOH_GFX_DEBUGGER_H -#include "window/gui/GuiWindow.h" -#include "window/gui/GfxDebuggerWindow.h" +#include +#include class SohGfxDebuggerWindow : public LUS::GfxDebuggerWindow { public: diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp index d21d9449e..5792a4ec0 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.cpp +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -1228,4 +1228,4 @@ void ActorViewer_RegisterNameTagHooks() { [](void* actor) { ActorViewer_AddTagForActor(static_cast(actor)); }); } -RegisterShipInitFunc nametagInit(ActorViewer_RegisterNameTagHooks, { CVAR_ACTOR_NAME_TAGS_ENABLED_NAME }); +static RegisterShipInitFunc initFunc(ActorViewer_RegisterNameTagHooks, { CVAR_ACTOR_NAME_TAGS_ENABLED_NAME }); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 7b514a16c..463f900e0 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -572,7 +572,9 @@ void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& fl PopStyleCheckbox(); if (ImGui::IsItemHovered() && hasDescription) { ImGui::BeginTooltip(); - ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60).c_str()); + uint16_t index = row * 16 + flagIndex; + const char* desc = flagTable.flagDescriptions.at(index); + ImGui::Text("0x%02X: %s", index, UIWidgets::WrappedText(desc, 60).c_str()); ImGui::EndTooltip(); } ImGui::PopID(); @@ -930,7 +932,15 @@ void DrawFlagsTab() { for (int j = 0; j < flagTable.size + 1; j++) { DrawGroupWithBorder( [&]() { - ImGui::Text("%s", fmt::format("{:<2x}", j).c_str()); + if (j == 0) { + for (int k = 0xF; k >= 0; k--) { + ImGui::SameLine(37.5 + ((0xF - k) * 33.8)); + ImGui::Text("%X", k); + } + } + + ImGui::Text("%s", fmt::format("{:<2X}", j).c_str()); + switch (flagTable.flagTableType) { case EVENT_CHECK_INF: DrawFlagTableArray16(flagTable, j, gSaveContext.eventChkInf[j]); diff --git a/soh/soh/Enhancements/debugger/dlViewer.cpp b/soh/soh/Enhancements/debugger/dlViewer.cpp index a02aa7d95..60a6e07c8 100644 --- a/soh/soh/Enhancements/debugger/dlViewer.cpp +++ b/soh/soh/Enhancements/debugger/dlViewer.cpp @@ -2,8 +2,9 @@ #include "soh/util.h" #include "soh/SohGui/UIWidgets.hpp" #include "soh/SohGui/SohGui.hpp" -#include "ResourceManager.h" -#include "DisplayList.h" +#include +#include +#include #include "soh/OTRGlobals.h" #include diff --git a/soh/soh/Enhancements/debugger/valueViewer.cpp b/soh/soh/Enhancements/debugger/valueViewer.cpp index 4544979cb..a4ab75e72 100644 --- a/soh/soh/Enhancements/debugger/valueViewer.cpp +++ b/soh/soh/Enhancements/debugger/valueViewer.cpp @@ -151,7 +151,7 @@ void RegisterValueViewerHooks() { COND_HOOK(OnGameFrameUpdate, CVAR_VALUE, []() { ValueViewer_SetupDraw(); }); } -RegisterShipInitFunc initFunc(RegisterValueViewerHooks, { CVAR_NAME }); +static RegisterShipInitFunc initFunc(RegisterValueViewerHooks, { CVAR_NAME }); void ValueViewerWindow::DrawElement() { ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp index 11f024226..2913e06db 100644 --- a/soh/soh/Enhancements/enemyrandomizer.cpp +++ b/soh/soh/Enhancements/enemyrandomizer.cpp @@ -619,6 +619,7 @@ void FixClubMoblinScale(void* ptr) { void RegisterEnemyRandomizer() { COND_ID_HOOK(OnActorInit, ACTOR_EN_MB, CVAR_ENEMY_RANDOMIZER_VALUE, FixClubMoblinScale); + // prevent dark link from triggering a voidout COND_VB_SHOULD(VB_TRIGGER_VOIDOUT, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, { Actor* actor = va_arg(args, Actor*); @@ -647,6 +648,24 @@ void RegisterEnemyRandomizer() { } }); + // prevent dark link from interfering with ice floors + COND_VB_SHOULD(VB_SET_STATIC_PREV_FLOOR_TYPE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, { + Player* playerOrDarkLink = va_arg(args, Player*); + + if (playerOrDarkLink->actor.id != ACTOR_PLAYER) { + *should = false; + } + }); + + // prevent dark link from interfering with ice floors + COND_VB_SHOULD(VB_SET_STATIC_FLOOR_TYPE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, { + Player* playerOrDarkLink = va_arg(args, Player*); + + if (playerOrDarkLink->actor.id != ACTOR_PLAYER) { + *should = false; + } + }); + // prevent dark link from being grabbed by like likes and therefore grabbing the player COND_VB_SHOULD(VB_LIKE_LIKE_GRAB_PLAYER, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, { EnRr* likeLike = va_arg(args, EnRr*); diff --git a/soh/soh/Enhancements/enhancementTypes.h b/soh/soh/Enhancements/enhancementTypes.h index c1b91cffa..bd025115b 100644 --- a/soh/soh/Enhancements/enhancementTypes.h +++ b/soh/soh/Enhancements/enhancementTypes.h @@ -112,7 +112,9 @@ typedef enum { typedef enum { TIME_TRAVEL_DISABLED, TIME_TRAVEL_OOT, + TIME_TRAVEL_OOT_MS, TIME_TRAVEL_ANY, + TIME_TRAVEL_ANY_MS } TimeTravelType; typedef enum { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp index 03667dd86..682a1271e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp @@ -50,7 +50,7 @@ namespace GameInteractionEffect { // MARK: - Flags GameInteractionEffectQueryResult SetSceneFlag::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } @@ -62,7 +62,7 @@ void SetSceneFlag::_Apply() { } GameInteractionEffectQueryResult UnsetSceneFlag::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } @@ -74,7 +74,7 @@ void UnsetSceneFlag::_Apply() { } GameInteractionEffectQueryResult SetFlag::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } @@ -86,7 +86,7 @@ void SetFlag::_Apply() { } GameInteractionEffectQueryResult UnsetFlag::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } @@ -99,7 +99,7 @@ void UnsetFlag::_Apply() { // MARK: - ModifyHeartContainers GameInteractionEffectQueryResult ModifyHeartContainers::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else if ((parameters[0] > 0 && (gSaveContext.healthCapacity + (parameters[0] * 0x10) > 0x140)) || (parameters[0] < 0 && (gSaveContext.healthCapacity + (parameters[0] * 0x10) < 0x10))) { @@ -115,7 +115,7 @@ void ModifyHeartContainers::_Apply() { // MARK: - FillMagic GameInteractionEffectQueryResult FillMagic::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else if (!gSaveContext.isMagicAcquired || gSaveContext.magic >= ((gSaveContext.isDoubleMagicAcquired + 1) * 48)) { return GameInteractionEffectQueryResult::NotPossible; @@ -129,7 +129,7 @@ void FillMagic::_Apply() { // MARK: - EmptyMagic GameInteractionEffectQueryResult EmptyMagic::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else if (!gSaveContext.isMagicAcquired || gSaveContext.magic <= 0) { return GameInteractionEffectQueryResult::NotPossible; @@ -143,7 +143,7 @@ void EmptyMagic::_Apply() { // MARK: - ModifyRupees GameInteractionEffectQueryResult ModifyRupees::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else if ((parameters[0] < 0 && gSaveContext.rupees <= 0) || (parameters[0] > 0 && gSaveContext.rupees >= CUR_CAPACITY(UPG_WALLET))) { @@ -158,7 +158,7 @@ void ModifyRupees::_Apply() { // MARK: - NoUI GameInteractionEffectQueryResult NoUI::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -173,7 +173,7 @@ void NoUI::_Remove() { // MARK: - ModifyGravity GameInteractionEffectQueryResult ModifyGravity::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -188,7 +188,7 @@ void ModifyGravity::_Remove() { // MARK: - ModifyHealth GameInteractionEffectQueryResult ModifyHealth::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else if ((parameters[0] > 0 && gSaveContext.health == gSaveContext.healthCapacity) || (parameters[0] < 0 && (gSaveContext.health + (16 * parameters[0]) <= 0))) { @@ -204,7 +204,7 @@ void ModifyHealth::_Apply() { // MARK: - SetPlayerHealth GameInteractionEffectQueryResult SetPlayerHealth::CanBeApplied() { Player* player = GET_PLAYER(gPlayState); - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -217,7 +217,7 @@ void SetPlayerHealth::_Apply() { // MARK: - FreezePlayer GameInteractionEffectQueryResult FreezePlayer::CanBeApplied() { Player* player = GET_PLAYER(gPlayState); - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -230,7 +230,7 @@ void FreezePlayer::_Apply() { // MARK: - BurnPlayer GameInteractionEffectQueryResult BurnPlayer::CanBeApplied() { Player* player = GET_PLAYER(gPlayState); - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -243,7 +243,7 @@ void BurnPlayer::_Apply() { // MARK: - ElectrocutePlayer GameInteractionEffectQueryResult ElectrocutePlayer::CanBeApplied() { Player* player = GET_PLAYER(gPlayState); - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -256,7 +256,7 @@ void ElectrocutePlayer::_Apply() { // MARK: - KnockbackPlayer GameInteractionEffectQueryResult KnockbackPlayer::CanBeApplied() { Player* player = GET_PLAYER(gPlayState); - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused() || player->stateFlags2 & PLAYER_STATE2_CRAWLING) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { @@ -269,7 +269,7 @@ void KnockbackPlayer::_Apply() { // MARK: - ModifyLinkSize GameInteractionEffectQueryResult ModifyLinkSize::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -284,7 +284,7 @@ void ModifyLinkSize::_Remove() { // MARK: - InvisibleLink GameInteractionEffectQueryResult InvisibleLink::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -299,7 +299,7 @@ void InvisibleLink::_Remove() { // MARK: - PacifistMode GameInteractionEffectQueryResult PacifistMode::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -314,7 +314,7 @@ void PacifistMode::_Remove() { // MARK: - DisableZTargeting GameInteractionEffectQueryResult DisableZTargeting::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -329,7 +329,7 @@ void DisableZTargeting::_Remove() { // MARK: - WeatherRainstorm GameInteractionEffectQueryResult WeatherRainstorm::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -344,7 +344,7 @@ void WeatherRainstorm::_Remove() { // MARK: - ReverseControls GameInteractionEffectQueryResult ReverseControls::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -359,7 +359,7 @@ void ReverseControls::_Remove() { // MARK: - ForceEquipBoots GameInteractionEffectQueryResult ForceEquipBoots::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -374,7 +374,7 @@ void ForceEquipBoots::_Remove() { // MARK: - ModifyMovementSpeedMultiplier GameInteractionEffectQueryResult ModifyMovementSpeedMultiplier::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -393,7 +393,7 @@ void ModifyMovementSpeedMultiplier::_Remove() { // MARK: - OneHitKO GameInteractionEffectQueryResult OneHitKO::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -408,7 +408,7 @@ void OneHitKO::_Remove() { // MARK: - ModifyDefenseModifier GameInteractionEffectQueryResult ModifyDefenseModifier::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -423,7 +423,7 @@ void ModifyDefenseModifier::_Remove() { // MARK: - GiveOrTakeShield GameInteractionEffectQueryResult GiveOrTakeShield::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else if ((parameters[0] > 0 && ((gBitFlags[parameters[0] - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_TYPE_SHIELD]) & gSaveContext.inventory.equipment)) || @@ -441,7 +441,7 @@ void GiveOrTakeShield::_Apply() { // MARK: - TeleportPlayer GameInteractionEffectQueryResult TeleportPlayer::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -453,7 +453,7 @@ void TeleportPlayer::_Apply() { // MARK: - ClearAssignedButtons GameInteractionEffectQueryResult ClearAssignedButtons::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -465,7 +465,7 @@ void ClearAssignedButtons::_Apply() { // MARK: - SetTimeOfDay GameInteractionEffectQueryResult SetTimeOfDay::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -477,7 +477,7 @@ void SetTimeOfDay::_Apply() { // MARK: - SetCollisionViewer GameInteractionEffectQueryResult SetCollisionViewer::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -492,7 +492,7 @@ void SetCollisionViewer::_Remove() { // MARK: - RandomizeCosmetics GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -504,7 +504,7 @@ void RandomizeCosmetics::_Apply() { // MARK: - PressButton GameInteractionEffectQueryResult PressButton::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -516,7 +516,7 @@ void PressButton::_Apply() { // MARK: - PressRandomButton GameInteractionEffectQueryResult PressRandomButton::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -528,7 +528,7 @@ void PressRandomButton::_Apply() { // MARK: - AddOrTakeAmmo GameInteractionEffectQueryResult AddOrTakeAmmo::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else if (!GameInteractor::CanAddOrTakeAmmo(parameters[0], parameters[1])) { return GameInteractionEffectQueryResult::NotPossible; @@ -542,7 +542,7 @@ void AddOrTakeAmmo::_Apply() { // MARK: - RandomBombFuseTimer GameInteractionEffectQueryResult RandomBombFuseTimer::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -557,7 +557,7 @@ void RandomBombFuseTimer::_Remove() { // MARK: - DisableLedgeGrabs GameInteractionEffectQueryResult DisableLedgeGrabs::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -572,7 +572,7 @@ void DisableLedgeGrabs::_Remove() { // MARK: - RandomWind GameInteractionEffectQueryResult RandomWind::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -587,7 +587,7 @@ void RandomWind::_Remove() { // MARK: - RandomBonks GameInteractionEffectQueryResult RandomBonks::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -602,7 +602,7 @@ void RandomBonks::_Remove() { // MARK: - PlayerInvincibility GameInteractionEffectQueryResult PlayerInvincibility::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -617,7 +617,7 @@ void PlayerInvincibility::_Remove() { // MARK: - SlipperyFloor GameInteractionEffectQueryResult SlipperyFloor::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { + if (!GameInteractor::IsSaveLoaded(true) || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; @@ -632,10 +632,10 @@ void SlipperyFloor::_Remove() { // MARK: - SpawnEnemyWithOffset GameInteractionEffectQueryResult SpawnEnemyWithOffset::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } - return GameInteractor::RawAction::SpawnEnemyWithOffset(parameters[0], parameters[1]); + return GameInteractionEffectQueryResult::Possible; } void SpawnEnemyWithOffset::_Apply() { @@ -644,10 +644,10 @@ void SpawnEnemyWithOffset::_Apply() { // MARK: - SpawnActor GameInteractionEffectQueryResult SpawnActor::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } - return GameInteractor::RawAction::SpawnActor(parameters[0], parameters[1]); + return GameInteractionEffectQueryResult::Possible; } void SpawnActor::_Apply() { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index 29bac7f5e..f2579db60 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -44,6 +44,7 @@ DEFINE_HOOK(OnPlayerFirstPersonControl, (Player * player)); DEFINE_HOOK(OnPlayerProcessStick, ()); DEFINE_HOOK(OnPlayerShieldControl, (float_t * sp50, float_t* sp54)); DEFINE_HOOK(OnPlayDestroy, ()); +DEFINE_HOOK(OnPlayDrawBegin, ()); DEFINE_HOOK(OnPlayDrawEnd, ()); DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs)); DEFINE_HOOK(OnSaveFile, (int32_t fileNum)); @@ -70,12 +71,15 @@ DEFINE_HOOK(OnUpdateFileBossRushOptionSelection, (uint8_t optionIndex, uint8_t o DEFINE_HOOK(OnUpdateFileRandomizerOptionSelection, (uint8_t optionIndex)); DEFINE_HOOK(OnUpdateFileNameSelection, (int16_t charCode)); DEFINE_HOOK(OnFileChooseMain, (void* gameState)); +DEFINE_HOOK(OnGenerationCompletion, ()); DEFINE_HOOK(OnSetGameLanguage, ()); -DEFINE_HOOK(OnFileDropped, (std::string filePath)); DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnKaleidoUpdate, ()); DEFINE_HOOK(OnRandomizerItemGivenHooks, (uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped)); DEFINE_HOOK(OnArchipelagoItemReceived, (uint32_t rg)); DEFINE_HOOK(OnRandomizerExternalCheck, (uint32_t rc)); + +// Audio +DEFINE_HOOK(OnSeqPlayerInit, (int32_t playerIdx, int32_t seqId)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 6a58e003a..0e9e0c58e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -194,6 +194,10 @@ void GameInteractor_ExecuteOnPlayDestroy() { GameInteractor::Instance->ExecuteHooks(); } +void GameInteractor_ExecuteOnPlayDrawBegin() { + GameInteractor::Instance->ExecuteHooks(); +} + void GameInteractor_ExecuteOnPlayDrawEnd() { GameInteractor::Instance->ExecuteHooks(); } @@ -333,7 +337,6 @@ void GameInteractor_ExecuteOnKaleidoUpdate() { } // Mark: Randomizer - void GameInteractor_ExecuteOnRandomizerItemGivenHooks(uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped) { GameInteractor::Instance->ExecuteHooks(rc, gi, isGiSkipped); } @@ -346,3 +349,8 @@ void GameInteractor_ExecuteOnArchipelagoItemReceived(uint32_t rg) { void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc) { GameInteractor::Instance->ExecuteHooks(rc); } + +// Mark: Audio +void GameInteractor_ExecuteOnSeqPlayerInit(int32_t playerIdx, int32_t seqId) { + GameInteractor::Instance->ExecuteHooks(playerIdx, seqId); +} diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 488a65d36..8700d89ab 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -47,6 +47,7 @@ void GameInteractor_ExecuteOnPlayerShieldControl(float_t* sp50, float_t* sp54); void GameInteractor_ExecuteOnPlayerProcessStick(); void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price); void GameInteractor_ExecuteOnPlayDestroy(); +void GameInteractor_ExecuteOnPlayDrawBegin(); void GameInteractor_ExecuteOnPlayDrawEnd(); bool GameInteractor_Should(GIVanillaBehavior flag, uint32_t result, ...); @@ -94,6 +95,9 @@ void GameInteractor_ExecuteOnRandomizerItemGivenHooks(uint32_t rc, GetItemEntry void GameInteractor_ExecuteOnArchipelagoItemReceived(uint32_t rg); void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc); +// Mark: - Audio +void GameInteractor_ExecuteOnSeqPlayerInit(int32_t playerIdx, int32_t seqId); + #ifdef __cplusplus } #endif diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 186307aed..08d663c7e 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -1362,6 +1362,22 @@ typedef enum { // - `*EnDs` VB_OFFER_BLUE_POTION, + // #### `result` + // ```c + // this->switchFlag >= 0 + // ``` + // #### `args` + // - `*EnOkarinaTag` + VB_OKARINA_TAG_COMPLETE, + + // #### `result` + // ```c + // (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)) + // ``` + // #### `args` + // - `*EnOkarinaTag` + VB_OKARINA_TAG_COMPLETED, + // #### `result` // ```c // CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) @@ -2155,6 +2171,23 @@ typedef enum { // - `*EnWood02` VB_TREE_DROP_COLLECTIBLE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*ObjWood02` + VB_TREE_SETUP_DRAW, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*ObjWood02` + VB_TREE_DROP_ITEM, + + // #### `result` // ```c // true // ``` @@ -2222,6 +2255,69 @@ typedef enum { // - `s32` limbCount // - `*Vec3s` frameTable VB_LOAD_PLAYER_ANIMATION_FRAME, + + // #### `result` + // ```c + // DoorWarp1_PlayerInRange(this, play) + // ``` + // #### `args` + // - `*DoorWarp1` + VB_BLUE_WARP_CONSIDER_ADULT_IN_RANGE, + + // #### `result` + // ```c + // (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowIngameTimer"), 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum + // <= 2) + // ``` + // #### `args` + // - `*PlayState` + VB_SHOW_GAMEPLAY_TIMER, + + // (this->dyna.actor.params >> 5 & 0x7F) == GI_ICE_TRAP && this->actionFunc == EnBox_Open && + // this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100 + // ``` + // #### `args` + // - `*EnBox` + VB_CHEST_USE_ICE_EFFECT, + + // #### `result` + // ```c + // arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y) + // ``` + // #### `args` + // - `*DoorShutter` + VB_BE_NEAR_DOOR_SHUTTER, + + // #### `result` + // ```c + // CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0) + // ``` + // #### `args` + // - None + VB_DRAW_2D_BACKGROUND, + + // #### `result` + // ```c + // CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0) + // ``` + // #### `args` + // - None + VB_LOAD_SKYBOX, + + // true + // ``` + // #### `args` + // - `*Player` + VB_SET_STATIC_PREV_FLOOR_TYPE, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*Player` + VB_SET_STATIC_FLOOR_TYPE, + } GIVanillaBehavior; #endif diff --git a/soh/soh/Enhancements/gameplaystats.h b/soh/soh/Enhancements/gameplaystats.h index 1f89cb3a4..1d60b5dfc 100644 --- a/soh/soh/Enhancements/gameplaystats.h +++ b/soh/soh/Enhancements/gameplaystats.h @@ -51,9 +51,48 @@ typedef enum { /* 0xA9 */ TIMESTAMP_DEFEAT_GANON, // z_boss_ganon2.c /* 0xA9 */ TIMESTAMP_BOSSRUSH_FINISH, // z_boss_ganon2.c /* 0xAA */ TIMESTAMP_FOUND_GREG, // z_parameter.c - /* 0xAA */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c - /* 0xAB */ TIMESTAMP_MAX - + /* 0xAB */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c + /* 0xAC */ TIMESTAMP_FOUND_GOHMA_SOUL, + /* 0xAD */ TIMESTAMP_FOUND_KING_DODONGO_SOUL, + /* 0xAE */ TIMESTAMP_FOUND_BARINADE_SOUL, + /* 0xAF */ TIMESTAMP_FOUND_PHANTOM_GANON_SOUL, + /* 0xB0 */ TIMESTAMP_FOUND_VOLVAGIA_SOUL, + /* 0xB1 */ TIMESTAMP_FOUND_MORPHA_SOUL, + /* 0xB2 */ TIMESTAMP_FOUND_BONGO_BONGO_SOUL, + /* 0xB3 */ TIMESTAMP_FOUND_TWINROVA_SOUL, + /* 0xB5 */ TIMESTAMP_FOUND_GANON_SOUL, + /* 0xB6 */ TIMESTAMP_FOUND_BRONZE_SCALE, + /* 0xB7 */ TIMESTAMP_FOUND_OCARINA_A_BUTTON, + /* 0xB8 */ TIMESTAMP_FOUND_OCARINA_C_UP_BUTTON, + /* 0xB9 */ TIMESTAMP_FOUND_OCARINA_C_DOWN_BUTTON, + /* 0xBA */ TIMESTAMP_FOUND_OCARINA_C_LEFT_BUTTON, + /* 0xBB */ TIMESTAMP_FOUND_OCARINA_C_RIGHT_BUTTON, + /* 0xBC */ TIMESTAMP_FOUND_FISHING_POLE, + /* 0xBD */ TIMESTAMP_FOUND_GUARD_HOUSE_KEY, + /* 0xBE */ TIMESTAMP_FOUND_MARKET_BAZAAR_KEY, + /* 0xBF */ TIMESTAMP_FOUND_MARKET_POTION_SHOP_KEY, + /* 0xC0 */ TIMESTAMP_FOUND_MASK_SHOP_KEY, + /* 0xC1 */ TIMESTAMP_FOUND_MARKET_SHOOTING_GALLERY_KEY, + /* 0xC2 */ TIMESTAMP_FOUND_BOMBCHU_BOWLING_KEY, + /* 0xC3 */ TIMESTAMP_FOUND_TREASURE_CHEST_GAME_BUILDING_KEY, + /* 0xC4 */ TIMESTAMP_FOUND_BOMBCHU_SHOP_KEY, + /* 0xC5 */ TIMESTAMP_FOUND_RICHARDS_HOUSE_KEY, + /* 0xC6 */ TIMESTAMP_FOUND_ALLEY_HOUSE_KEY, + /* 0xC7 */ TIMESTAMP_FOUND_KAK_BAZAAR_KEY, + /* 0xC8 */ TIMESTAMP_FOUND_KAK_POTION_SHOP_KEY, + /* 0xC9 */ TIMESTAMP_FOUND_BOSS_HOUSE_KEY, + /* 0xCA */ TIMESTAMP_FOUND_GRANNYS_POTION_SHOP_KEY, + /* 0xCB */ TIMESTAMP_FOUND_SKULLTULA_HOUSE_KEY, + /* 0xCC */ TIMESTAMP_FOUND_IMPAS_HOUSE_KEY, + /* 0xCD */ TIMESTAMP_FOUND_WINDMILL_KEY, + /* 0xCE */ TIMESTAMP_FOUND_KAK_SHOOTING_GALLERY_KEY, + /* 0xCF */ TIMESTAMP_FOUND_DAMPES_HUT_KEY, + /* 0xD0 */ TIMESTAMP_FOUND_TALONS_HOUSE_KEY, + /* 0xD1 */ TIMESTAMP_FOUND_STABLES_KEY, + /* 0xD2 */ TIMESTAMP_FOUND_BACK_TOWER_KEY, + /* 0xD3 */ TIMESTAMP_FOUND_HYLIA_LAB_KEY, + /* 0xD4 */ TIMESTAMP_FOUND_FISHING_HOLE_KEY, + /* 0xD5 */ TIMESTAMP_MAX } GameplayStatTimestamp; typedef enum { diff --git a/soh/soh/Enhancements/kaleido.cpp b/soh/soh/Enhancements/kaleido.cpp index eef19b495..2b9552263 100644 --- a/soh/soh/Enhancements/kaleido.cpp +++ b/soh/soh/Enhancements/kaleido.cpp @@ -16,7 +16,7 @@ extern PlayState* gPlayState; #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh_assets.h" #include "textures/icon_item_static/icon_item_static.h" -#include "consolevariablebridge.h" +#include #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" #include diff --git a/soh/soh/Enhancements/mod_menu.cpp b/soh/soh/Enhancements/mod_menu.cpp new file mode 100644 index 000000000..feb412350 --- /dev/null +++ b/soh/soh/Enhancements/mod_menu.cpp @@ -0,0 +1,239 @@ +#include "mod_menu.h" +#include +#include +#include "soh/SohGui/SohGui.hpp" +#include "soh/OTRGlobals.h" +#include "soh/resource/type/Skeleton.h" +#include +#include +#include + +std::vector enabledModFiles; +std::vector disabledModFiles; + +#define CVAR_ENABLED_MODS_NAME CVAR_GENERAL("EnabledMods") +#define CVAR_ENABLED_MODS_DEFAULT "" +#define CVAR_ENABLED_MODS_VALUE CVarGetString(CVAR_ENABLED_MODS_NAME, CVAR_ENABLED_MODS_DEFAULT) + +// "|" was chosen as the separator due to +// it being an invalid character in NTFS +// and being rarely used in ext4 +// it is also an ASCII character +// improving portability + +// if being an ASCII character is not a requirement, +// other possible candidates include: +// - U+FFFF: non-character +// - any private use character +#define SEPARATOR "|" + +void SetEnabledModsCVarValue() { + std::string s = ""; + + for (auto& modPath : enabledModFiles) { + s += modPath + SEPARATOR; + } + + // remove trailing separator if present + if (s.length() != 0) { + s.pop_back(); + } + + CVarSetString(CVAR_ENABLED_MODS_NAME, s.c_str()); +} + +std::vector GetEnabledModsFromCVar() { + std::string enabledModsCVarValue = CVAR_ENABLED_MODS_VALUE; + return StringHelper::Split(enabledModsCVarValue, SEPARATOR); +} + +std::vector& GetModFiles(bool enabled) { + return enabled ? enabledModFiles : disabledModFiles; +} + +std::shared_ptr GetArchiveManager() { + return Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager(); +} + +void UpdateModFiles(bool init = false) { + if (init) { + enabledModFiles.clear(); + } + disabledModFiles.clear(); + std::vector enabledMods = GetEnabledModsFromCVar(); + std::string modsPath = Ship::Context::LocateFileAcrossAppDirs("mods", appShortName); + if (modsPath.length() > 0 && std::filesystem::exists(modsPath)) { + if (std::filesystem::is_directory(modsPath)) { + for (const std::filesystem::directory_entry& p : std::filesystem::recursive_directory_iterator( + modsPath, std::filesystem::directory_options::follow_directory_symlink)) { + std::string extension = p.path().extension().string(); + if ( +#ifndef EXCLUDE_MPQ_SUPPORT + StringHelper::IEquals(extension, ".otr") || StringHelper::IEquals(extension, ".mpq") || +#endif + StringHelper::IEquals(extension, ".o2r") || StringHelper::IEquals(extension, ".zip")) { + std::string path = p.path().generic_string(); + bool shouldBeEnabled = std::find(enabledMods.begin(), enabledMods.end(), path) != enabledMods.end(); + + if (shouldBeEnabled) { + if (init) { + enabledModFiles.push_back(path); + GetArchiveManager()->AddArchive(path); + } + } else { + disabledModFiles.push_back(path); + } + } + } + } + } +} + +extern "C" void gfx_texture_cache_clear(); + +void AfterModChange() { + SetEnabledModsCVarValue(); + // TODO: runtime changes + /* + gfx_texture_cache_clear(); + SOH::SkeletonPatcher::ClearSkeletons(); + */ + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + + // disabled mods are always sorted + std::sort(disabledModFiles.begin(), disabledModFiles.end(), [](const std::string& a, const std::string& b) { + return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), + [](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); }); + }); +} + +void EnableMod(std::string file) { + disabledModFiles.erase(std::find(disabledModFiles.begin(), disabledModFiles.end(), file)); + enabledModFiles.insert(enabledModFiles.begin(), file); + + // TODO: runtime changes + // GetArchiveManager()->AddArchive(file); + AfterModChange(); +} + +void DisableMod(std::string file) { + enabledModFiles.erase(std::find(enabledModFiles.begin(), enabledModFiles.end(), file)); + disabledModFiles.insert(disabledModFiles.begin(), file); + + // TODO: runtime changes + // GetArchiveManager()->RemoveArchive(file); + AfterModChange(); +} + +void DrawModInfo(std::string file) { + ImGui::SameLine(); + ImGui::Text("%s", file.c_str()); +} + +void DrawMods(bool enabled) { + std::vector& selectedModFiles = GetModFiles(enabled); + if (selectedModFiles.empty()) { + return; + } + + bool madeAnyChange = false; + int switchFromIndex = -1; + int switchToIndex = -1; + + for (int i = 0; i < selectedModFiles.size(); i += 1) { + std::string file = selectedModFiles[i]; + if (UIWidgets::StateButton((file + "_left_right").c_str(), enabled ? ICON_FA_ARROW_LEFT : ICON_FA_ARROW_RIGHT, + ImVec2(25, 25), UIWidgets::ButtonOptions().Color(THEME_COLOR))) { + if (enabled) { + DisableMod(file); + } else { + EnableMod(file); + } + } + + // it's not relevant to reorder disabled mods + if (enabled) { + ImGui::SameLine(); + if (i == 0) { + ImGui::BeginDisabled(); + } + if (UIWidgets::StateButton((file + "_up").c_str(), ICON_FA_ARROW_UP, ImVec2(25, 25), + UIWidgets::ButtonOptions().Color(THEME_COLOR))) { + madeAnyChange = true; + switchFromIndex = i; + switchToIndex = i - 1; + } + if (i == 0) { + ImGui::EndDisabled(); + } + + ImGui::SameLine(); + if (i == selectedModFiles.size() - 1) { + ImGui::BeginDisabled(); + } + if (UIWidgets::StateButton((file + "_down").c_str(), ICON_FA_ARROW_DOWN, ImVec2(25, 25), + UIWidgets::ButtonOptions().Color(THEME_COLOR))) { + madeAnyChange = true; + switchFromIndex = i; + switchToIndex = i + 1; + } + if (i == selectedModFiles.size() - 1) { + ImGui::EndDisabled(); + } + } + + DrawModInfo(file); + } + + if (madeAnyChange) { + std::iter_swap(selectedModFiles.begin() + switchFromIndex, selectedModFiles.begin() + switchToIndex); + AfterModChange(); + } +} + +void ModMenuWindow::DrawElement() { + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); + + const ImVec4 yellow = ImVec4(1, 1, 0, 1); + + ImGui::TextColored( + yellow, "Mods are currently not reloaded at runtime.\nClose and re-open Ship for the changes to take effect."); + + if (UIWidgets::Button("Update", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) { + UpdateModFiles(); + } + UIWidgets::Tooltip("Re-check the mods folder for new files"); + + if (ImGui::BeginTable("tableMods", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { + ImGui::TableSetupColumn("Disabled Mods", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Enabled Mods", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::TableHeadersRow(); + ImGui::PopItemFlag(); + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + + if (ImGui::BeginChild("Disabled Mods", ImVec2(0, -8))) { + DrawMods(false); + + ImGui::EndChild(); + } + + ImGui::TableNextColumn(); + + if (ImGui::BeginChild("Enabled Mods", ImVec2(0, -8))) { + DrawMods(true); + + ImGui::EndChild(); + } + + ImGui::EndTable(); + } + + ImGui::EndDisabled(); +} + +void ModMenuWindow::InitElement() { + UpdateModFiles(true); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/mod_menu.h b/soh/soh/Enhancements/mod_menu.h new file mode 100644 index 000000000..cb29b4001 --- /dev/null +++ b/soh/soh/Enhancements/mod_menu.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#ifdef __cplusplus +class ModMenuWindow : public Ship::GuiWindow { + public: + using GuiWindow::GuiWindow; + + void InitElement() override; + void DrawElement() override; + void UpdateElement() override{}; +}; +#endif \ No newline at end of file diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 391806b16..259a5e47f 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -6,7 +6,6 @@ #include "soh/SaveManager.h" #include "soh/ResourceManagerHelpers.h" #include "soh/resource/type/Skeleton.h" -#include "soh/Enhancements/boss-rush/BossRushTypes.h" #include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/randomizer/3drando/random.hpp" @@ -50,7 +49,6 @@ extern "C" { extern SaveContext gSaveContext; extern PlayState* gPlayState; -extern void Overlay_DisplayText(float duration, const char* text); } // GreyScaleEndDlist @@ -132,10 +130,27 @@ void RegisterOcarinaTimeTravel() { bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime && !nearbyFrogs && !nearbyGossipStone; bool hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME); - bool doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2; bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER); - // TODO: Once Swordless Adult is fixed: Remove the Master Sword check - if (justPlayedSoT && notNearAnySource && (hasOcarinaOfTime || doesntNeedOcarinaOfTime) && hasMasterSword) { + int timeTravelSetting = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0); + bool meetsTimeTravelRequirements = false; + + switch (timeTravelSetting) { + case TIME_TRAVEL_ANY: + meetsTimeTravelRequirements = true; + break; + case TIME_TRAVEL_ANY_MS: + meetsTimeTravelRequirements = hasMasterSword; + break; + case TIME_TRAVEL_OOT_MS: + meetsTimeTravelRequirements = hasMasterSword && hasOcarinaOfTime; + break; + case TIME_TRAVEL_OOT: + default: + meetsTimeTravelRequirements = hasOcarinaOfTime; + break; + } + + if (justPlayedSoT && notNearAnySource && meetsTimeTravelRequirements) { SwitchAge(); } }); @@ -284,49 +299,6 @@ void UpdateHyperEnemiesState() { } } -void RegisterBonkDamage() { - GameInteractor::Instance->RegisterGameHook([]() { - uint8_t bonkOption = CVarGetInteger(CVAR_ENHANCEMENT("BonkDamageMult"), BONK_DAMAGE_NONE); - if (bonkOption == BONK_DAMAGE_NONE) { - return; - } - - if (bonkOption == BONK_DAMAGE_OHKO) { - gSaveContext.health = 0; - return; - } - - uint16_t bonkDamage = 0; - switch (bonkOption) { - case BONK_DAMAGE_QUARTER_HEART: - bonkDamage = 4; - break; - case BONK_DAMAGE_HALF_HEART: - bonkDamage = 8; - break; - case BONK_DAMAGE_1_HEART: - bonkDamage = 16; - break; - case BONK_DAMAGE_2_HEARTS: - bonkDamage = 32; - break; - case BONK_DAMAGE_4_HEARTS: - bonkDamage = 64; - break; - case BONK_DAMAGE_8_HEARTS: - bonkDamage = 128; - break; - default: - break; - } - - Health_ChangeBy(gPlayState, -bonkDamage); - // Set invincibility to make Link flash red as a visual damage indicator. - Player* player = GET_PLAYER(gPlayState); - player->invincibilityTimer = 28; - }); -} - void UpdateDirtPathFixState(int32_t sceneNum) { switch (sceneNum) { case SCENE_HYRULE_FIELD: @@ -959,7 +931,6 @@ void RegisterCustomSkeletons() { } void InitMods() { - BossRush_RegisterHooks(); RandomizerRegisterHooks(); TimeSaverRegisterHooks(); RegisterTTS(); @@ -968,7 +939,6 @@ void InitMods() { RegisterDeleteFileOnDeath(); RegisterHyperBosses(); UpdateHyperEnemiesState(); - RegisterBonkDamage(); RegisterMenuPathFix(); RegisterMirrorModeHandler(); RegisterResetNaviTimer(); diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 2ac5a3592..3204ace65 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -9,7 +9,6 @@ #include "hints.hpp" #include "shops.hpp" #include "pool_functions.hpp" -//#include "debug.hpp" #include "soh/Enhancements/randomizer/static_data.h" #include "soh/Enhancements/debugger/performanceTimer.h" @@ -685,9 +684,9 @@ void LookForExternalArea(Region* currentRegion, std::set& alreadyChecke void SetAreas() { auto ctx = Rando::Context::GetInstance(); - // RANDOTODO give entrances an enum like RandomizerCheck, the give them all areas here, - // then use those areas to not need to recursivly find ItemLocation areas when an identifying entrance's area - for (int regionType = 0; regionType < RR_MARKER_AREAS_END; regionType++) { + // RANDOTODO give entrances an enum like RandomizerCheck, then give them all areas here, + // then use those areas to not need to recursively find ItemLocation areas when identifying entrance's area + for (int regionType = 0; regionType < RR_MAX; regionType++) { Region* region = &areaTable[regionType]; std::set areas = region->GetAllAreas(); std::set regionsToSet = { region }; @@ -974,8 +973,7 @@ static void RandomizeDungeonRewards() { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; }); - if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA) || - ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS) + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS) .Is(RO_DUNGEON_REWARDS_VANILLA)) { // Place dungeon rewards in vanilla locations for (RandomizerCheck loc : Rando::StaticData::dungeonRewardLocations) { ctx->GetItemLocation(loc)->PlaceVanillaItem(); diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 21891ff81..598940082 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2257,6 +2257,11 @@ void StaticData::HintTable_Init() { /*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#.^Tu devrais aller y jeter un coup d'oeil, @!\x0B", {QM_GREEN, QM_RED}, {}, TEXTBOX_TYPE_BLUE)); + hintTextTable[RHT_MIDO_HINT] = HintText(CustomMessage("You'll never find the #Kokiri Sword# I hid in #[[1]]#!", + /*german*/ "Du wirst nie das #Kokiri-Schwert# finden, das ich in #[[1]]# versteckt habe!", + /*french*/ "Pfeuuh! Tu n'trouveras jamais l'#Epée Kokiri# que j'ai cachée dans #[[1]]#!", + {QM_GREEN, QM_RED})); + hintTextTable[RHT_LOACH_HINT] = HintText(CustomMessage("What?^You wanna know about the&%rHyrule Loach%w?^It's a big fish, but it's so rare that I'll give my %g[[1]]%w to anyone who catches it. Seriously!", /*german*/ "Was?^Du willst etwas über die&%rhylianische Forelle%w wissen?&Es ist ein riesiger Fisch,&der unfassbar selten ist!^Wenn Du mir eine bringst, |springt|springen| für Dich&%g[[1]]%w dabei raus.&Ganz im Ernst!", /*french*/ "Quoi?&Tu veux en savoir plus sur le&%rBrochet d'Hyrule%w?^C'est un gros poisson, mais il&est si rare que je donne&%g[[1]]%w&à celui qui l'attrape.^Ouais, j'suis sérieux!", diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index 5fcb213ff..0c40dfdb9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -2102,6 +2102,30 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß eine #Kiste im Labor am See# #[[1]]# enthielte.", /*french*/ "Selon moi, une #caisse dans un laboratoire# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_TREE_HYRULE_FIELD] = + HintText(CustomMessage("They say that a #tree in Hyrule Field# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #arbre dans la Plaine d'Hyrule# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_TREE_MARKET] = + HintText(CustomMessage("They say that a #tree in Hyrule Market# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #arbre sur la Place du Marché# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_TREE_HYRULE_CASTLE] = + HintText(CustomMessage("They say that a #tree in Hyrule Castle# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #arbre au Château d'Hyrule# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_TREE_ZORAS_RIVER] = + HintText(CustomMessage("They say that a #tree in Zora's River# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #arbre à la Rivière Zora# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_TREE_ZORAS_FOUNTAIN] = + HintText(CustomMessage("They say that a #tree in Zora's Fountain# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #arbre à la Fontaine Zora# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_TREE_LON_LON_RANCH] = + HintText(CustomMessage("They say that a #tree in Lon Lon Ranch# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #arbre au Ranch Lon Lon# cache #[[1]]#.", { QM_RED, QM_GREEN })); // clang-format on } } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index f5195c91d..c74c0ff23 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -426,7 +426,7 @@ void StaticData::HintTable_Init_Item() { CustomMessage("a tree killer", /*german*/"ein Baumtöter", /*french*/"un coupeur d'arbres")}); // /*spanish*/un destructor de árboles - hintTextTable[RHT_BROKEN_SWORD] = HintText(CustomMessage("the Broken Goron's Sword", /*german*/"das zerbrochene Goronen-Schwert", /*french*/"l'Épée Brisée de Goron"), + hintTextTable[RHT_BROKEN_SWORD] = HintText(CustomMessage("the Broken Goron's Sword", /*german*/"das Zerbr. Goronen-Schwert", /*french*/"l'Épée Brisée de Goron"), // /*spanish*/la espada goron rota { CustomMessage("a trade quest item", /*german*/"ein Handelsgegenstand", /*french*/"un objet de quête d'échanges"), diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 3e6588646..e8cab933f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -604,17 +604,23 @@ void GenerateItemPool() { ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL); PlaceItemsForType(RCTYPE_POT, overworldPotsActive, dungeonPotsActive); + // Shuffle Trees + bool treesActive = (bool)ctx->GetOption(RSK_SHUFFLE_TREES); + PlaceItemsForType(RCTYPE_TREE, treesActive, false); + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC)) { + PlaceItemsForType(RCTYPE_NLTREE, treesActive, false); + } + // Shuffle Crates bool overworldCratesActive = ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_OVERWORLD) || ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_ALL); - bool overworldNLCratesActive = ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) && - (ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_OVERWORLD) || - ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_ALL)); bool dungeonCratesActive = ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_DUNGEONS) || ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_ALL); PlaceItemsForType(RCTYPE_CRATE, overworldCratesActive, dungeonCratesActive); - PlaceItemsForType(RCTYPE_NLCRATE, overworldNLCratesActive, dungeonCratesActive); PlaceItemsForType(RCTYPE_SMALL_CRATE, overworldCratesActive, dungeonCratesActive); + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC)) { + PlaceItemsForType(RCTYPE_NLCRATE, overworldCratesActive, dungeonCratesActive); + } auto fsMode = ctx->GetOption(RSK_FISHSANITY); if (fsMode.IsNot(RO_FISHSANITY_OFF)) { @@ -861,7 +867,7 @@ void GenerateItemPool() { AddItemToMainPool(RG_GERUDO_MEMBERSHIP_CARD); ctx->possibleIceTrapModels.push_back(RG_GERUDO_MEMBERSHIP_CARD); } else if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { - AddItemToPool(PendingJunkPool, RG_GERUDO_MEMBERSHIP_CARD); + AddItemToPool(ItemPool, RG_GERUDO_MEMBERSHIP_CARD); ctx->PlaceItemInLocation(RC_TH_FREED_CARPENTERS, RG_ICE_TRAP, false, true); } else { ctx->PlaceItemInLocation(RC_TH_FREED_CARPENTERS, RG_GERUDO_MEMBERSHIP_CARD, false, true); @@ -990,13 +996,44 @@ void GenerateItemPool() { AddItemsToPool(ItemPool, shopsanityRupees); // Shopsanity gets extra large rupees } - // Shuffle Fairies - if (ctx->GetOption(RSK_SHUFFLE_FAIRIES)) { - for (auto rc : Rando::StaticData::GetOverworldFairyLocations()) { + // Shuffle Fountain Fairies + if (ctx->GetOption(RSK_SHUFFLE_FOUNTAIN_FAIRIES)) { + for (auto rc : Rando::StaticData::GetFountainFairyLocations()) { AddItemToMainPool(GetJunkItem()); } - // 8 extra for Ganon's Castle + 2 Dodongo's Cavern Gossip Stone + 3 Shadow Temple - int extra = 13; + // 8 extra for Ganon's Castle + int extra = 8; + for (int i = 0; i < extra; i++) { + AddItemToMainPool(GetJunkItem()); + } + } + + // Shuffle Gossip Stone Fairies + if (ctx->GetOption(RSK_SHUFFLE_STONE_FAIRIES)) { + for (auto rc : Rando::StaticData::GetStoneFairyLocations()) { + AddItemToMainPool(GetJunkItem()); + } + // 2 Dodongo's Cavern Gossip Stone + int extra = 2; + for (int i = 0; i < extra; i++) { + AddItemToMainPool(GetJunkItem()); + } + } + + // Shuffle Bean Fairies + if (ctx->GetOption(RSK_SHUFFLE_BEAN_FAIRIES)) { + for (auto rc : Rando::StaticData::GetBeanFairyLocations()) { + AddItemToMainPool(GetJunkItem()); + } + } + + // Shuffle Song Fairies + if (ctx->GetOption(RSK_SHUFFLE_SONG_FAIRIES)) { + for (auto rc : Rando::StaticData::GetSongFairyLocations()) { + AddItemToMainPool(GetJunkItem()); + } + // 3 Shadow Temple + int extra = 3; extra += ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla() ? 0 : 2; extra += ctx->GetDungeon(Rando::WATER_TEMPLE)->IsVanilla() ? 0 : 3; extra += ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->IsVanilla() ? 2 : 1; diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 1e4a3db38..7e73d2906 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -65,13 +65,9 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations, Random_Init(finalHash); ctx->SetHash(std::to_string(finalHash)); - if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { - VanillaFill(); // Just place items in their vanilla locations - } else { // Fill locations with logic - int ret = Fill(); - if (ret < 0) { - return ret; - } + int ret = Fill(); + if (ret < 0) { + return ret; } GenerateHash(); diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index 51cfdd535..28f8537b4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -5,7 +5,7 @@ #include "rando_main.hpp" #include "../context.h" #include -#include +#include #include #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp index 441454cd0..0a6ff6ac9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp @@ -434,12 +434,12 @@ void InitTrickNames() { }; trickNameTable[RG_BROKEN_SWORD] = { Text{ "Broken Biggoron's Sword", "Épée brisée de Grogoron", - "zerbr. Biggoron-Schwert" }, // "Espada de Biggoron rota" - Text{ "Broken Giant's Knife", "Lame des Géants brisée", "zerbr. Langschwert" }, // "Daga gigante rota" - Text{ "Broken Noble Sword", "Épée noble brisée", "zerbr. Edelschwert" }, // "Espada noble rota" - Text{ "Broken Picori Blade", "Épée Minish brisée", "zerbr. Schwert der Minish" }, // "Espada minish rota" + "Zerbr. Biggoron-Schwert" }, // "Espada de Biggoron rota" + Text{ "Broken Giant's Knife", "Lame des Géants brisée", "Zerbr. Langschwert" }, // "Daga gigante rota" + Text{ "Broken Noble Sword", "Épée noble brisée", "Zerbr. Edelschwert" }, // "Espada noble rota" + Text{ "Broken Picori Blade", "Épée Minish brisée", "Zerbr. Schwert der Minish" }, // "Espada minish rota" Text{ "Decayed Master Sword", "Épée de légende pourrie", - "zerfr. Master-Schwert" }, // "Espada decadente de leyenda" + "Zerf. Master-Schwert" }, // "Espada decadente de leyenda" }; trickNameTable[RG_PRESCRIPTION] = { Text{ "Biggoron's Prescription", "Ordonnance de Grogoron", "Biggorons Rezept" }, // "Receta de Biggoron" @@ -691,7 +691,7 @@ void InitTrickNames() { trickNameTable[RG_RUTOS_LETTER] = { Text{ "Bottle with Maggie's Letter", "Flacon avec lettre de Maggy", - "Flasche (Dolores Brief)" }, // "Carta de Dolores" + "Flasche (Dolores' Brief)" }, // "Carta de Dolores" Text{ "Bottle with Letter to Kafei", "Flacon avec lettre pour Kafei", "Flasche (Brief an Kafei)" }, // "Carta para Kafei" Text{ "Bottle with Zelda's Letter", "Flacon avec Lettre de Zelda", @@ -717,7 +717,7 @@ void InitTrickNames() { }; trickNameTable[RG_SARIAS_SONG] = { Text{ "Mido's Song", "La chanson de Mido", "Midos Lied" }, // "La canción de Mido" - Text{ "Kass' Theme", "Le thème de Kass", "Kashiwa Thema" }, // "El tema de Kass" + Text{ "Kass' Theme", "Le thème de Kass", "Kashiwas Thema" }, // "El tema de Kass" Text{ "Tune of Echoes", "Chant des Échos ", "Melodie des Echos" }, // "Melodía del Eco" }; trickNameTable[RG_SUNS_SONG] = { @@ -916,7 +916,7 @@ void InitTrickNames() { }; trickNameTable[RG_MORPHA_SOUL] = { Text{ "Dihydrogen Monoxide", "Monoxyde de Dihydrogène", "Dihydrogenmonoxid" }, - Text{ "Morpha Molecules", "Molécule de Morpha", "Morphas Molekyle" }, + Text{ "Morpha Molecules", "Molécule de Morpha", "Morphas Moleküle" }, Text{ "Wet Stuff", "Truc Mouillé", "nasses Zeug" }, }; trickNameTable[RG_BONGO_BONGO_SOUL] = { @@ -1114,7 +1114,7 @@ void InitTrickNames() { }; trickNameTable[GI_CUCCO] = { Text{"D.I.Y. Alarm Clock", "Réveille-matin improvisé", "Improvisierter Wecker"}, // "Alarma emplumada" - Text{"Kakariko Cucco", "Cocotte Cocorico", "Kakariko Huhn" }, // "Cuco de Kakariko" + Text{"Kakariko Cucco", "Cocotte Cocorico", "Kakariko-Huhn" }, // "Cuco de Kakariko" Text{"Hatched Cucco", "Cocotte éclose", "Geschlüpftes Küken" }, // "Pollo" }; trickNameTable[GI_MASK_KEATON] = { @@ -1169,4 +1169,4 @@ Text GetIceTrapName(uint8_t id) { } // Randomly get the easy, medium, or hard name for the given item id return RandomElement(trickNameTable[id]); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 3c91a1f70..b3e71e8f0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -26,10 +26,10 @@ #include #include -#include +#include #include -#include "consolevariablebridge.h" +#include using json = nlohmann::ordered_json; using namespace Rando; diff --git a/soh/soh/Enhancements/randomizer/Plandomizer.cpp b/soh/soh/Enhancements/randomizer/Plandomizer.cpp index 4e03e8b8f..06bb69003 100644 --- a/soh/soh/Enhancements/randomizer/Plandomizer.cpp +++ b/soh/soh/Enhancements/randomizer/Plandomizer.cpp @@ -647,7 +647,7 @@ void PlandomizerOverlayText(std::pair drawObject) { imageMax.y - ImGui::CalcTextSize(std::to_string(drawObject.second).c_str()).y - 2); ImGui::SetCursorScreenPos(textPos); - ImGui::Text(std::to_string(drawObject.second).c_str()); + ImGui::Text("%s", std::to_string(drawObject.second).c_str()); // Overlay item info if (drawObject.first.GetRandomizerGet() >= RG_PROGRESSIVE_HOOKSHOT && @@ -665,7 +665,7 @@ void PlandomizerOverlayText(std::pair drawObject) { ImGui::SetCursorScreenPos(textPos); std::string overlayText = "+"; overlayText += extractNumberInParentheses(drawObject.first.GetName().english.c_str()); - ImGui::Text(overlayText.c_str()); + ImGui::Text("%s", overlayText.c_str()); } if (drawObject.first.GetRandomizerGet() >= RG_FOREST_TEMPLE_BOSS_KEY && drawObject.first.GetRandomizerGet() <= RG_GANONS_CASTLE_BOSS_KEY) { @@ -678,7 +678,7 @@ void PlandomizerOverlayText(std::pair drawObject) { break; } } - ImGui::Text(shortName.c_str()); + ImGui::Text("%s", shortName.c_str()); } if (drawObject.first.GetRandomizerGet() >= RG_OCARINA_A_BUTTON && drawObject.first.GetRandomizerGet() <= RG_OCARINA_C_RIGHT_BUTTON) { @@ -691,7 +691,7 @@ void PlandomizerOverlayText(std::pair drawObject) { break; } } - ImGui::Text(shortName.c_str()); + ImGui::Text("%s", shortName.c_str()); } } @@ -1066,7 +1066,7 @@ void PlandomizerDrawHintsWindow() { ImGui::SeparatorText(hintData.hintName.c_str()); ImGui::Text("Current Hint: "); ImGui::SameLine(); - ImGui::TextWrapped(hintData.hintText.c_str()); + ImGui::TextWrapped("%s", hintData.hintText.c_str()); if (spoilerHintData.size() > 0) { hintInputText = plandoHintData[index].hintText.c_str(); @@ -1115,9 +1115,9 @@ void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) { auto randoArea = Rando::StaticData::GetLocation(checkID)->GetArea(); if (rcArea == RCAREA_INVALID || rcArea == randoArea) { ImGui::TableNextColumn(); - ImGui::TextWrapped(spoilerData.checkName.c_str()); + ImGui::TextWrapped("%s", spoilerData.checkName.c_str()); ImGui::TableNextColumn(); - ImGui::TextWrapped(spoilerData.checkRewardItem.GetName().english.c_str()); + ImGui::TextWrapped("%s", spoilerData.checkRewardItem.GetName().english.c_str()); ImGui::TableNextColumn(); PlandomizerDrawItemSlots(index); if (plandoLogData[index].checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) { diff --git a/soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp b/soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp index c94c68511..00c060cf9 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp @@ -43,7 +43,7 @@ void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) { objComb->unk_1B0 -= 50; const auto beehiveIdentity = ObjectExtension::GetInstance().Get(&objComb->actor); - if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && beehiveIdentity == nullptr && + if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && beehiveIdentity != nullptr && !Flags_GetRandomizerInf(beehiveIdentity->randomizerInf)) { if (objComb->unk_1B0 <= -5000) { objComb->unk_1B0 = 1500; @@ -55,7 +55,10 @@ void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) { if ((objComb->collider.base.acFlags & AC_HIT) != 0) { objComb->collider.base.acFlags &= ~AC_HIT; s32 dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags; - if (dmgFlags & 0x4001F866) { + + bool slingBowDmg = RAND_GET_OPTION(RSK_SLINGBOW_BREAK_BEEHIVES) && (dmgFlags & (DMG_ARROW | DMG_SLINGSHOT)); + + if ((dmgFlags & 0x4001F866) && !slingBowDmg) { objComb->unk_1B0 = 1500; } else { ObjComb_Break(objComb, play); @@ -82,9 +85,11 @@ void ObjComb_RandomizerInit(void* actor) { void ObjComb_RandomizerUpdate(void* actor) { ObjComb* combActor = reinterpret_cast(actor); + PlayState* play = gPlayState; + combActor->unk_1B2 += 0x2EE0; + combActor->actionFunc(combActor, play); combActor->actor.shape.rot.x = - static_cast(Math_SinS(combActor->unk_1B2)) * CLAMP_MIN(combActor->unk_1B0, 0) + - combActor->actor.home.rot.x; + Math_SinS(combActor->unk_1B2) * CLAMP_MIN(combActor->unk_1B0, 0) + combActor->actor.home.rot.x; } void RegisterShuffleBeehives() { @@ -94,7 +99,7 @@ void RegisterShuffleBeehives() { COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_COMB, shouldRegister, ObjComb_RandomizerUpdate); } -static RegisterShipInitFunc initFunc(RegisterShuffleBeehives, { "IS_RANDO" }); +static RegisterShipInitFunc registerShuffleBeehives(RegisterShuffleBeehives, { "IS_RANDO" }); void Rando::StaticData::RegisterBeehiveLocations() { static bool registered = false; @@ -138,4 +143,4 @@ void Rando::StaticData::RegisterBeehiveLocations() { } static ObjectExtension::Register RegisterBeehiveIdentity; -static RegisterShipInitFunc registerFunc(Rando::StaticData::RegisterBeehiveLocations); +static RegisterShipInitFunc registerBeehiveLocations(Rando::StaticData::RegisterBeehiveLocations); diff --git a/soh/soh/Enhancements/randomizer/ShuffleCows.cpp b/soh/soh/Enhancements/randomizer/ShuffleCows.cpp index 17ae3a834..63fbd858c 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleCows.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleCows.cpp @@ -58,7 +58,7 @@ void RegisterShuffleCows() { }); } -static RegisterShipInitFunc initFunc(RegisterShuffleCows, { "IS_RANDO" }); +static RegisterShipInitFunc registerShuffleCows(RegisterShuffleCows, { "IS_RANDO" }); void Rando::StaticData::RegisterCowLocations() { static bool registered = false; @@ -79,4 +79,4 @@ void Rando::StaticData::RegisterCowLocations() { // clang-format-on } -static RegisterShipInitFunc registerFunc(Rando::StaticData::RegisterCowLocations); +static RegisterShipInitFunc registerCowLocations(Rando::StaticData::RegisterCowLocations); diff --git a/soh/soh/Enhancements/randomizer/ShuffleCrates.cpp b/soh/soh/Enhancements/randomizer/ShuffleCrates.cpp index 53a65df22..007c12bc0 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleCrates.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleCrates.cpp @@ -336,7 +336,7 @@ void Rando::StaticData::RegisterCrateLocations() { locationTable[RC_GF_SOUTHMOST_CENTER_CRATE] = Location::Crate(RC_GF_SOUTHMOST_CENTER_CRATE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(315, -1534), "Southmost Center Crate", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_SOUTHMOST_CENTER_CRATE)); locationTable[RC_GF_MID_SOUTH_CENTER_CRATE] = Location::Crate(RC_GF_MID_SOUTH_CENTER_CRATE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(315, -1594), "Middle South Center Crate", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_MID_SOUTH_CENTER_CRATE)); locationTable[RC_GF_MID_NORTH_CENTER_CRATE] = Location::Crate(RC_GF_MID_NORTH_CENTER_CRATE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(310, -1782), "Middle North Center Crate", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_MID_NORTH_CENTER_CRATE)); - locationTable[RR_GF_NORTHMOST_CENTER_CRATE] = Location::Crate(RR_GF_NORTHMOST_CENTER_CRATE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(310, -1842), "Northmost Center Crate", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_NORTHMOST_CENTER_CRATE)); + locationTable[RC_GF_NORTHMOST_CENTER_CRATE] = Location::Crate(RC_GF_NORTHMOST_CENTER_CRATE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(310, -1842), "Northmost Center Crate", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_NORTHMOST_CENTER_CRATE)); locationTable[RC_GF_OUTSKIRTS_NE_CRATE] = Location::Crate(RC_GF_OUTSKIRTS_NE_CRATE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(-60, -2210), "Outskirts Northeast Crate", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_OUTSKIRTS_NE_CRATE)); locationTable[RC_GF_OUTSKIRTS_NW_CRATE] = Location::Crate(RC_GF_OUTSKIRTS_NW_CRATE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(-120, -2210), "Outskirts Northwest Crate", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_OUTSKIRTS_NW_CRATE)); locationTable[RC_GF_HBA_RANGE_CRATE_2] = Location::Crate(RC_GF_HBA_RANGE_CRATE_2, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, TWO_ACTOR_PARAMS(4090, -1780), "Horseback Archery Range Crate 2", RHT_CRATE_GERUDOS_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_HBA_RANGE_CRATE_2)); @@ -597,5 +597,5 @@ void Rando::StaticData::RegisterCrateLocations() { static ObjectExtension::Register RegisterCrateIdentity; static ObjectExtension::Register RegisterSmallCrateIdentity; -static RegisterShipInitFunc initFunc(RegisterShuffleCrates, { "IS_RANDO" }); -static RegisterShipInitFunc locFunc(Rando::StaticData::RegisterCrateLocations); +static RegisterShipInitFunc registerShuffleCrates(RegisterShuffleCrates, { "IS_RANDO" }); +static RegisterShipInitFunc registerCrateLocations(Rando::StaticData::RegisterCrateLocations); diff --git a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp index 666ba0a21..75717f8e9 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp @@ -89,7 +89,11 @@ static bool SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params, FairyType f } void RegisterShuffleFairies() { - bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_FAIRIES); + bool shouldRegisterFountain = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_FOUNTAIN_FAIRIES); + bool shouldRegisterStone = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_STONE_FAIRIES); + bool shouldRegisterBean = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_BEAN_FAIRIES); + bool shouldRegisterSong = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_SONG_FAIRIES); + bool shouldRegister = shouldRegisterFountain || shouldRegisterStone || shouldRegisterBean || shouldRegisterSong; // Grant item when picking up fairy. COND_VB_SHOULD(VB_FAIRY_HEAL, shouldRegister, { @@ -106,7 +110,7 @@ void RegisterShuffleFairies() { }); // Spawn fairies in fairy fountains - COND_VB_SHOULD(VB_SPAWN_FOUNTAIN_FAIRIES, shouldRegister, { + COND_VB_SHOULD(VB_SPAWN_FOUNTAIN_FAIRIES, shouldRegisterFountain, { Actor* actor = va_arg(args, Actor*); bool fairySpawned = false; s16 grottoId = (gPlayState->sceneNum == SCENE_FAIRYS_FOUNTAIN) ? Grotto_CurrentGrotto() : 0; @@ -122,7 +126,7 @@ void RegisterShuffleFairies() { }); // Spawn 3 fairies when playing Song of Storms next to a planted bean - COND_VB_SHOULD(VB_SPAWN_BEAN_STALK_FAIRIES, shouldRegister, { + COND_VB_SHOULD(VB_SPAWN_BEAN_STALK_FAIRIES, shouldRegisterBean, { ObjBean* objBean = va_arg(args, ObjBean*); bool fairySpawned = false; for (s16 index = 0; index < 3; index++) { @@ -138,7 +142,7 @@ void RegisterShuffleFairies() { }); // Spawn a fairy from a ShotSun when playing the right song near it - COND_VB_SHOULD(VB_SPAWN_SONG_FAIRY, shouldRegister, { + COND_VB_SHOULD(VB_SPAWN_SONG_FAIRY, shouldRegisterSong, { ShotSun* shotSun = va_arg(args, ShotSun*); if (SpawnFairy(shotSun->actor.world.pos.x, shotSun->actor.world.pos.y, shotSun->actor.world.pos.z, TWO_ACTOR_PARAMS(0x1000, (int32_t)shotSun->actor.world.pos.z), FAIRY_HEAL_BIG)) { @@ -147,7 +151,7 @@ void RegisterShuffleFairies() { }); // Handle playing both misc songs and song of storms in front of a gossip stone. - COND_VB_SHOULD(VB_SPAWN_GOSSIP_STONE_FAIRY, shouldRegister, { + COND_VB_SHOULD(VB_SPAWN_GOSSIP_STONE_FAIRY, shouldRegisterStone, { EnGs* gossipStone = va_arg(args, EnGs*); FairyType fairyType = FAIRY_HEAL; @@ -196,229 +200,229 @@ void Rando::StaticData::RegisterFairyLocations() { return; registered = true; // clang-format off - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_1] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1800, "Fairy Grotto Fairy 1", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_1)); - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_2] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1801, "Fairy Grotto Fairy 2", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_2)); - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_3] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1802, "Fairy Grotto Fairy 3", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_3)); - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_4] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1803, "Fairy Grotto Fairy 4", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_4)); - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_5] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1804, "Fairy Grotto Fairy 5", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_5)); - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_6] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1805, "Fairy Grotto Fairy 6", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_6)); - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_7] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1806, "Fairy Grotto Fairy 7", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_7)); - locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_8] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1807, "Fairy Grotto Fairy 8", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_8)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_1] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0300, "Fairy Grotto Fairy 1", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_1)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_2] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0301, "Fairy Grotto Fairy 2", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_2)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_3] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0302, "Fairy Grotto Fairy 3", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_3)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_4] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0303, "Fairy Grotto Fairy 4", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_4)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_5] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0304, "Fairy Grotto Fairy 5", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_5)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_6] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0305, "Fairy Grotto Fairy 6", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_6)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_7] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0306, "Fairy Grotto Fairy 7", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_7)); - locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_8] = Location::Fairy(RC_ZR_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0307, "Fairy Grotto Fairy 8", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_8)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_1] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F00, "Fairy Grotto Fairy 1", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_1)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_2] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F01, "Fairy Grotto Fairy 2", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_2)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_3] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F02, "Fairy Grotto Fairy 3", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_3)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_4] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F03, "Fairy Grotto Fairy 4", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_4)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_5] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F04, "Fairy Grotto Fairy 5", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_5)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_6] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F05, "Fairy Grotto Fairy 6", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_6)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_7] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F06, "Fairy Grotto Fairy 7", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_7)); - locationTable[RC_HF_FAIRY_GROTTO_FAIRY_8] = Location::Fairy(RC_HF_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F07, "Fairy Grotto Fairy 8", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_8)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_1] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C00, "Fairy Grotto Fairy 1", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_1)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_2] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C01, "Fairy Grotto Fairy 2", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_2)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_3] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C02, "Fairy Grotto Fairy 3", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_3)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_4] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C03, "Fairy Grotto Fairy 4", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_4)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_5] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C04, "Fairy Grotto Fairy 5", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_5)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_6] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C05, "Fairy Grotto Fairy 6", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_6)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_7] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C06, "Fairy Grotto Fairy 7", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_7)); - locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_8] = Location::Fairy(RC_ZD_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C07, "Fairy Grotto Fairy 8", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_8)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_1] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D00, "Fairy Grotto Fairy 1", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_1)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_2] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D01, "Fairy Grotto Fairy 2", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_2)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_3] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D02, "Fairy Grotto Fairy 3", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_3)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_4] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D03, "Fairy Grotto Fairy 4", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_4)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_5] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D04, "Fairy Grotto Fairy 5", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_5)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_6] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D05, "Fairy Grotto Fairy 6", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_6)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_7] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D06, "Fairy Grotto Fairy 7", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_7)); - locationTable[RC_GF_FAIRY_GROTTO_FAIRY_8] = Location::Fairy(RC_GF_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D07, "Fairy Grotto Fairy 8", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_8)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_1] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1800, "Fairy Grotto Fairy 1", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_1)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_2] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1801, "Fairy Grotto Fairy 2", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_2)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_3] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1802, "Fairy Grotto Fairy 3", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_3)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_4] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1803, "Fairy Grotto Fairy 4", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_4)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_5] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1804, "Fairy Grotto Fairy 5", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_5)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_6] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1805, "Fairy Grotto Fairy 6", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_6)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_7] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1806, "Fairy Grotto Fairy 7", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_7)); + locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_8] = Location::FountainFairy(RC_SFM_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1807, "Fairy Grotto Fairy 8", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_8)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_1] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0300, "Fairy Grotto Fairy 1", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_1)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_2] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0301, "Fairy Grotto Fairy 2", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_2)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_3] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0302, "Fairy Grotto Fairy 3", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_3)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_4] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0303, "Fairy Grotto Fairy 4", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_4)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_5] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0304, "Fairy Grotto Fairy 5", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_5)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_6] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0305, "Fairy Grotto Fairy 6", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_6)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_7] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0306, "Fairy Grotto Fairy 7", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_7)); + locationTable[RC_ZR_FAIRY_GROTTO_FAIRY_8] = Location::FountainFairy(RC_ZR_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_FAIRYS_FOUNTAIN, 0x0307, "Fairy Grotto Fairy 8", RHT_ZR_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_FAIRY_GROTTO_FAIRY_8)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_1] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F00, "Fairy Grotto Fairy 1", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_1)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_2] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F01, "Fairy Grotto Fairy 2", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_2)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_3] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F02, "Fairy Grotto Fairy 3", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_3)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_4] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F03, "Fairy Grotto Fairy 4", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_4)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_5] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F04, "Fairy Grotto Fairy 5", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_5)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_6] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F05, "Fairy Grotto Fairy 6", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_6)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_7] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F06, "Fairy Grotto Fairy 7", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_7)); + locationTable[RC_HF_FAIRY_GROTTO_FAIRY_8] = Location::FountainFairy(RC_HF_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_FAIRYS_FOUNTAIN, 0x0F07, "Fairy Grotto Fairy 8", RHT_HF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FAIRY_GROTTO_FAIRY_8)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_1] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C00, "Fairy Grotto Fairy 1", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_1)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_2] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C01, "Fairy Grotto Fairy 2", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_2)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_3] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C02, "Fairy Grotto Fairy 3", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_3)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_4] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C03, "Fairy Grotto Fairy 4", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_4)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_5] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C04, "Fairy Grotto Fairy 5", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_5)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_6] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C05, "Fairy Grotto Fairy 6", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_6)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_7] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C06, "Fairy Grotto Fairy 7", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_7)); + locationTable[RC_ZD_FAIRY_GROTTO_FAIRY_8] = Location::FountainFairy(RC_ZD_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_FAIRYS_FOUNTAIN, 0x1C07, "Fairy Grotto Fairy 8", RHT_ZD_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_FAIRY_GROTTO_FAIRY_8)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_1] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D00, "Fairy Grotto Fairy 1", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_1)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_2] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_2, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D01, "Fairy Grotto Fairy 2", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_2)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_3] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_3, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D02, "Fairy Grotto Fairy 3", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_3)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_4] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_4, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D03, "Fairy Grotto Fairy 4", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_4)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_5] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_5, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D04, "Fairy Grotto Fairy 5", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_5)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_6] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_6, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D05, "Fairy Grotto Fairy 6", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_6)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_7] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_7, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D06, "Fairy Grotto Fairy 7", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_7)); + locationTable[RC_GF_FAIRY_GROTTO_FAIRY_8] = Location::FountainFairy(RC_GF_FAIRY_GROTTO_FAIRY_8, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_FAIRYS_FOUNTAIN, 0x1D07, "Fairy Grotto Fairy 8", RHT_GF_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_FAIRY_GROTTO_FAIRY_8)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_1] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x00, "Shield Grave Fairy 1", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_1)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_2] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x01, "Shield Grave Fairy 2", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_2)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_3] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x02, "Shield Grave Fairy 3", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_3)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_4] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x03, "Shield Grave Fairy 4", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_4)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_5] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x04, "Shield Grave Fairy 5", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_5)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_6] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x05, "Shield Grave Fairy 6", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_6)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_7] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_7, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x06, "Shield Grave Fairy 7", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_7)); - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_8] = Location::Fairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_8, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x07, "Shield Grave Fairy 8", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_8)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_1] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_1, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x00, "Scrubs Fairy 1", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_1)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_2] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_2, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x01, "Scrubs Fairy 2", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_2)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_3] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_3, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x02, "Scrubs Fairy 3", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_3)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_4] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_4, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x03, "Scrubs Fairy 4", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_4)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_5] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_5, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x04, "Scrubs Fairy 5", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_5)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_6] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_6, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x05, "Scrubs Fairy 6", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_6)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_7] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_7, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x06, "Scrubs Fairy 7", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_7)); - locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_8] = Location::Fairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_8, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x07, "Scrubs Fairy 8", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_8)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_1] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_1, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x00, "MQ Scrubs Fairy 1", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_1)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_2] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_2, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x01, "MQ Scrubs Fairy 2", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_2)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_3] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_3, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x02, "MQ Scrubs Fairy 3", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_3)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_4] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_4, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x03, "MQ Scrubs Fairy 4", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_4)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_5] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_5, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x04, "MQ Scrubs Fairy 5", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_5)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_6] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_6, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x05, "MQ Scrubs Fairy 6", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_6)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_7] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_7, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x06, "MQ Scrubs Fairy 7", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_7)); - locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_8] = Location::Fairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_8, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x07, "MQ Scrubs Fairy 8", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_8)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_1] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_1, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x00, "Oasis Fairy 1", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_1)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_2] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_2, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x01, "Oasis Fairy 2", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_2)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_3] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_3, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x02, "Oasis Fairy 3", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_3)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_4] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_4, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x03, "Oasis Fairy 4", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_4)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_5] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_5, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x04, "Oasis Fairy 5", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_5)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_6] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_6, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x05, "Oasis Fairy 6", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_6)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_7] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_7, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x06, "Oasis Fairy 7", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_7)); - locationTable[RC_COLOSSUS_OASIS_FAIRY_8] = Location::Fairy(RC_COLOSSUS_OASIS_FAIRY_8, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x07, "Oasis Fairy 8", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_8)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_1] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x00, "Shield Grave Fairy 1", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_1)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_2] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x01, "Shield Grave Fairy 2", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_2)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_3] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x02, "Shield Grave Fairy 3", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_3)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_4] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x03, "Shield Grave Fairy 4", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_4)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_5] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x04, "Shield Grave Fairy 5", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_5)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_6] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x05, "Shield Grave Fairy 6", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_6)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_7] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_7, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x06, "Shield Grave Fairy 7", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_7)); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_8] = Location::FountainFairy(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_8, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 0x07, "Shield Grave Fairy 8", RHT_GRAVEYARD_SHIELD_GRAVE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_SHIELD_GRAVE_FAIRY_8)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_1] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_1, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x00, "Scrubs Fairy 1", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_1)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_2] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_2, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x01, "Scrubs Fairy 2", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_2)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_3] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_3, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x02, "Scrubs Fairy 3", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_3)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_4] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_4, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x03, "Scrubs Fairy 4", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_4)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_5] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_5, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x04, "Scrubs Fairy 5", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_5)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_6] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_6, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x05, "Scrubs Fairy 6", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_6)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_7] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_7, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x06, "Scrubs Fairy 7", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_7)); + locationTable[RC_GANONS_CASTLE_SCRUBS_FAIRY_8] = Location::FountainFairy(RC_GANONS_CASTLE_SCRUBS_FAIRY_8, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x07, "Scrubs Fairy 8", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SCRUBS_FAIRY_8)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_1] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_1, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x00, "MQ Scrubs Fairy 1", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_1)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_2] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_2, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x01, "MQ Scrubs Fairy 2", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_2)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_3] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_3, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x02, "MQ Scrubs Fairy 3", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_3)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_4] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_4, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x03, "MQ Scrubs Fairy 4", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_4)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_5] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_5, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x04, "MQ Scrubs Fairy 5", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_5)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_6] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_6, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x05, "MQ Scrubs Fairy 6", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_6)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_7] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_7, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x06, "MQ Scrubs Fairy 7", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_7)); + locationTable[RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_8] = Location::FountainFairy(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_8, RCQUEST_MQ, RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, 0x07, "MQ Scrubs Fairy 8", RHT_GANONS_CASTLE_SCRUBS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_SCRUBS_FAIRY_8)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_1] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_1, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x00, "Oasis Fairy 1", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_1)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_2] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_2, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x01, "Oasis Fairy 2", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_2)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_3] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_3, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x02, "Oasis Fairy 3", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_3)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_4] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_4, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x03, "Oasis Fairy 4", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_4)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_5] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_5, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x04, "Oasis Fairy 5", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_5)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_6] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_6, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x05, "Oasis Fairy 6", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_6)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_7] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_7, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x06, "Oasis Fairy 7", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_7)); + locationTable[RC_COLOSSUS_OASIS_FAIRY_8] = Location::FountainFairy(RC_COLOSSUS_OASIS_FAIRY_8, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x07, "Oasis Fairy 8", RHT_COLOSSUS_OASIS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_OASIS_FAIRY_8)); - locationTable[RC_ZR_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_ZR_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 0x0300, "Bean Sprout Fairy 1", RHT_ZR_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_ZR_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_ZR_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 0x0301, "Bean Sprout Fairy 2", RHT_ZR_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_ZR_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_ZR_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 0x0302, "Bean Sprout Fairy 3", RHT_ZR_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_KF_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_KF_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 0x0900, "Bean Sprout Fairy 1", RHT_KF_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_KF_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_KF_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 0x0901, "Bean Sprout Fairy 2", RHT_KF_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_KF_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_KF_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 0x0902, "Bean Sprout Fairy 3", RHT_KF_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1] = Location::Fairy(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x0400, "Bean Sprout Near Bridge Fairy 1", RHT_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1)); - locationTable[RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2] = Location::Fairy(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x0401, "Bean Sprout Near Bridge Fairy 2", RHT_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2)); - locationTable[RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3] = Location::Fairy(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x0402, "Bean Sprout Near Bridge Fairy 3", RHT_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3)); - locationTable[RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1] = Location::Fairy(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x1200, "Bean Sprout Near Theatre Fairy 1", RHT_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1)); - locationTable[RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2] = Location::Fairy(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x1201, "Bean Sprout Near Theatre Fairy 2", RHT_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2)); - locationTable[RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3] = Location::Fairy(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x1202, "Bean Sprout Near Theatre Fairy 3", RHT_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3)); - locationTable[RC_LH_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_LH_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 0x0100, "Bean Sprout Fairy 1", RHT_LH_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_LH_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_LH_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 0x0101, "Bean Sprout Fairy 2", RHT_LH_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_LH_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_LH_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 0x0102, "Bean Sprout Fairy 3", RHT_LH_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_GV_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_GV_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 0x0300, "Bean Sprout Fairy 1", RHT_GV_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_GV_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_GV_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 0x0301, "Bean Sprout Fairy 2", RHT_GV_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_GV_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_GV_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 0x0302, "Bean Sprout Fairy 3", RHT_GV_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_COLOSSUS_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_COLOSSUS_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x1800, "Bean Sprout Fairy 1", RHT_COLOSSUS_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_COLOSSUS_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_COLOSSUS_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x1801, "Bean Sprout Fairy 2", RHT_COLOSSUS_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_COLOSSUS_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_COLOSSUS_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x1802, "Bean Sprout Fairy 3", RHT_COLOSSUS_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 0x0300, "Bean Sprout Fairy 1", RHT_GRAVEYARD_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_GRAVEYARD_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 0x0301, "Bean Sprout Fairy 2", RHT_GRAVEYARD_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_GRAVEYARD_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 0x0302, "Bean Sprout Fairy 3", RHT_GRAVEYARD_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_DMC_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_DMC_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 0x0300, "Bean Sprout Fairy 1", RHT_DMC_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_DMC_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_DMC_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 0x0301, "Bean Sprout Fairy 2", RHT_DMC_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_DMC_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_DMC_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 0x0302, "Bean Sprout Fairy 3", RHT_DMC_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_DMT_BEAN_SPROUT_FAIRY_1] = Location::Fairy(RC_DMT_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 0x0600, "Bean Sprout Fairy 1", RHT_DMT_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_BEAN_SPROUT_FAIRY_1)); - locationTable[RC_DMT_BEAN_SPROUT_FAIRY_2] = Location::Fairy(RC_DMT_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 0x0601, "Bean Sprout Fairy 2", RHT_DMT_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_BEAN_SPROUT_FAIRY_2)); - locationTable[RC_DMT_BEAN_SPROUT_FAIRY_3] = Location::Fairy(RC_DMT_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 0x0602, "Bean Sprout Fairy 3", RHT_DMT_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_ZR_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_ZR_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 0x0300, "Bean Sprout Fairy 1", RHT_ZR_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_ZR_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_ZR_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 0x0301, "Bean Sprout Fairy 2", RHT_ZR_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_ZR_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_ZR_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 0x0302, "Bean Sprout Fairy 3", RHT_ZR_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_KF_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_KF_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 0x0900, "Bean Sprout Fairy 1", RHT_KF_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_KF_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_KF_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 0x0901, "Bean Sprout Fairy 2", RHT_KF_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_KF_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_KF_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 0x0902, "Bean Sprout Fairy 3", RHT_KF_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1] = Location::BeanFairy(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x0400, "Bean Sprout Near Bridge Fairy 1", RHT_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1)); + locationTable[RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2] = Location::BeanFairy(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x0401, "Bean Sprout Near Bridge Fairy 2", RHT_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2)); + locationTable[RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3] = Location::BeanFairy(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x0402, "Bean Sprout Near Bridge Fairy 3", RHT_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3)); + locationTable[RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1] = Location::BeanFairy(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x1200, "Bean Sprout Near Theatre Fairy 1", RHT_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1)); + locationTable[RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2] = Location::BeanFairy(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x1201, "Bean Sprout Near Theatre Fairy 2", RHT_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2)); + locationTable[RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3] = Location::BeanFairy(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 0x1202, "Bean Sprout Near Theatre Fairy 3", RHT_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3)); + locationTable[RC_LH_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_LH_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 0x0100, "Bean Sprout Fairy 1", RHT_LH_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_LH_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_LH_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 0x0101, "Bean Sprout Fairy 2", RHT_LH_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_LH_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_LH_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 0x0102, "Bean Sprout Fairy 3", RHT_LH_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_GV_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_GV_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 0x0300, "Bean Sprout Fairy 1", RHT_GV_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_GV_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_GV_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 0x0301, "Bean Sprout Fairy 2", RHT_GV_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_GV_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_GV_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 0x0302, "Bean Sprout Fairy 3", RHT_GV_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_COLOSSUS_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_COLOSSUS_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x1800, "Bean Sprout Fairy 1", RHT_COLOSSUS_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_COLOSSUS_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_COLOSSUS_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x1801, "Bean Sprout Fairy 2", RHT_COLOSSUS_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_COLOSSUS_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_COLOSSUS_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 0x1802, "Bean Sprout Fairy 3", RHT_COLOSSUS_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 0x0300, "Bean Sprout Fairy 1", RHT_GRAVEYARD_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_GRAVEYARD_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 0x0301, "Bean Sprout Fairy 2", RHT_GRAVEYARD_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_GRAVEYARD_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 0x0302, "Bean Sprout Fairy 3", RHT_GRAVEYARD_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_DMC_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_DMC_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 0x0300, "Bean Sprout Fairy 1", RHT_DMC_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_DMC_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_DMC_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 0x0301, "Bean Sprout Fairy 2", RHT_DMC_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_DMC_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_DMC_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 0x0302, "Bean Sprout Fairy 3", RHT_DMC_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_BEAN_SPROUT_FAIRY_3)); + locationTable[RC_DMT_BEAN_SPROUT_FAIRY_1] = Location::BeanFairy(RC_DMT_BEAN_SPROUT_FAIRY_1, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 0x0600, "Bean Sprout Fairy 1", RHT_DMT_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_BEAN_SPROUT_FAIRY_1)); + locationTable[RC_DMT_BEAN_SPROUT_FAIRY_2] = Location::BeanFairy(RC_DMT_BEAN_SPROUT_FAIRY_2, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 0x0601, "Bean Sprout Fairy 2", RHT_DMT_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_BEAN_SPROUT_FAIRY_2)); + locationTable[RC_DMT_BEAN_SPROUT_FAIRY_3] = Location::BeanFairy(RC_DMT_BEAN_SPROUT_FAIRY_3, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 0x0602, "Bean Sprout Fairy 3", RHT_DMT_BEAN_SPROUT_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_BEAN_SPROUT_FAIRY_3)); - locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -680), "ToT Left Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFTMOST_GOSSIP_STONE_FAIRY)); - locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -680), "ToT Left Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFTMOST_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -615), "ToT Left Center Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY)); - locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -615), "ToT Left Center Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -550), "ToT Right Center Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY)); - locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -550), "ToT Right Center Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -485), "ToT Right Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY)); - locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -485), "ToT Right Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_DMC_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_DMC_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS( 0, 1656), "Gossip Stone Fairy", RHT_DMC_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GOSSIP_STONE_FAIRY)); - locationTable[RC_DMC_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_DMC_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS(0x1000, 1656), "Gossip Stone Big Fairy", RHT_DMC_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_DMT_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_DMT_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, TWO_ACTOR_PARAMS( 0, -3935), "Gossip Stone Fairy", RHT_DMT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GOSSIP_STONE_FAIRY)); - locationTable[RC_DMT_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_DMT_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, TWO_ACTOR_PARAMS(0x1000, -3935), "Gossip Stone Big Fairy", RHT_DMT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_COLOSSUS_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_COLOSSUS_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, TWO_ACTOR_PARAMS( 0, 1320), "Gossip Stone Fairy", RHT_COLOSSUS_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GOSSIP_STONE_FAIRY)); - locationTable[RC_COLOSSUS_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_COLOSSUS_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, TWO_ACTOR_PARAMS(0x1000, 1320), "Gossip Stone Big Fairy", RHT_COLOSSUS_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, RCQUEST_VANILLA,RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS( 0, -1520), "Gossip Stone Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY)); - locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, RCQUEST_VANILLA,RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(0x1000, -1520), "Gossip Stone Big Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS( 0, -916), "MQ Gossip Stone Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY)); - locationTable[RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY_BIG, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(0x1000, -916), "MQ Gossip Stone Big Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_GV_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_GV_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, TWO_ACTOR_PARAMS( 0, -2340), "Gossip Stone Fairy", RHT_GV_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_GOSSIP_STONE_FAIRY)); - locationTable[RC_GV_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_GV_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, TWO_ACTOR_PARAMS(0x1000, -2340), "Gossip Stone Big Fairy", RHT_GV_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_GC_MAZE_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_GC_MAZE_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS( 0, -1265), "Maze Gossip Stone Fairy", RHT_GC_MAZE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MAZE_GOSSIP_STONE_FAIRY)); - locationTable[RC_GC_MAZE_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_GC_MAZE_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(0x1000, -1265), "Maze Gossip Stone Big Fairy", RHT_GC_MAZE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MAZE_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS( 0, 1496), "Medigoron Gossip Stone Fairy", RHT_GC_MEDIGORON_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MEDIGORON_GOSSIP_STONE_FAIRY)); - locationTable[RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(0x1000, 1496), "Medigoron Gossip Stone Big Fairy", RHT_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_GRAVEYARD_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_GRAVEYARD_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, TWO_ACTOR_PARAMS( 0, -75), "Gossip Stone Fairy", RHT_GRAVEYARD_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_GOSSIP_STONE_FAIRY)); - locationTable[RC_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, TWO_ACTOR_PARAMS(0x1000, -75), "Gossip Stone Big Fairy", RHT_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_HC_MALON_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_HC_MALON_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS( 0, 3445), "Malon Gossip Stone Fairy", RHT_HC_MALON_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_MALON_GOSSIP_STONE_FAIRY)); - locationTable[RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(0x1000, 3445), "Malon Gossip Stone Big Fairy", RHT_HC_MALON_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_MALON_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS( 0, 1041), "Rock Wall Gossip Stone Fairy", RHT_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_ROCK_WALL_GOSSIP_STONE_FAIRY)); - locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(0x1000, 1041), "Rock Wall Gossip Stone Big Fairy", RHT_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0xC, 735), "Storms Grotto Gossip Stone Fairy", RHT_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x100C, 735), "Storms Grotto Gossip Stone Big Fairy", RHT_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS( 0, -2230), "Deku Tree Left Gossip Stone Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY)); - locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(0x1000, -2230), "Deku Tree Left Gossip Stone Big Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS( 0, -700), "Deku Tree Right Gossip Stone Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY)); - locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(0x1000, -700), "Deku Tree Right Gossip Stone Big Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_KF_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_KF_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS( 0, -1223), "Gossip Stone Fairy", RHT_KF_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_GOSSIP_STONE_FAIRY)); - locationTable[RC_KF_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_KF_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(0x1000, -1223), "Gossip Stone Big Fairy", RHT_KF_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x1B, -236), "Storms Gossip Stone Fairy", RHT_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x101B, -236), "Storms Gossip Stone Big Fairy", RHT_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_LH_LAB_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_LH_LAB_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS( 0, 3212), "Lab Gossip Stone Fairy", RHT_LH_LAB_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_LAB_GOSSIP_STONE_FAIRY)); - locationTable[RC_LH_LAB_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_LH_LAB_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 3212), "Lab Gossip Stone Big Fairy", RHT_LH_LAB_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_LAB_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS( 0, 8395), "Southeast Gossip Stone Fairy", RHT_LH_SOUTHEAST_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHEAST_GOSSIP_STONE_FAIRY)); - locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 8395), "Southeast Gossip Stone Big Fairy", RHT_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS( 0, 7984), "Southwest Gossip Stone Fairy", RHT_LH_SOUTHWEST_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHWEST_GOSSIP_STONE_FAIRY)); - locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 7984), "Southwest Gossip Stone Big Fairy", RHT_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_LW_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_LW_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS( 0, 2300), "Gossip Stone Fairy", RHT_LW_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_GOSSIP_STONE_FAIRY)); - locationTable[RC_LW_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_LW_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS(0x1000, 2300), "Gossip Stone Big Fairy", RHT_LW_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS( 0, 1370), "Maze Lower Gossip Stone Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY)); - locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS(0x1000, 1370), "Maze Lower Gossip Stone Big Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS( 0, 740), "Maze Upper Gossip Stone Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY)); - locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS(0x1000, 740), "Maze Upper Gossip Stone Big Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_SFM_SARIA_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_SFM_SARIA_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS( 0, -2300), "Saria Gossip Stone Fairy", RHT_SFM_SARIA_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_SARIA_GOSSIP_STONE_FAIRY)); - locationTable[RC_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS(0x1000, -2300), "Saria Gossip Stone Big Fairy", RHT_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_ZD_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_ZD_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS( 0, -1600), "Gossip Stone Fairy", RHT_ZD_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_GOSSIP_STONE_FAIRY)); - locationTable[RC_ZD_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_ZD_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(0x1000, -1600), "Gossip Stone Big Fairy", RHT_ZD_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_ZF_FAIRY_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS( 0, 2205), "Fairy Gossip Stone Fairy", RHT_ZF_FAIRY_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_FAIRY_GOSSIP_STONE_FAIRY)); - locationTable[RC_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(0x1000, 2205), "Fairy Gossip Stone Big Fairy", RHT_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_ZF_JABU_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_ZF_JABU_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS( 0, -985), "Jabu Gossip Stone Fairy", RHT_ZF_JABU_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_JABU_GOSSIP_STONE_FAIRY)); - locationTable[RC_ZF_JABU_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_ZF_JABU_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(0x1000, -985), "Jabu Gossip Stone Big Fairy", RHT_ZF_JABU_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_JABU_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS( 0, -1070), "Near Grottos Gossip Stone Fairy", RHT_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY)); - locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(0x1000, -1070), "Near Grottos Gossip Stone Big Fairy", RHT_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS( 0, -1650), "Near Domain Gossip Stone Fairy", RHT_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY)); - locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(0x1000, -1650), "Near Domain Gossip Stone Big Fairy", RHT_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x11, -357), "Cow Grotto Gossip Stone Fairy", RHT_HF_COW_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1011, -357), "Cow Grotto Gossip Stone Big Fairy", RHT_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x10, -236), "Near Market Gossip Stone Fairy", RHT_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1010, -236), "Near Market Gossip Stone Big Fairy", RHT_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x14, -236), "Southeast Gossip Stone Fairy", RHT_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1014, -236), "Southeast Gossip Stone Big Fairy", RHT_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x13, -236), "Open Grotto Gossip Stone Fairy", RHT_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1013, -236), "Open Grotto Gossip Stone Big Fairy", RHT_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0xA, -236), "Open Grotto Gossip Stone Fairy", RHT_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x100A, -236), "Open Grotto Gossip Stone Big Fairy", RHT_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x4, -236), "Open Grotto Gossip Stone Fairy", RHT_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1004, -236), "Open Grotto Gossip Stone Big Fairy", RHT_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x1A, -236), "Tunnel Grotto Gossip Stone Fairy", RHT_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x101A, -236), "Tunnel Grotto Gossip Stone Big Fairy", RHT_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x8, -236), "Storms Grotto Gossip Stone Fairy", RHT_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1008, -236), "Storms Grotto Gossip Stone Big Fairy", RHT_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY] = Location::Fairy(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x6, -236), "Upper Grotto Gossip Stone Fairy", RHT_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY)); - locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::Fairy(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1006, -236), "Upper Grotto Gossip Stone Big Fairy", RHT_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -680), "ToT Left Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFTMOST_GOSSIP_STONE_FAIRY)); + locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -680), "ToT Left Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFTMOST_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -615), "ToT Left Center Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY)); + locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -615), "ToT Left Center Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_LEFT_CENTER_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -550), "ToT Right Center Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY)); + locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -550), "ToT Right Center Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHT_CENTER_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS( 0, -485), "ToT Right Gossip Stone Fairy", RHT_TOT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY)); + locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_MARKET, SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, TWO_ACTOR_PARAMS(0x1000, -485), "ToT Right Gossip Stone Big Fairy", RHT_TOT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TOT_RIGHTMOST_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_DMC_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_DMC_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS( 0, 1656), "Gossip Stone Fairy", RHT_DMC_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GOSSIP_STONE_FAIRY)); + locationTable[RC_DMC_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_DMC_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS(0x1000, 1656), "Gossip Stone Big Fairy", RHT_DMC_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_DMT_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_DMT_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, TWO_ACTOR_PARAMS( 0, -3935), "Gossip Stone Fairy", RHT_DMT_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GOSSIP_STONE_FAIRY)); + locationTable[RC_DMT_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_DMT_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, TWO_ACTOR_PARAMS(0x1000, -3935), "Gossip Stone Big Fairy", RHT_DMT_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_COLOSSUS_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_COLOSSUS_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, TWO_ACTOR_PARAMS( 0, 1320), "Gossip Stone Fairy", RHT_COLOSSUS_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GOSSIP_STONE_FAIRY)); + locationTable[RC_COLOSSUS_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_COLOSSUS_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, TWO_ACTOR_PARAMS(0x1000, 1320), "Gossip Stone Big Fairy", RHT_COLOSSUS_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, RCQUEST_VANILLA,RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS( 0, -1520), "Gossip Stone Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY)); + locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, RCQUEST_VANILLA,RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(0x1000, -1520), "Gossip Stone Big Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS( 0, -916), "MQ Gossip Stone Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY)); + locationTable[RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY_BIG, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(0x1000, -916), "MQ Gossip Stone Big Fairy", RHT_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_GV_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_GV_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, TWO_ACTOR_PARAMS( 0, -2340), "Gossip Stone Fairy", RHT_GV_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_GOSSIP_STONE_FAIRY)); + locationTable[RC_GV_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_GV_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, TWO_ACTOR_PARAMS(0x1000, -2340), "Gossip Stone Big Fairy", RHT_GV_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GV_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_GC_MAZE_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_GC_MAZE_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS( 0, -1265), "Maze Gossip Stone Fairy", RHT_GC_MAZE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MAZE_GOSSIP_STONE_FAIRY)); + locationTable[RC_GC_MAZE_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_GC_MAZE_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(0x1000, -1265), "Maze Gossip Stone Big Fairy", RHT_GC_MAZE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MAZE_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS( 0, 1496), "Medigoron Gossip Stone Fairy", RHT_GC_MEDIGORON_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MEDIGORON_GOSSIP_STONE_FAIRY)); + locationTable[RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(0x1000, 1496), "Medigoron Gossip Stone Big Fairy", RHT_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_GRAVEYARD_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_GRAVEYARD_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, TWO_ACTOR_PARAMS( 0, -75), "Gossip Stone Fairy", RHT_GRAVEYARD_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_GOSSIP_STONE_FAIRY)); + locationTable[RC_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, TWO_ACTOR_PARAMS(0x1000, -75), "Gossip Stone Big Fairy", RHT_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_HC_MALON_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_HC_MALON_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS( 0, 3445), "Malon Gossip Stone Fairy", RHT_HC_MALON_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_MALON_GOSSIP_STONE_FAIRY)); + locationTable[RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(0x1000, 3445), "Malon Gossip Stone Big Fairy", RHT_HC_MALON_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_MALON_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS( 0, 1041), "Rock Wall Gossip Stone Fairy", RHT_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_ROCK_WALL_GOSSIP_STONE_FAIRY)); + locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(0x1000, 1041), "Rock Wall Gossip Stone Big Fairy", RHT_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0xC, 735), "Storms Grotto Gossip Stone Fairy", RHT_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x100C, 735), "Storms Grotto Gossip Stone Big Fairy", RHT_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS( 0, -2230), "Deku Tree Left Gossip Stone Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY)); + locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(0x1000, -2230), "Deku Tree Left Gossip Stone Big Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS( 0, -700), "Deku Tree Right Gossip Stone Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY)); + locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(0x1000, -700), "Deku Tree Right Gossip Stone Big Fairy", RHT_KF_DEKU_TREE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_DEKU_TREE_RIGHT_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_KF_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_KF_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS( 0, -1223), "Gossip Stone Fairy", RHT_KF_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_GOSSIP_STONE_FAIRY)); + locationTable[RC_KF_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_KF_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(0x1000, -1223), "Gossip Stone Big Fairy", RHT_KF_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x1B, -236), "Storms Gossip Stone Fairy", RHT_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x101B, -236), "Storms Gossip Stone Big Fairy", RHT_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_LH_LAB_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_LH_LAB_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS( 0, 3212), "Lab Gossip Stone Fairy", RHT_LH_LAB_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_LAB_GOSSIP_STONE_FAIRY)); + locationTable[RC_LH_LAB_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_LH_LAB_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 3212), "Lab Gossip Stone Big Fairy", RHT_LH_LAB_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_LAB_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS( 0, 8395), "Southeast Gossip Stone Fairy", RHT_LH_SOUTHEAST_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHEAST_GOSSIP_STONE_FAIRY)); + locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 8395), "Southeast Gossip Stone Big Fairy", RHT_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS( 0, 7984), "Southwest Gossip Stone Fairy", RHT_LH_SOUTHWEST_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHWEST_GOSSIP_STONE_FAIRY)); + locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 7984), "Southwest Gossip Stone Big Fairy", RHT_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_LW_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_LW_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS( 0, 2300), "Gossip Stone Fairy", RHT_LW_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_GOSSIP_STONE_FAIRY)); + locationTable[RC_LW_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_LW_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS(0x1000, 2300), "Gossip Stone Big Fairy", RHT_LW_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS( 0, 1370), "Maze Lower Gossip Stone Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY)); + locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS(0x1000, 1370), "Maze Lower Gossip Stone Big Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS( 0, 740), "Maze Upper Gossip Stone Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY)); + locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS(0x1000, 740), "Maze Upper Gossip Stone Big Fairy", RHT_SFM_MAZE_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_SFM_SARIA_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_SFM_SARIA_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS( 0, -2300), "Saria Gossip Stone Fairy", RHT_SFM_SARIA_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_SARIA_GOSSIP_STONE_FAIRY)); + locationTable[RC_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, TWO_ACTOR_PARAMS(0x1000, -2300), "Saria Gossip Stone Big Fairy", RHT_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_ZD_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_ZD_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS( 0, -1600), "Gossip Stone Fairy", RHT_ZD_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_GOSSIP_STONE_FAIRY)); + locationTable[RC_ZD_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_ZD_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(0x1000, -1600), "Gossip Stone Big Fairy", RHT_ZD_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_ZF_FAIRY_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS( 0, 2205), "Fairy Gossip Stone Fairy", RHT_ZF_FAIRY_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_FAIRY_GOSSIP_STONE_FAIRY)); + locationTable[RC_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(0x1000, 2205), "Fairy Gossip Stone Big Fairy", RHT_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_ZF_JABU_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_ZF_JABU_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS( 0, -985), "Jabu Gossip Stone Fairy", RHT_ZF_JABU_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_JABU_GOSSIP_STONE_FAIRY)); + locationTable[RC_ZF_JABU_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_ZF_JABU_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(0x1000, -985), "Jabu Gossip Stone Big Fairy", RHT_ZF_JABU_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_JABU_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS( 0, -1070), "Near Grottos Gossip Stone Fairy", RHT_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY)); + locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(0x1000, -1070), "Near Grottos Gossip Stone Big Fairy", RHT_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS( 0, -1650), "Near Domain Gossip Stone Fairy", RHT_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY)); + locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(0x1000, -1650), "Near Domain Gossip Stone Big Fairy", RHT_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_DOMAIN_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x11, -357), "Cow Grotto Gossip Stone Fairy", RHT_HF_COW_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1011, -357), "Cow Grotto Gossip Stone Big Fairy", RHT_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x10, -236), "Near Market Gossip Stone Fairy", RHT_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1010, -236), "Near Market Gossip Stone Big Fairy", RHT_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x14, -236), "Southeast Gossip Stone Fairy", RHT_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1014, -236), "Southeast Gossip Stone Big Fairy", RHT_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x13, -236), "Open Grotto Gossip Stone Fairy", RHT_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1013, -236), "Open Grotto Gossip Stone Big Fairy", RHT_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0xA, -236), "Open Grotto Gossip Stone Fairy", RHT_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x100A, -236), "Open Grotto Gossip Stone Big Fairy", RHT_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x4, -236), "Open Grotto Gossip Stone Fairy", RHT_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1004, -236), "Open Grotto Gossip Stone Big Fairy", RHT_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x1A, -236), "Tunnel Grotto Gossip Stone Fairy", RHT_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x101A, -236), "Tunnel Grotto Gossip Stone Big Fairy", RHT_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x8, -236), "Storms Grotto Gossip Stone Fairy", RHT_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1008, -236), "Storms Grotto Gossip Stone Big Fairy", RHT_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG)); + locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY] = Location::StoneFairy(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, TWO_ACTOR_PARAMS( 0x6, -236), "Upper Grotto Gossip Stone Fairy", RHT_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY)); + locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG] = Location::StoneFairy(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1006, -236), "Upper Grotto Gossip Stone Big Fairy", RHT_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG)); - locationTable[RC_LH_ISLAND_SUN_FAIRY] = Location::Fairy(RC_LH_ISLAND_SUN_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 7319), "Island Sun's Song Fairy", RHT_LH_ISLAND_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_ISLAND_SUN_FAIRY)); - locationTable[RC_HF_POND_STORMS_FAIRY] = Location::Fairy(RC_HF_POND_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(0x1000, 5012), "Pond Song of Storms Fairy", RHT_HF_POND_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_POND_STORMS_FAIRY)); - locationTable[RC_HF_FENCE_GROTTO_STORMS_FAIRY] = Location::Fairy(RC_HF_FENCE_GROTTO_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, -308), "Deku Scrub Grotto Storms Fairy", RHT_HF_FENCE_GROTTO_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FENCE_GROTTO_STORMS_FAIRY)); - locationTable[RC_DMT_FLAG_SUN_FAIRY] = Location::Fairy(RC_DMT_FLAG_SUN_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, TWO_ACTOR_PARAMS(0x1000, 464), "Flag Sun's Song Fairy", RHT_DMT_FLAG_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_FLAG_SUN_FAIRY)); - locationTable[RC_DMT_COW_GROTTO_STORMS_FAIRY] = Location::Fairy(RC_DMT_COW_GROTTO_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, -311), "Cow Grotto Song of Storms Fairy", RHT_DMT_COW_GROTTO_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_COW_GROTTO_STORMS_FAIRY)); - locationTable[RC_LW_SHORTCUT_STORMS_FAIRY] = Location::Fairy(RC_LW_SHORTCUT_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS(0x1000, -795), "Shortcuts Song of Storms Fairy", RHT_LW_SHORTCUT_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_SHORTCUT_STORMS_FAIRY)); - locationTable[RC_TH_KITCHEN_SUN_FAIRY] = Location::Fairy(RC_TH_KITCHEN_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(0x1000, -621), "Kitchen Sun's Song Fairy", RHT_TH_KITCHEN_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_SUN_FAIRY)); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY] = Location::Fairy(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, 741), "Scrub Grotto Sun's Song Fairy", RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY)); - locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY] = Location::Fairy(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_ROYAL_FAMILYS_TOMB, TWO_ACTOR_PARAMS(0x1000, 1476), "Royal Family's Tomb Sun's Song Fairy", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY)); + locationTable[RC_LH_ISLAND_SUN_FAIRY] = Location::SongFairy(RC_LH_ISLAND_SUN_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(0x1000, 7319), "Island Sun's Song Fairy", RHT_LH_ISLAND_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_ISLAND_SUN_FAIRY)); + locationTable[RC_HF_POND_STORMS_FAIRY] = Location::SongFairy(RC_HF_POND_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(0x1000, 5012), "Pond Song of Storms Fairy", RHT_HF_POND_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_POND_STORMS_FAIRY)); + locationTable[RC_HF_FENCE_GROTTO_STORMS_FAIRY] = Location::SongFairy(RC_HF_FENCE_GROTTO_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, -308), "Deku Scrub Grotto Storms Fairy", RHT_HF_FENCE_GROTTO_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FENCE_GROTTO_STORMS_FAIRY)); + locationTable[RC_DMT_FLAG_SUN_FAIRY] = Location::SongFairy(RC_DMT_FLAG_SUN_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, TWO_ACTOR_PARAMS(0x1000, 464), "Flag Sun's Song Fairy", RHT_DMT_FLAG_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_FLAG_SUN_FAIRY)); + locationTable[RC_DMT_COW_GROTTO_STORMS_FAIRY] = Location::SongFairy(RC_DMT_COW_GROTTO_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, -311), "Cow Grotto Song of Storms Fairy", RHT_DMT_COW_GROTTO_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_COW_GROTTO_STORMS_FAIRY)); + locationTable[RC_LW_SHORTCUT_STORMS_FAIRY] = Location::SongFairy(RC_LW_SHORTCUT_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS(0x1000, -795), "Shortcuts Song of Storms Fairy", RHT_LW_SHORTCUT_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_SHORTCUT_STORMS_FAIRY)); + locationTable[RC_TH_KITCHEN_SUN_FAIRY] = Location::SongFairy(RC_TH_KITCHEN_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(0x1000, -621), "Kitchen Sun's Song Fairy", RHT_TH_KITCHEN_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_SUN_FAIRY)); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY] = Location::SongFairy(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, 741), "Deku Scrub Grotto Sun's Song Fairy", RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY)); + locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY] = Location::SongFairy(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_ROYAL_FAMILYS_TOMB, TWO_ACTOR_PARAMS(0x1000, 1476), "Royal Family's Tomb Sun's Song Fairy", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY)); - locationTable[RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY] = Location::Fairy(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1896), "After Boulder Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY)); - locationTable[RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY] = Location::Fairy(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -220), "Four Armos Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY)); - locationTable[RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY] = Location::Fairy(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, RCQUEST_VANILLA,RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 54), "Beamos Song of Storms Fairy", RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY)); - locationTable[RC_SHADOW_TEMPLE_PIT_STORM_FAIRY] = Location::Fairy(RC_SHADOW_TEMPLE_PIT_STORM_FAIRY, RCQUEST_VANILLA,RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 3339), "Pit Room Song of Storms Fairy", RHT_SHADOW_TEMPLE_PIT_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_PIT_STORM_FAIRY)); - locationTable[RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY] = Location::Fairy(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -127), "Wind Hint Sun's Song Fairy", RHT_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY)); - locationTable[RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY] = Location::Fairy(RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(0x1000, -1531), "Basement Sun's Song Fairy", RHT_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY)); - locationTable[RC_ICE_CAVERN_ENTRANCE_STORMS_FAIRY] = Location::Fairy(RC_ICE_CAVERN_ENTRANCE_STORMS_FAIRY, RCQUEST_VANILLA,RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(0x1000, 1186), "Entrance Song of Storms Fairy", RHT_ICE_CAVERN_ENTRANCE_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_ENTRANCE_STORMS_FAIRY)); - locationTable[RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY] = Location::Fairy(RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, RCQUEST_VANILLA,RCAREA_GERUDO_TRAINING_GROUND,SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(0x1000, -445), "Entrance Song of Storms Fairy", RHT_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY)); - locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY] = Location::Fairy(RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(0x1000, 587), "Spirit Trial Beamos Sun's Song Fairy", RHT_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY)); + locationTable[RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY] = Location::SongFairy(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1896), "After Boulder Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY)); + locationTable[RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY] = Location::SongFairy(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -220), "Four Armos Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY)); + locationTable[RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY] = Location::SongFairy(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, RCQUEST_VANILLA,RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 54), "Beamos Song of Storms Fairy", RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY)); + locationTable[RC_SHADOW_TEMPLE_PIT_STORM_FAIRY] = Location::SongFairy(RC_SHADOW_TEMPLE_PIT_STORM_FAIRY, RCQUEST_VANILLA,RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 3339), "Pit Room Song of Storms Fairy", RHT_SHADOW_TEMPLE_PIT_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_PIT_STORM_FAIRY)); + locationTable[RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY] = Location::SongFairy(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -127), "Wind Hint Sun's Song Fairy", RHT_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY)); + locationTable[RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY] = Location::SongFairy(RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(0x1000, -1531), "Basement Sun's Song Fairy", RHT_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY)); + locationTable[RC_ICE_CAVERN_ENTRANCE_STORMS_FAIRY] = Location::SongFairy(RC_ICE_CAVERN_ENTRANCE_STORMS_FAIRY, RCQUEST_VANILLA,RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(0x1000, 1186), "Entrance Song of Storms Fairy", RHT_ICE_CAVERN_ENTRANCE_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_ENTRANCE_STORMS_FAIRY)); + locationTable[RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY] = Location::SongFairy(RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, RCQUEST_VANILLA,RCAREA_GERUDO_TRAINING_GROUND,SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(0x1000, -445), "Entrance Song of Storms Fairy", RHT_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY)); + locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY] = Location::SongFairy(RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_GANONS_CASTLE, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(0x1000, 587), "Spirit Trial Beamos Sun's Song Fairy", RHT_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY)); - locationTable[RC_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY] = Location::Fairy(RC_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -551), "MQ Lower Loop Stalfos Room Sun's Song Fairy", RHT_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY)); - locationTable[RC_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY] = Location::Fairy(RC_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1563), "MQ Lower Loop Behind Iron Knuckle Sun's Song Fairy", RHT_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY)); - locationTable[RC_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY] = Location::Fairy(RC_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -540), "MQ Before Dark Link Pilar Sun's Song Fairy", RHT_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY)); - locationTable[RC_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY] = Location::Fairy(RC_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1501), "MQ Before Dark Link Left Song of Storms Fairy", RHT_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY)); - locationTable[RC_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY] = Location::Fairy(RC_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1504), "MQ Before Dark Link Right Sun's Song Fairy", RHT_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY)); - locationTable[RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY] = Location::Fairy(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -220), "MQ Dinalfos Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY)); - locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY] = Location::Fairy(RC_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 55), "MQ Beamos Song of Storms Fairy", RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY)); - locationTable[RC_SHADOW_TEMPLE_MQ_PIT_STORM_FAIRY] = Location::Fairy(RC_SHADOW_TEMPLE_MQ_PIT_STORM_FAIRY, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 3342), "MQ Pit Room Song of Storms Fairy", RHT_SHADOW_TEMPLE_PIT_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_MQ_PIT_STORM_FAIRY)); - locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY] = Location::Fairy(RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -127), "MQ Wind Hint Sun's Song Fairy", RHT_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY)); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY] = Location::Fairy(RC_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(0x1000, -437), "MQ East Cell Sun's Song Fairy", RHT_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY)); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY] = Location::Fairy(RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(0x1000, -1458), "MQ Basement Sun's Song Fairy", RHT_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY)); + locationTable[RC_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY] = Location::SongFairy(RC_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -551), "MQ Lower Loop Stalfos Room Sun's Song Fairy", RHT_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY)); + locationTable[RC_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY] = Location::SongFairy(RC_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1563), "MQ Lower Loop Behind Iron Knuckle Sun's Song Fairy", RHT_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY)); + locationTable[RC_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY] = Location::SongFairy(RC_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -540), "MQ Before Dark Link Pilar Sun's Song Fairy", RHT_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY)); + locationTable[RC_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY] = Location::SongFairy(RC_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1501), "MQ Before Dark Link Left Song of Storms Fairy", RHT_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY)); + locationTable[RC_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY] = Location::SongFairy(RC_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1504), "MQ Before Dark Link Right Sun's Song Fairy", RHT_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY)); + locationTable[RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY] = Location::SongFairy(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -220), "MQ Dinalfos Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY)); + locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY] = Location::SongFairy(RC_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 55), "MQ Beamos Song of Storms Fairy", RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY)); + locationTable[RC_SHADOW_TEMPLE_MQ_PIT_STORM_FAIRY] = Location::SongFairy(RC_SHADOW_TEMPLE_MQ_PIT_STORM_FAIRY, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 3342), "MQ Pit Room Song of Storms Fairy", RHT_SHADOW_TEMPLE_PIT_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_MQ_PIT_STORM_FAIRY)); + locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY] = Location::SongFairy(RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -127), "MQ Wind Hint Sun's Song Fairy", RHT_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY)); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY] = Location::SongFairy(RC_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(0x1000, -437), "MQ East Cell Sun's Song Fairy", RHT_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY)); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY] = Location::SongFairy(RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(0x1000, -1458), "MQ Basement Sun's Song Fairy", RHT_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY)); // clang-format on } static ObjectExtension::Register RegisterFairyIdentity; static RegisterShipInitFunc registerShuffleFairies(RegisterShuffleFairies, { "IS_RANDO" }); -static RegisterShipInitFunc registerShuffleFairiesLocations(Rando::StaticData::RegisterFairyLocations); +static RegisterShipInitFunc registerFairyLocations(Rando::StaticData::RegisterFairyLocations); diff --git a/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp b/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp index 7291fdbef..dac291196 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp @@ -287,4 +287,4 @@ void Rando::StaticData::RegisterFreestandingLocations() { } static RegisterShipInitFunc registerShuffleFreestanding(RegisterShuffleFreestanding, { "IS_RANDO" }); -static RegisterShipInitFunc registerShuffleFreestandingLocations(Rando::StaticData::RegisterFreestandingLocations); +static RegisterShipInitFunc registerFreestandingLocations(Rando::StaticData::RegisterFreestandingLocations); diff --git a/soh/soh/Enhancements/randomizer/ShuffleGrass.cpp b/soh/soh/Enhancements/randomizer/ShuffleGrass.cpp index 27d42a148..d82c3b393 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleGrass.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleGrass.cpp @@ -15,11 +15,10 @@ extern PlayState* gPlayState; extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); void DrawTypeOfGrass(EnKusa* grassActor, Gfx* bushDList, Gfx* grassDList, PlayState* play) { - // Actor params is -255 for regrowable grass. - if (grassActor->actor.params == -255) { - Gfx_DrawDListOpa(play, grassDList); - } else { + if ((grassActor->actor.params & 3) == 0) { Gfx_DrawDListOpa(play, bushDList); + } else { + Gfx_DrawDListOpa(play, grassDList); } } @@ -531,4 +530,4 @@ void Rando::StaticData::RegisterGrassLocations() { static ObjectExtension::Register RegisterGrassIdentity; static RegisterShipInitFunc registerShuffleGrass(RegisterShuffleGrass, { "IS_RANDO" }); -static RegisterShipInitFunc registerShuffleGrassLocations(Rando::StaticData::RegisterGrassLocations); +static RegisterShipInitFunc registerGrassLocations(Rando::StaticData::RegisterGrassLocations); diff --git a/soh/soh/Enhancements/randomizer/ShufflePots.cpp b/soh/soh/Enhancements/randomizer/ShufflePots.cpp index 869af92e4..815562578 100644 --- a/soh/soh/Enhancements/randomizer/ShufflePots.cpp +++ b/soh/soh/Enhancements/randomizer/ShufflePots.cpp @@ -661,4 +661,4 @@ void Rando::StaticData::RegisterPotLocations() { static ObjectExtension::Register RegisterPotIdentity; static RegisterShipInitFunc registerShufflePots(RegisterShufflePots, { "IS_RANDO" }); -static RegisterShipInitFunc registerShufflePotLocations(Rando::StaticData::RegisterPotLocations); +static RegisterShipInitFunc registerPotLocations(Rando::StaticData::RegisterPotLocations); diff --git a/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp b/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp new file mode 100644 index 000000000..14cb9c7b1 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp @@ -0,0 +1,265 @@ +#include +#include "soh_assets.h" +#include "static_data.h" +#include "soh/ObjectExtension/ObjectExtension.h" + +extern "C" { +#include "variables.h" +#include "src/overlays/actors/ovl_En_Wood02/z_en_wood02.h" +#include "objects/object_wood02/object_wood02.h" +#include "soh/Enhancements/enhancementTypes.h" +extern PlayState* gPlayState; +void EnWood02_Draw(Actor*, PlayState*); +} + +static Gfx* D_80B3BF54[] = { + (Gfx*)object_wood02_DL_0078D0, (Gfx*)object_wood02_DL_007CA0, (Gfx*)object_wood02_DL_0080D0, + (Gfx*)object_wood02_DL_000090, (Gfx*)object_wood02_DL_000340, (Gfx*)object_wood02_DL_000340, + (Gfx*)object_wood02_DL_000700, +}; + +static Gfx* D_80B3BF70[] = { + (Gfx*)object_wood02_DL_007968, + (Gfx*)object_wood02_DL_007D38, + (Gfx*)object_wood02_DL_0081A8, + NULL, + NULL, + NULL, + (Gfx*)object_wood02_DL_007AD0, + (Gfx*)object_wood02_DL_007E20, + (Gfx*)object_wood02_DL_008350, + (Gfx*)object_wood02_DL_000160, + (Gfx*)object_wood02_DL_000440, + (Gfx*)object_wood02_DL_000700, +}; + +extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); + +uint8_t EnWood02_RandomizerHoldsItem(EnWood02* treeActor, PlayState* play) { + const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); + if (treeIdentity == nullptr) { + return false; + } + + // Don't pull randomized item if tree isn't randomized or is already checked + return IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get() && + !Flags_GetRandomizerInf(treeIdentity->randomizerInf) && treeIdentity->randomizerCheck != RC_UNKNOWN_CHECK; +} + +extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) { + GetItemCategory getItemCategory; + GetItemEntry smallCrateItem; + auto treeActor = (EnWood02*)thisx; + int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); + int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); + + int isVanilla = + csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)); + + const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); + if (treeIdentity == nullptr) { + return; + } + + if (isVanilla || treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { + getItemCategory = ITEM_CATEGORY_JUNK; + } else { + smallCrateItem = Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); + getItemCategory = smallCrateItem.getItemCategory; + + // If they have bombchus, don't consider the bombchu item major + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU && + ((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) || + (smallCrateItem.modIndex == MOD_NONE && + (smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 || + smallCrateItem.getItemId == GI_BOMBCHUS_20)))) { + getItemCategory = ITEM_CATEGORY_JUNK; + // If it's a bottle and they already have one, consider the item lesser + } else if ((smallCrateItem.modIndex == MOD_RANDOMIZER && + smallCrateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION && + smallCrateItem.getItemId <= RG_BOTTLE_WITH_POE) || + (smallCrateItem.modIndex == MOD_NONE && + (smallCrateItem.getItemId == GI_BOTTLE || smallCrateItem.getItemId == GI_MILK_BOTTLE))) { + if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) { + getItemCategory = ITEM_CATEGORY_LESSER; + } + } + } + + GraphicsContext* gfxCtx = play->state.gfxCtx; + OPEN_DISPS(gfxCtx); + Matrix_Push(); + + // Change texture + switch (getItemCategory) { + case ITEM_CATEGORY_MAJOR: + Matrix_Scale(0.1, 0.05, 0.1, MTXMODE_APPLY); + Gfx_DrawDListOpa(play, (Gfx*)gSmallMajorCrateDL); + break; + case ITEM_CATEGORY_SKULLTULA_TOKEN: + Matrix_Scale(0.1, 0.05, 0.1, MTXMODE_APPLY); + Gfx_DrawDListOpa(play, (Gfx*)gSmallTokenCrateDL); + break; + case ITEM_CATEGORY_SMALL_KEY: + Matrix_Scale(0.1, 0.05, 0.1, MTXMODE_APPLY); + Gfx_DrawDListOpa(play, (Gfx*)gSmallSmallKeyCrateDL); + break; + case ITEM_CATEGORY_BOSS_KEY: + Matrix_Scale(0.1, 0.05, 0.1, MTXMODE_APPLY); + Gfx_DrawDListOpa(play, (Gfx*)gSmallBossKeyCrateDL); + break; + case ITEM_CATEGORY_LESSER: + Matrix_Scale(0.1, 0.05, 0.1, MTXMODE_APPLY); + switch (smallCrateItem.itemId) { + case ITEM_HEART_PIECE: + case ITEM_HEART_PIECE_2: + case ITEM_HEART_CONTAINER: + Gfx_DrawDListOpa(play, (Gfx*)gSmallHeartCrateDL); + break; + default: + Gfx_DrawDListOpa(play, (Gfx*)gSmallMinorCrateDL); + break; + } + case ITEM_CATEGORY_JUNK: + default: + Matrix_Scale(0.04, 0.02, 0.04, MTXMODE_APPLY); + Gfx_DrawDListOpa(play, (Gfx*)gLargeJunkCrateDL); + break; + } + + Matrix_Pop(); + CLOSE_DISPS(gfxCtx); +} + +void EnWood02_RandomizerSpawnCollectible(EnWood02* treeActor, PlayState* play) { + const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); + if (treeIdentity == nullptr) { + return; + } + + EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &treeActor->actor.world.pos, ITEM00_SOH_DUMMY); + item00->randoInf = treeIdentity->randomizerInf; + item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + item00->actor.velocity.y = 0.0f; + item00->actor.world.pos.y += 120.0f; + item00->actor.speedXZ = 2.0f; + item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f); + // clear randomizerCheck to prevent multiple bonks, + // reloading area without collecting drop won't persist this + treeIdentity->randomizerCheck = RC_UNKNOWN_CHECK; +} + +void EnWood02_RandomizerInit(void* actorRef) { + EnWood02* treeActor = static_cast(actorRef); + if (treeActor->actor.params <= WOOD_TREE_KAKARIKO_ADULT) { + auto treeIdentity = OTRGlobals::Instance->gRandomizer->IdentifyTree( + gPlayState->sceneNum, (s16)treeActor->actor.world.pos.x, (s16)treeActor->actor.world.pos.z); + ObjectExtension::GetInstance().Set(actorRef, std::move(treeIdentity)); + } +} + +void RegisterShuffleTrees() { + bool shouldRegister = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get(); + + COND_ID_HOOK(OnActorInit, ACTOR_EN_WOOD02, shouldRegister, EnWood02_RandomizerInit); + + COND_VB_SHOULD(VB_TREE_SETUP_DRAW, shouldRegister, { + EnWood02* treeActor = va_arg(args, EnWood02*); + if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { + EnWood02_RandomizerDraw(&treeActor->actor, gPlayState); + } + }); + + COND_VB_SHOULD(VB_TREE_DROP_ITEM, shouldRegister, { + EnWood02* treeActor = va_arg(args, EnWood02*); + if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { + EnWood02_RandomizerSpawnCollectible(treeActor, gPlayState); + // QoL, drop golden skulltula alongside item + if ((treeActor->unk_14C < 0 || treeActor->unk_14C >= 0x64) && treeActor->actor.home.rot.z != 0) { + Vec3f dropsSpawnPt = treeActor->actor.world.pos; + dropsSpawnPt.y += 200.0f; + treeActor->actor.home.rot.z &= 0x1FFF; + treeActor->actor.home.rot.z |= 0xE000; + Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_SW, dropsSpawnPt.x, dropsSpawnPt.y, + dropsSpawnPt.z, 0, treeActor->actor.world.rot.y, 0, treeActor->actor.home.rot.z, true); + treeActor->actor.home.rot.z = 0; + } + *should = false; + } + }); +} + +void Rando::StaticData::RegisterTreeLocations() { + // clang-format off + // Trees + // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check + locationTable[RC_MARKET_TREE] = Location::Tree(RC_MARKET_TREE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_DAY, TWO_ACTOR_PARAMS(-100, 240), "Tree in Hyrule Market", RHT_TREE_MARKET, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREE)); + locationTable[RC_HC_NEAR_GUARDS_TREE_1] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1209, 2242), "Tree Near Guards 1", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_1)); + locationTable[RC_HC_NEAR_GUARDS_TREE_2] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(943, 2051), "Tree Near Guards 2", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_2)); + locationTable[RC_HC_NEAR_GUARDS_TREE_3] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(827, 1428), "Tree Near Guards 3", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_3)); + locationTable[RC_HC_NEAR_GUARDS_TREE_4] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(421, 1397), "Tree Near Guards 4", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_4)); + locationTable[RC_HC_NEAR_GUARDS_TREE_5] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-73, 1459), "Tree Near Guards 5", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_5)); + locationTable[RC_HC_NEAR_GUARDS_TREE_6] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1494, 2108), "Tree Near Guards 6", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_6)); + locationTable[RC_HC_SKULLTULA_TREE] = Location::Tree(RC_HC_SKULLTULA_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-145, 2961), "HC GS Tree", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_SKULLTULA_TREE)); + locationTable[RC_HC_GROTTO_TREE] = Location::Tree(RC_HC_GROTTO_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(924, 872), "Tree Near Storms Grotto", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_GROTTO_TREE)); + locationTable[RC_HC_NL_TREE_1] = Location::NLTree(RC_HC_NL_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-331, 1438), "NL Tree Near Guards 1", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NL_TREE_1)); + locationTable[RC_HC_NL_TREE_2] = Location::NLTree(RC_HC_NL_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1022, 1444), "NL Tree Near Guards 2", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NL_TREE_2)); + locationTable[RC_HF_NEAR_KAK_TREE] = Location::Tree(RC_HF_NEAR_KAK_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3276, 971), "Tree Outside Kakariko", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_KAK_TREE)); + locationTable[RC_HF_NEAR_KAK_SMALL_TREE] = Location::Tree(RC_HF_NEAR_KAK_SMALL_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2076, -91), "Small Tree Outside Kakariko", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_KAK_SMALL_TREE)); + locationTable[RC_HF_NEAR_MARKET_TREE_1] = Location::Tree(RC_HF_NEAR_MARKET_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1041, 1022), "Tree Near HC Entrance Grotto 1", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_MARKET_TREE_1)); + locationTable[RC_HF_NEAR_MARKET_TREE_2] = Location::Tree(RC_HF_NEAR_MARKET_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1244, 819), "Tree Near HC Entrance Grotto 2", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_MARKET_TREE_2)); + locationTable[RC_HF_NEAR_MARKET_TREE_3] = Location::Tree(RC_HF_NEAR_MARKET_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1448, 620), "Tree Near HC Entrance Grotto 3", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_MARKET_TREE_3)); + locationTable[RC_HF_NEAR_LLR_TREE] = Location::Tree(RC_HF_NEAR_LLR_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1907, 5409), "Tree Outside Lon Lon Ranch", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_LLR_TREE)); + locationTable[RC_HF_NEAR_LH_TREE] = Location::Tree(RC_HF_NEAR_LH_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4377, 13662), "Tree Outside Lake Hylia", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_LH_TREE)); + locationTable[RC_HF_CHILD_NEAR_GV_TREE] = Location::Tree(RC_HF_CHILD_NEAR_GV_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6270, 8579), "Child Near Gerudo Valley Tree", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NEAR_GV_TREE)); + locationTable[RC_HF_ADULT_NEAR_GV_TREE] = Location::Tree(RC_HF_ADULT_NEAR_GV_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6241, 7097), "Adult Near Gerudo Valley Tree", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_ADULT_NEAR_GV_TREE)); + locationTable[RC_HF_NEAR_ZR_TREE] = Location::Tree(RC_HF_NEAR_ZR_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3117, 4239), "Tree Outside Zora's River", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_ZR_TREE)); + locationTable[RC_HF_NORTHWEST_TREE_1] = Location::Tree(RC_HF_NORTHWEST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4777, 136), "Tree in Northwest 1", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_1)); + locationTable[RC_HF_NORTHWEST_TREE_2] = Location::Tree(RC_HF_NORTHWEST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4188, 263), "Tree in Northwest 2", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_2)); + locationTable[RC_HF_NORTHWEST_TREE_3] = Location::Tree(RC_HF_NORTHWEST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5000, -147), "Tree in Northwest 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_3)); + locationTable[RC_HF_NORTHWEST_TREE_4] = Location::Tree(RC_HF_NORTHWEST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4463, -182), "Tree in Northwest 4", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_4)); + locationTable[RC_HF_NORTHWEST_TREE_5] = Location::Tree(RC_HF_NORTHWEST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5262, 398), "Tree in Northwest 5", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_5)); + locationTable[RC_HF_NORTHWEST_TREE_6] = Location::Tree(RC_HF_NORTHWEST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4391, 891), "Tree in Northwest 6", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_6)); + locationTable[RC_HF_EAST_TREE_1] = Location::Tree(RC_HF_EAST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3817, 7119), "Tree in East 1", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_1)); + locationTable[RC_HF_EAST_TREE_2] = Location::Tree(RC_HF_EAST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(4365, 7182), "Tree in East 2", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_2)); + locationTable[RC_HF_EAST_TREE_3] = Location::Tree(RC_HF_EAST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3837, 7479), "Tree in East 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_3)); + locationTable[RC_HF_EAST_TREE_4] = Location::Tree(RC_HF_EAST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3377, 7201), "Tree in East 4", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_4)); + locationTable[RC_HF_EAST_TREE_5] = Location::Tree(RC_HF_EAST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3408, 6676), "Tree in East 5", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_5)); + locationTable[RC_HF_EAST_TREE_6] = Location::Tree(RC_HF_EAST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3935, 6279), "Tree in East 6", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_6)); + locationTable[RC_HF_SOUTHEAST_TREE_1] = Location::Tree(RC_HF_SOUTHEAST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(915, 12557), "Tree in Southeast 1", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_1)); + locationTable[RC_HF_SOUTHEAST_TREE_2] = Location::Tree(RC_HF_SOUTHEAST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(350, 11605), "Tree in Southeast 2", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_2)); + locationTable[RC_HF_SOUTHEAST_TREE_3] = Location::Tree(RC_HF_SOUTHEAST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(470, 12494), "Tree in Southeast 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_3)); + locationTable[RC_HF_SOUTHEAST_TREE_4] = Location::Tree(RC_HF_SOUTHEAST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(614, 12357), "Tree in Southeast 4", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_4)); + locationTable[RC_HF_SOUTHEAST_TREE_5] = Location::Tree(RC_HF_SOUTHEAST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1114, 12156), "Tree in Southeast 5", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_5)); + locationTable[RC_HF_SOUTHEAST_TREE_6] = Location::Tree(RC_HF_SOUTHEAST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(549, 11204), "Tree in Southeast 6", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_6)); + locationTable[RC_HF_SOUTHEAST_TREE_7] = Location::Tree(RC_HF_SOUTHEAST_TREE_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(49, 11405), "Tree in Southeast 7", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_7)); + locationTable[RC_HF_SOUTHEAST_TREE_8] = Location::Tree(RC_HF_SOUTHEAST_TREE_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-29, 12005), "Tree in Southeast 8", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_8)); + locationTable[RC_HF_SOUTHEAST_TREE_9] = Location::Tree(RC_HF_SOUTHEAST_TREE_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1514,13157), "Tree in Southeast 9", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_9)); + locationTable[RC_HF_SOUTHEAST_TREE_10] = Location::Tree(RC_HF_SOUTHEAST_TREE_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-509,12954), "Tree in Southeast 10", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_10)); + locationTable[RC_HF_SOUTHEAST_TREE_11] = Location::Tree(RC_HF_SOUTHEAST_TREE_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-430,12354), "Tree in Southeast 11", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_11)); + locationTable[RC_HF_SOUTHEAST_TREE_12] = Location::Tree(RC_HF_SOUTHEAST_TREE_12, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(69,12153), "Tree in Southeast 12", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_12)); + locationTable[RC_HF_SOUTHEAST_TREE_13] = Location::Tree(RC_HF_SOUTHEAST_TREE_13, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-129,12554), "Tree in Southeast 13", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_13)); + locationTable[RC_HF_SOUTHEAST_TREE_14] = Location::Tree(RC_HF_SOUTHEAST_TREE_14, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(950,11545), "Tree in Southeast 14", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_14)); + locationTable[RC_HF_SOUTHEAST_TREE_15] = Location::Tree(RC_HF_SOUTHEAST_TREE_15, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(949,12205), "Tree in Southeast 15", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_15)); + locationTable[RC_HF_SOUTHEAST_TREE_16] = Location::Tree(RC_HF_SOUTHEAST_TREE_16, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(469,13154), "Tree in Southeast 16", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_16)); + locationTable[RC_HF_SOUTHEAST_TREE_17] = Location::Tree(RC_HF_SOUTHEAST_TREE_17, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(535,12957), "Tree in Southeast 17", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_17)); + locationTable[RC_HF_SOUTHEAST_TREE_18] = Location::Tree(RC_HF_SOUTHEAST_TREE_18, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1515,12497), "Tree in Southeast 18", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_18)); + locationTable[RC_HF_SOUTHEAST_TREE_19] = Location::Tree(RC_HF_SOUTHEAST_TREE_19, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-786,11293), "Tree in Southeast 19", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_19)); + locationTable[RC_HF_CHILD_SOUTHEAST_TREE_1] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1535, 11943), "Child Tree in Southeast Corner 1", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_1)); + locationTable[RC_HF_CHILD_SOUTHEAST_TREE_2] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2135,11883), "Child Tree in Southeast Corner 2", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_2)); + locationTable[RC_HF_CHILD_SOUTHEAST_TREE_3] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2134,12543), "Child Tree in Southeast Corner 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_3)); + locationTable[RC_HF_CHILD_SOUTHEAST_TREE_4] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1734,11542), "Child Tree in Southeast Corner 4", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_4)); + locationTable[RC_HF_CHILD_SOUTHEAST_TREE_5] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1234,11743), "Child Tree in Southeast Corner 5", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_5)); + locationTable[RC_HF_CHILD_SOUTHEAST_TREE_6] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1155,12343), "Child Tree in Southeast Corner 6", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_6)); + locationTable[RC_HF_TEKTITE_GROTTO_TREE] = Location::Tree(RC_HF_TEKTITE_GROTTO_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4976, 2812), "Tektite Grotto Tree", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_TEKTITE_GROTTO_TREE)); + locationTable[RC_ZF_TREE] = Location::Tree(RC_ZF_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(186, 2222), "Tree in Zora's Fountain", RHT_TREE_ZORAS_FOUNTAIN, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_TREE)); + locationTable[RC_ZR_TREE] = Location::Tree(RC_ZR_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(-1690, 554), "Tree in Zoras River", RHT_TREE_ZORAS_RIVER, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_TREE)); + locationTable[RC_KAK_TREE] = Location::Tree(RC_KAK_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-860, 522), "Kakariko GS Tree", RHT_TREE_KAKARIKO, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_TREE)); + locationTable[RC_LLR_TREE] = Location::Tree(RC_LLR_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(1309, -2241), "Lon Lon Ranch GS Tree", RHT_TREE_LON_LON_RANCH, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TREE)); + // clang-format on +} + +static ObjectExtension::Register RegisterPotIdentity; +static RegisterShipInitFunc registerShuffleTrees(RegisterShuffleTrees, { "IS_RANDO" }); +static RegisterShipInitFunc registerTreeLocations(Rando::StaticData::RegisterTreeLocations); diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index c4ce6c326..5c9e2f0ba 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -54,7 +54,10 @@ Context::Context() { &mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES], &mOptions[RSK_SHUFFLE_ADULT_TRADE], &mOptions[RSK_SHUFFLE_100_GS_REWARD], - &mOptions[RSK_SHUFFLE_FAIRIES], + &mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES], + &mOptions[RSK_SHUFFLE_STONE_FAIRIES], + &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], + &mOptions[RSK_SHUFFLE_SONG_FAIRIES], &mOptions[RSK_GOSSIP_STONE_HINTS], }; } @@ -126,8 +129,7 @@ void Context::PlaceItemInLocation(const RandomizerCheck locKey, const Randomizer SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetEnglish() + " placed at " + StaticData::GetLocation(locKey)->GetName() + "\n"); - if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS) || - mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) { + if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS)) { StaticData::RetrieveItem(item).ApplyEffect(); } @@ -163,12 +165,16 @@ bool Context::IsQuestOfLocationActive(RandomizerCheck rc) { void Context::GenerateLocationPool() { allLocations.clear(); + overworldLocations.clear(); + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { + dungeon->locations.clear(); + } for (Location& location : StaticData::GetLocationTable()) { // skip RCs that shouldn't be in the pool for any reason (i.e. settings, unsupported check type, etc.) // TODO: Exclude checks for some of the older shuffles from the pool too i.e. Frog Songs, Scrubs, etc.) if (location.GetRandomizerCheck() == RC_UNKNOWN_CHECK || location.GetRandomizerCheck() == RC_TRIFORCE_COMPLETED || // already in pool - (location.GetRandomizerCheck() == RC_MASTER_SWORD_PEDESTAL && + (location.GetRandomizerCheck() == RC_TOT_MASTER_SWORD && mOptions[RSK_SHUFFLE_MASTER_SWORD].Is(RO_GENERIC_OFF)) || (location.GetRandomizerCheck() == RC_KAK_100_GOLD_SKULLTULA_REWARD && mOptions[RSK_SHUFFLE_100_GS_REWARD].Is(RO_GENERIC_OFF)) || @@ -191,9 +197,15 @@ void Context::GenerateLocationPool() { (location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OFF)) || (location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) || (location.GetRCType() == RCTYPE_NLCRATE && (mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF) || - !mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC))) || + mOptions[RSK_LOGIC_RULES].IsNot(RO_LOGIC_NO_LOGIC))) || (location.GetRCType() == RCTYPE_SMALL_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) || - (location.GetRCType() == RCTYPE_FAIRY && !mOptions[RSK_SHUFFLE_FAIRIES]) || + (location.GetRCType() == RCTYPE_FOUNTAIN_FAIRY && !mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES]) || + (location.GetRCType() == RCTYPE_STONE_FAIRY && !mOptions[RSK_SHUFFLE_STONE_FAIRIES]) || + (location.GetRCType() == RCTYPE_BEAN_FAIRY && !mOptions[RSK_SHUFFLE_BEAN_FAIRIES]) || + (location.GetRCType() == RCTYPE_SONG_FAIRY && !mOptions[RSK_SHUFFLE_SONG_FAIRIES]) || + (location.GetRCType() == RCTYPE_TREE && !mOptions[RSK_SHUFFLE_TREES]) || + (location.GetRCType() == RCTYPE_NLTREE && + (!mOptions[RSK_SHUFFLE_TREES] || mOptions[RSK_LOGIC_RULES].IsNot(RO_LOGIC_NO_LOGIC))) || (location.GetRCType() == RCTYPE_FREESTANDING && mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OFF)) || (location.GetRCType() == RCTYPE_BEEHIVE && !mOptions[RSK_SHUFFLE_BEEHIVES])) { diff --git a/soh/soh/Enhancements/randomizer/fishsanity.cpp b/soh/soh/Enhancements/randomizer/fishsanity.cpp index e34799156..83d326384 100644 --- a/soh/soh/Enhancements/randomizer/fishsanity.cpp +++ b/soh/soh/Enhancements/randomizer/fishsanity.cpp @@ -5,7 +5,7 @@ #include "variables.h" #include "functions.h" #include "macros.h" -#include +#include extern "C" { #include "src/overlays/actors/ovl_Fishing/z_fishing.h" diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index a20935378..c58273adb 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1,4 +1,4 @@ -#include +#include #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/enhancementTypes.h" @@ -49,6 +49,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Ds/z_en_ds.h" #include "src/overlays/actors/ovl_En_Gm/z_en_gm.h" #include "src/overlays/actors/ovl_En_Js/z_en_js.h" +#include "src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.h" #include "src/overlays/actors/ovl_En_Door/z_en_door.h" #include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h" #include "src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.h" @@ -413,8 +414,10 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { getItemEntry.modIndex == MOD_RANDOMIZER) && (getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK || getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN || - getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER))))) { - + 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))))))) { Item_DropCollectible(gPlayState, &spawnPos, static_cast(ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000)); isGiSkipped = 1; @@ -960,7 +963,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should = !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) && LINK_IS_ADULT && gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_KAKARIKO_VILLAGE && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && - CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER); + CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) && gSaveContext.cutsceneIndex < 0xFFF0; break; case VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD: { // Don't require a bomb bag to get prize in rando @@ -976,7 +979,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l break; } case VB_GIVE_ITEM_MASTER_SWORD: - if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD)) { + if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD) || RAND_GET_OPTION(RSK_STARTING_MASTER_SWORD)) { *should = false; } else { *should = true; @@ -1111,20 +1114,59 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l } if (item00->itemEntry.modIndex == MOD_NONE) { + std::string message; + + switch (gSaveContext.language) { + case LANGUAGE_FRA: + message = "Vous obtenez: "; + break; + case LANGUAGE_GER: + message = "Du erhältst: "; + break; + case LANGUAGE_ENG: + default: + message = "You found "; + break; + } + Notification::Emit({ .itemIcon = GetTextureForItemId(item00->itemEntry.itemId), - .message = "You found ", + .message = message, .suffix = SohUtils::GetItemName(item00->itemEntry.itemId), }); } else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) { + std::string message; + std::string itemName; + if (!(item00->itemEntry.getItemId == RG_ARCHIPELAGO_ITEM_PROGRESSIVE || item00->itemEntry.getItemId == RG_ARCHIPELAGO_ITEM_USEFUL || item00->itemEntry.getItemId == RG_ARCHIPELAGO_ITEM_JUNK)) { + + switch (gSaveContext.language) { + case LANGUAGE_FRA: + message = "Vous obtenez: "; + itemName = Rando::StaticData::RetrieveItem((RandomizerGet)item00->itemEntry.getItemId) + .GetName() + .french; + break; + case LANGUAGE_GER: + message = "Du erhältst: "; + itemName = Rando::StaticData::RetrieveItem((RandomizerGet)item00->itemEntry.getItemId) + .GetName() + .german; + break; + case LANGUAGE_ENG: + default: + message = "You found "; + itemName = Rando::StaticData::RetrieveItem((RandomizerGet)item00->itemEntry.getItemId) + .GetName() + .english; + break; + } + Notification::Emit({ - .message = "You found ", - .suffix = Rando::StaticData::RetrieveItem((RandomizerGet)item00->itemEntry.getItemId) - .GetName() - .english, + .message = message, + .suffix = itemName, }); } } @@ -1184,7 +1226,8 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l break; } case VB_SELL_POES_TO_POE_COLLECTOR: { - if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES) && HIGH_SCORE(HS_POE_POINTS) >= 1000) { + if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES) && HIGH_SCORE(HS_POE_POINTS) >= 1000 && + !(GET_PLAYER(gPlayState)->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS)) { EnGb* enGb = va_arg(args, EnGb*); enGb->textId = 0x70F8; Message_ContinueTextbox(gPlayState, enGb->textId); @@ -1421,6 +1464,30 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should |= RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF; break; } + case VB_OKARINA_TAG_COMPLETE: { + if (gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL) { + auto dungeon = + OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + if (dungeon->IsVanilla()) { + EnOkarinaTag* enOkarinaTag = va_arg(args, EnOkarinaTag*); + if (enOkarinaTag->switchFlag >= 0 && Flags_GetSwitch(gPlayState, enOkarinaTag->switchFlag)) { + Flags_UnsetSwitch(gPlayState, enOkarinaTag->switchFlag); + *should = false; + } + } + } + break; + } + case VB_OKARINA_TAG_COMPLETED: { + if (gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL) { + auto dungeon = + OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + if (dungeon->IsVanilla()) { + *should = false; + } + } + break; + } case VB_GRANNY_SAY_INSUFFICIENT_RUPEES: { if (EnDs_RandoCanGetGrannyItem()) { *should = gSaveContext.rupees < @@ -1537,7 +1604,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l break; } case VB_GERUDO_GUARD_SET_ACTION_AFTER_TALK: - if (gPlayState->msgCtx.choiceIndex == 0) { + if (gPlayState->msgCtx.choiceIndex == 0 && gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS) { EnGe2* enGe2 = va_arg(args, EnGe2*); EnGe2_SetupCapturePlayer(enGe2, gPlayState); *should = false; @@ -1806,6 +1873,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l case VB_GIVE_ITEM_WATER_MEDALLION: case VB_GIVE_ITEM_SPIRIT_MEDALLION: case VB_GIVE_ITEM_SHADOW_MEDALLION: + case VB_CHEST_USE_ICE_EFFECT: *should = false; break; case VB_GIVE_ITEM_SKULL_TOKEN: @@ -2207,6 +2275,15 @@ void RandomizerOnActorInitHandler(void* actorRef) { return; } + // Turn MQ switch into toggle + if (actor->id == ACTOR_OBJ_SWITCH && gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL && (actor->params & 7) == 3) { + auto dungeon = + OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + if (dungeon->IsMQ()) { + actor->params |= 0x10; + } + } + // In ER, once Link has spawned we know the scene has loaded, so we can sanitize the last known entrance type if (actor->id == ACTOR_PLAYER && RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES)) { Grotto_SanitizeEntranceType(); diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 71f9fff38..5207b9734 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -52,7 +52,7 @@ void Item::ApplyEffect() const { if (!logic->CalculatingAvailableChecks) { logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true); } - logic->SetInLogic(logicVal, true); + logic->Set(logicVal, true); } void Item::UndoEffect() const { @@ -61,7 +61,7 @@ void Item::UndoEffect() const { if (!logic->CalculatingAvailableChecks) { logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false); } - logic->SetInLogic(logicVal, false); + logic->Set(logicVal, false); } const Text& Item::GetName() const { diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 685c572dc..c08b6a1e4 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -35,10 +35,10 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuer-Pfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eis-Pfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Licht-Pfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuer-Pfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eis-Pfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Licht-Pfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Paß" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, LOGIC_DOUBLE_DEFENSE, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); @@ -48,10 +48,10 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, LOGIC_ZELDAS_LETTER, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Ei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Henni" }, ITEMTYPE_ITEM, GI_COJIRO, true, LOGIC_COJIRO, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Schimmelpilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champignon Suspect", "Schimmelpilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Modertrank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "zerbr. Goronen-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Zerbr. Goronen-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Rezept" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Glotzfrosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Augentropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); @@ -64,7 +64,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Bombentasche (prog.)" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, ITEM_CATEGORY_MAJOR, true); itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Bogen (prog.)" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, ITEM_CATEGORY_MAJOR, true); itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Schleuder (prog.)" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, ITEM_CATEGORY_MAJOR, true); - itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Geldbörse (prog.)" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Börse (prog.)" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, ITEM_CATEGORY_MAJOR, true); itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Zora-Schuppe (prog.)" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, ITEM_CATEGORY_MAJOR, true); itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Nuß-Kapazität (prog.)" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, ITEM_CATEGORY_MAJOR, true); itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Stab-Kapazität (prog.)" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, ITEM_CATEGORY_MAJOR, true); @@ -363,7 +363,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "Magie Infinie", "Unendliche Magische Kraft" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "Missiles Teigneux Infinis", "Unendliche Krabbelminentasche" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BOMBCHU_INF].SetCustomDrawFunc(Randomizer_DrawBombchuBag); - itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "Bourse Infinie", "Unendliche Geldbörse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "Bourse Infinie", "Unendliche Börse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "Clé Squelette", "Skelettschlüssel" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); @@ -393,10 +393,10 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Titanhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_GOLDEN, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Große Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesengeldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Goldene Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Petite Bourse", "Kindergeldbörse" }, ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Große Börse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesenbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Goldene Börse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Petite Bourse", "Kinderbörse" }, ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku-Nuß-Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku-Nuß-Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku-Stab-Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index 6c27e3aef..847ee9aa9 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -567,6 +567,24 @@ Rando::Location Rando::Location::SmallCrate(RandomizerCheck rc, RandomizerCheckQ false, collectionCheck }; } +Rando::Location Rando::Location::Tree(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_TREE, area_, ACTOR_EN_WOOD02, + scene_, actorParams_, std::move(shortName_), hintKey, vanillaItem, + false, collectionCheck }; +} + +Rando::Location Rando::Location::NLTree(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_NLTREE, area_, ACTOR_EN_WOOD02, + scene_, actorParams_, std::move(shortName_), hintKey, vanillaItem, + false, collectionCheck }; +} + Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_) { return { rc, quest_, RCTYPE_GOSSIP_STONE, area_, ACTOR_EN_GS, @@ -574,11 +592,37 @@ Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQu false }; } -Rando::Location Rando::Location::Fairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, - SceneID scene_, int32_t actorParams_, std::string&& shortName_, - RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck) { - return { rc, quest_, RCTYPE_FAIRY, area_, ACTOR_EN_ELF, scene_, actorParams_, std::move(shortName_), - hintKey, RG_NONE, false, collectionCheck }; +Rando::Location Rando::Location::FountainFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, + RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, + std::string&& shortName_, RandomizerHintTextKey hintKey, + SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_FOUNTAIN_FAIRY, area_, ACTOR_EN_ELF, + scene_, actorParams_, std::move(shortName_), hintKey, RG_NONE, + false, collectionCheck }; +} + +Rando::Location Rando::Location::StoneFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_STONE_FAIRY, area_, ACTOR_EN_ELF, + scene_, actorParams_, std::move(shortName_), hintKey, RG_NONE, + false, collectionCheck }; +} + +Rando::Location Rando::Location::BeanFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_BEAN_FAIRY, area_, ACTOR_EN_ELF, + scene_, actorParams_, std::move(shortName_), hintKey, RG_NONE, + false, collectionCheck }; +} + +Rando::Location Rando::Location::SongFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_SONG_FAIRY, area_, ACTOR_EN_ELF, + scene_, actorParams_, std::move(shortName_), hintKey, RG_NONE, + false, collectionCheck }; } Rando::Location Rando::Location::Grass(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index f99499652..f118bdcda 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -246,6 +246,14 @@ class Location { RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + static Location Tree(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, + int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + + static Location NLTree(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, + int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, ActorID actorId_, SceneID scene_, std::string&& shortName_, std::string&& spoilerName_); @@ -255,9 +263,21 @@ class Location { static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, ActorID actorId_, SceneID scene_, std::string&& shortName_); - static Location Fairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, - int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, - SpoilerCollectionCheck collectionCheck); + static Location FountainFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck); + + static Location StoneFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck); + + static Location BeanFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck); + + static Location SongFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck); static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, SceneID scene_, int32_t actorParams_, std::string&& shortName_); diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index cb5668b01..0f517aa3f 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -106,7 +106,8 @@ bool LocationAccess::CanBuy(bool calculatingAvailableChecks) const { const auto& loc = Rando::StaticData::GetLocation(location); const auto& itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(location); - if (loc->GetRCType() == RCTYPE_SHOP || loc->GetRCType() == RCTYPE_SCRUB || loc->GetRCType() == RCTYPE_MERCHANT) { + if (loc->GetRCType() == RCTYPE_SHOP || loc->GetRCType() == RCTYPE_SCRUB || loc->GetRCType() == RCTYPE_MERCHANT || + location == RC_ZR_MAGIC_BEAN_SALESMAN) { // Checks should only be identified while playing if (calculatingAvailableChecks && itemLoc->GetCheckStatus() != RCSHOW_IDENTIFIED) { return CanBuyAnother(GetMinimumPrice(loc)); @@ -617,7 +618,7 @@ void Region::ResetVariables() { bool Region::MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge) { // if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if // adult is here it's also Certain Access - if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) { + if (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7)) { if (anyAge) { return Here(condition); } @@ -627,10 +628,9 @@ bool Region::MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAg } else if (Adult() && logic->IsAdult) { return condition(); // if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and - // meet the adult universe's access condition We only need to do it as child, as only child access matters + // meet the adult universe's access condition. We only need to do it as child, as only child access matters // for this check, as adult access is assumed based on keys - } else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) { - bool result = false; + } else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6))) { // store current age variables bool pastAdult = logic->IsAdult; bool pastChild = logic->IsChild; @@ -638,7 +638,7 @@ bool Region::MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAg // First check if the check is possible as child logic->IsChild = true; logic->IsAdult = false; - result = condition(); + bool result = condition(); // If so, check again as adult. both have to be true for result to be true if (result) { logic->IsChild = false; @@ -763,10 +763,6 @@ bool AdultCanAccess(const RandomizerRegion region) { return areaTable[region].Adult(); } -bool HasAccessTo(const RandomizerRegion region) { - return areaTable[region].HasAccess(); -} - Rando::Context* ctx; std::shared_ptr logic; @@ -775,10 +771,10 @@ void RegionTable_Init() { ctx = Context::GetInstance().get(); logic = ctx->GetLogic(); // RANDOTODO do not hardcode, instead allow accepting a Logic class somehow grottoEvents = { - EventAccess(&logic->GossipStoneFairy, [] { return logic->CallGossipFairy(); }), - EventAccess(&logic->ButterflyFairy, [] { return logic->CanUse(RG_STICKS); }), - EventAccess(&logic->BugShrub, [] { return logic->CanCutShrubs(); }), - EventAccess(&logic->LoneFish, [] { return true; }), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, [] { return logic->CallGossipFairy(); }), + EventAccess(LOGIC_BUTTERFLY_FAIRY, [] { return logic->CanUse(RG_STICKS); }), + EventAccess(LOGIC_BUG_SHRUB, [] { return logic->CanCutShrubs(); }), + EventAccess(LOGIC_LONE_FISH, [] { return true; }), }; // Clear the array from any previous playthrough attempts. This is important so that // locations which appear in both MQ and Vanilla dungeons don't get set in both areas. @@ -787,12 +783,13 @@ void RegionTable_Init() { // clang-format off areaTable[RR_ROOT] = Region("Root", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, { //Events - EventAccess(&logic->KakarikoVillageGateOpen, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}), - EventAccess(&logic->THCouldFree1TorchCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE);}), - EventAccess(&logic->THCouldFreeDoubleCellCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}), - EventAccess(&logic->TH_CouldFreeDeadEndCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}), - EventAccess(&logic->THCouldRescueSlopeCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}), - EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE);}),EventAccess(&logic->FreedEpona, []{return (bool)ctx->GetOption(RSK_SKIP_EPONA_RACE);}), + EventAccess(LOGIC_KAKARIKO_GATE_OPEN, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}), + EventAccess(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE);}), + EventAccess(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}), + EventAccess(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}), + EventAccess(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}), + EventAccess(LOGIC_TH_RESCUED_ALL_CARPENTERS, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE);}), + EventAccess(LOGIC_FREED_EPONA, []{return (bool)ctx->GetOption(RSK_SKIP_EPONA_RACE);}), }, { //Locations LOCATION(RC_LINKS_POCKET, true), @@ -897,7 +894,7 @@ void RegionTable_Init() { RegionTable_Init_GanonsCastle(); // Set parent regions - for (uint32_t i = RR_ROOT; i <= RR_GANONS_CASTLE; i++) { + for (uint32_t i = RR_ROOT; i < RR_MAX; i++) { for (LocationAccess& locPair : areaTable[i].locations) { RandomizerCheck location = locPair.GetLocation(); Rando::Context::GetInstance()->GetItemLocation(location)->SetParentRegion((RandomizerRegion)i); diff --git a/soh/soh/Enhancements/randomizer/location_access.h b/soh/soh/Enhancements/randomizer/location_access.h index 5cbc84060..d55928eea 100644 --- a/soh/soh/Enhancements/randomizer/location_access.h +++ b/soh/soh/Enhancements/randomizer/location_access.h @@ -22,7 +22,7 @@ class Region; class EventAccess { public: - explicit EventAccess(bool* event_, ConditionFn condition_function_) + explicit EventAccess(LogicVal event_, ConditionFn condition_function_) : event(event_), condition_function(condition_function_) { } @@ -37,15 +37,15 @@ class EventAccess { bool CheckConditionAtAgeTime(bool& age, bool& time); void EventOccurred() { - *event = true; + logic->Set(event, true); } bool GetEvent() const { - return *event; + return logic->Get(event); } private: - bool* event; + LogicVal event; ConditionFn condition_function; }; @@ -231,7 +231,6 @@ bool CanPlantBean(const RandomizerRegion region); bool BothAges(const RandomizerRegion region); bool ChildCanAccess(const RandomizerRegion region); bool AdultCanAccess(const RandomizerRegion region); -bool HasAccessTo(const RandomizerRegion region); namespace Regions { extern void AccessReset(); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index 001ad5d81..46a89f7af 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -19,25 +19,25 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_PERIMETER] = Region("Bottom of the Well Perimeter", SCENE_BOTTOM_OF_THE_WELL, { //Events - EventAccess(&logic->StickPot, []{return true;}), - EventAccess(&logic->NutPot, []{return true;}), - EventAccess(&logic->LoweredWaterInsideBotw, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_STICK_POT, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), + EventAccess(LOGIC_BOTW_LOWERED_WATER, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->LoweredWaterInsideBotw || logic->CanOpenUnderwaterChest()), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_2, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_POT, (logic->CanBreakPots() && logic->LoweredWaterInsideBotw) || logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_POT, (logic->CanBreakPots() && logic->Get(LOGIC_BOTW_LOWERED_WATER)) || logic->CanUse(RG_BOOMERANG)), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), - Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), - Entrance(RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM, []{return logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE);}), - Entrance(RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, []{return logic->LoweredWaterInsideBotw && logic->IsChild;}), + Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, []{return logic->IsChild && logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 3);}), + Entrance(RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM, []{return logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE);}), + Entrance(RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, []{return logic->Get(LOGIC_BOTW_LOWERED_WATER) && logic->IsChild;}), //Falling down into basement requires nothing, but falling down somewhere specific requires lens or lens trick //kinda questionable given several drops are blocked by rocks, but that's how it was handled before and on N64 Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return true;}), @@ -56,7 +56,7 @@ void RegionTable_Init_BottomOfTheWell() { }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), - Entrance(RR_BOTTOM_OF_THE_WELL_INNER_ROOMS, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), + Entrance(RR_BOTTOM_OF_THE_WELL_INNER_ROOMS, []{return logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 3);}), Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return true;}), Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), }); @@ -79,7 +79,7 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_POT_1, logic->CanBreakPots() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}), + Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->IsChild && logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 3) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}), Entrance(RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), //not sure if this lens check is needed, these holes are a bit too easy to find, but it matches existing logic Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), @@ -97,15 +97,15 @@ void RegionTable_Init_BottomOfTheWell() { //If the player can voidwarp into one of these rooms they will need splitting up, and Fake walls will need specifying into middle and the rest moved to perimeter areaTable[RR_BOTTOM_OF_THE_WELL_INNER_ROOMS] = Region("Bottom of the Well Inner Rooms", SCENE_BOTTOM_OF_THE_WELL, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), + Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, []{return logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 3);}), }); areaTable[RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM] = Region("Bottom of the Well Coffin Room", SCENE_BOTTOM_OF_THE_WELL, {}, { @@ -115,7 +115,7 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE);}), + Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE);}), }); areaTable[RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM] = Region("Bottom of the Well Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { @@ -192,11 +192,11 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER] = Region("Bottom of the Well MQ Perimeter", SCENE_BOTTOM_OF_THE_WELL, { //Events //technically obsolete due to a wonder item fairy which only needs a projectile, but we don't have an event var for it yet - EventAccess(&logic->FairyPot, []{return Here(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets();}), + EventAccess(LOGIC_FAIRY_POT, []{return Here(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets();}), //It is possible to hit the water switch with a pot from RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, however the hitbox for making it activate is very unintuitive //You have to throw the pot from further back to hit the switch from the front instead of the top, trying to hit the "fingers" directly //This unintuitiveness means it should be a trick. ZL is needed to get a clear path to carry the pot - EventAccess(&logic->LoweredWaterInsideBotw, []{return logic->CanJumpslash() || logic->CanUseProjectile();}), + EventAccess(LOGIC_BOTW_LOWERED_WATER, []{return logic->CanJumpslash() || logic->CanUseProjectile();}), }, { //Locations //Implies CanBreakPots() @@ -207,16 +207,16 @@ void RegionTable_Init_BottomOfTheWell() { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild;}), Entrance(RR_BOTTOM_OF_THE_WELL_MQ_WEST_ROOM_SWITCH, []{return Here(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2) && logic->CanUseProjectile();}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM, []{return logic->IsChild && logic->LoweredWaterInsideBotw;}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM, []{return (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE)) && logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 2);}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE, []{return logic->IsChild && logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 2) && logic->CanUseProjectile();}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM, []{return logic->IsChild && logic->Get(LOGIC_BOTW_LOWERED_WATER);}), Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}), }); areaTable[RR_BOTTOM_OF_THE_WELL_MQ_WEST_ROOM_SWITCH] = Region("Bottom of the Well MQ West Room Switch", SCENE_BOTTOM_OF_THE_WELL, { //Events - EventAccess(&logic->OpenedWestRoomMQBotw, []{return true;}), + EventAccess(LOGIC_BOTW_MQ_OPENED_WEST_ROOM, []{return true;}), }, {}, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash() && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || ctx->GetTrickOption(RT_BOTW_MQ_PITS));}), @@ -231,15 +231,15 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_MIDDLE_LEFT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE)) && logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 2);}), }); areaTable[RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE] = Region("Bottom of the Well MQ Locked Cage", SCENE_BOTTOM_OF_THE_WELL, { //Events - EventAccess(&logic->OpenedMiddleHoleMQBotw, []{return logic->HasExplosives();}), + EventAccess(LOGIC_BOTW_MQ_OPENED_MIDDLE_HOLE, []{return logic->HasExplosives();}), }, {}, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->IsChild && logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 2);}), }); areaTable[RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM] = Region("Bottom of the Well MQ Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { @@ -268,7 +268,7 @@ void RegionTable_Init_BottomOfTheWell() { //Also you get cheap shotted on entry sometimes. //An MQ lens trick is recommended here, and a review of this room for OHKO logic what that is added is advised. //In the meantime I assume damage taken or the easy answer (nuts) - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, logic->OpenedWestRoomMQBotw && (logic->TakeDamage() || logic->CanUse(RG_NUTS)) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, logic->Get(LOGIC_BOTW_MQ_OPENED_WEST_ROOM) && (logic->TakeDamage() || logic->CanUse(RG_NUTS)) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_2, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_3, logic->CanBreakPots()), @@ -279,7 +279,7 @@ void RegionTable_Init_BottomOfTheWell() { }, { //Exits //If a relevant trick causes you to be able to warp into here without going through PERIMETER, a new eventAccess will be needed for lowering the gates with ZL - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SWITCH_PLATFORM, []{return logic->OpenedMiddleHoleMQBotw;}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SWITCH_PLATFORM, []{return logic->Get(LOGIC_BOTW_MQ_OPENED_MIDDLE_HOLE);}), Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp index 1d98e861a..caa46d9c7 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -18,8 +18,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_LOBBY] = Region("Deku Tree Lobby", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_DEKU_TREE_MAP_CHEST, true), @@ -61,8 +61,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_COMPASS_ROOM] = Region("Deku Tree Compass Room", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_DEKU_TREE_COMPASS_CHEST, true), @@ -78,8 +78,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_BASEMENT_LOWER] = Region("Deku Tree Basement Lower", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, true), @@ -91,7 +91,7 @@ void RegionTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_LOBBY, []{return true;}), Entrance(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return Here(RR_DEKU_TREE_BASEMENT_LOWER, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}), - Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return logic->IsAdult || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || HasAccessTo(RR_DEKU_TREE_BASEMENT_UPPER);}), + Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return logic->IsAdult || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK);}), Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return false;}), }); @@ -125,8 +125,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_BASEMENT_TORCH_ROOM] = Region("Deku Tree Basement Torch Room", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_DEKU_TREE_BASEMENT_TORCHES_GRASS_1, logic->CanCutShrubs()), @@ -139,8 +139,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_BASEMENT_BACK_LOBBY] = Region("Deku Tree Basement Back Lobby", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Location LOCATION(RC_DEKU_TREE_BASEMENT_LARVAE_GRASS_1, logic->CanCutShrubs()), @@ -162,8 +162,9 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_BASEMENT_UPPER] = Region("Deku Tree Basement Upper", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK, []{return true;}), }, {}, { //Exits Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return true;}), @@ -191,8 +192,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_1F] = Region("Deku Tree MQ 1F", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanKillEnemy(RE_WITHERED_DEKU_BABA);}), - EventAccess(&logic->BrokeDeku1FWeb, []{return logic->HasFireSource();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanKillEnemy(RE_WITHERED_DEKU_BABA);}), + EventAccess(LOGIC_DEKU_TREE_1F_BROKE_WEB, []{return logic->HasFireSource();}), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_LOBBY_GRASS_1, logic->CanCutShrubs()), @@ -208,7 +209,7 @@ void RegionTable_Init_DekuTree() { //Swim is not required because you can jump with enough momentum to hit land. //You even avoid fall damage if you hit the shallow water, though it's obscure knowledge so may be a trick //if it is, then we need a landing room with (IsAdult || HasItem(RG_BRONZE_SCALE) || TakeDamage() || that trick) to reach basement - Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->BrokeDeku1FWeb;}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->Get(LOGIC_DEKU_TREE_1F_BROKE_WEB);}), //is it possible to recoil from here to the ledge with a trick? }); @@ -230,9 +231,9 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_3F] = Region("Deku Tree MQ 3F", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), - EventAccess(&logic->BrokeDeku1FWeb, []{return true;}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_TREE_1F_BROKE_WEB, []{return true;}), }, { //Locations //Implies CanKillEnemy(RE_GOHMA_LARVA) @@ -293,8 +294,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT] = Region("Deku Tree MQ Basement", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), @@ -307,14 +308,14 @@ void RegionTable_Init_DekuTree() { Entrance(RR_DEKU_TREE_MQ_1F, []{return true;}), Entrance(RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM, []{return Here(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->CanHitEyeTargets();});}), //includes RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM Access, other fire sources clear directly from there - Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, []{return Here(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->CanHitEyeTargets();}) && logic->ClearedMQDekuSERoom && Here(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->CanUse(RG_STICKS);});}), - Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->PushedDekuBasementBlock || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, []{return Here(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->CanHitEyeTargets();}) && logic->Get(LOGIC_DEKU_TREE_MQ_CLEARED_SE_ROOM) && Here(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->CanUse(RG_STICKS);});}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->IsAdult || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->CanUse(RG_HOVER_BOOTS);}), }); areaTable[RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM] = Region("Deku Tree MQ Southeast Room", SCENE_DEKU_TREE, { //Events //Implies CanKillEnemy(RE_GOHMA_LARVA) - EventAccess(&logic->ClearedMQDekuSERoom, []{return logic->CanKillEnemy(RE_MAD_SCRUB);}), + EventAccess(LOGIC_DEKU_TREE_MQ_CLEARED_SE_ROOM, []{return logic->CanKillEnemy(RE_MAD_SCRUB);}), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_BASEMENT_TORCHES_GRASS_1, logic->CanCutShrubs()), @@ -324,13 +325,13 @@ void RegionTable_Init_DekuTree() { }, { //Exits Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, []{return logic->HasFireSource();}), - Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->ClearedMQDekuSERoom;}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->Get(LOGIC_DEKU_TREE_MQ_CLEARED_SE_ROOM);}), }); areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT] = Region("Deku Tree MQ Basement Water Room Front", SCENE_DEKU_TREE, { //Events //It's possible to get this with bow if you have move while in first person and one-point skips on, noticeably harder and jankier as child, but that's a trick - EventAccess(&logic->MQDekuWaterRoomTorches, []{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_STICKS) && (ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield())));}), + EventAccess(LOGIC_DEKU_TREE_MQ_WATER_ROOM_TORCHES, []{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_STICKS) && (ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield())));}), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, true), @@ -345,8 +346,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK] = Region("Deku Tree MQ Basement Water Room Back", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanKillEnemy(RE_WITHERED_DEKU_BABA);}), - EventAccess(&logic->MQDekuWaterRoomTorches, []{return logic->HasFireSource();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanKillEnemy(RE_WITHERED_DEKU_BABA);}), + EventAccess(LOGIC_DEKU_TREE_MQ_WATER_ROOM_TORCHES, []{return logic->HasFireSource();}), }, { //Locations //it blocks the chest while stunned unless you stun it from afar while it's slightly off the ground @@ -355,7 +356,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_BACK_GRASS_2, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, []{return logic->MQDekuWaterRoomTorches && logic->CanPassEnemy(RE_BIG_SKULLTULA, logic->CanUse(RG_SONG_OF_TIME) ? ED_CLOSE : ED_SHORT_JUMPSLASH);}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, []{return logic->Get(LOGIC_DEKU_TREE_MQ_WATER_ROOM_TORCHES) && logic->CanPassEnemy(RE_BIG_SKULLTULA, logic->CanUse(RG_SONG_OF_TIME) ? ED_CLOSE : ED_SHORT_JUMPSLASH);}), Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, []{return ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield()) || logic->CanUse(RG_LONGSHOT) || logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)));}), }); @@ -372,8 +373,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM] = Region("Deku Tree MQ Basement Grave Room", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}) + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}) }, { //Locations LOCATION(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG))), @@ -403,7 +404,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_LEDGE] = Region("Deku Tree MQ Basement Ledge", SCENE_DEKU_TREE, { //Events - EventAccess(&logic->PushedDekuBasementBlock, []{return true;}), + EventAccess(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK, []{return true;}), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku()), @@ -416,7 +417,7 @@ void RegionTable_Init_DekuTree() { Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return true;}), //If strength 0 is shuffled, add hovers or block push to the stick check //recoiling to skip swim is possible, but would be a trick - Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return Here(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->HasFireSource() || (/*logic->PushedDekuBasementBlock && */logic->CanUse(RG_STICKS));}) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}), + Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return Here(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->HasFireSource() || (/*logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) && */logic->CanUse(RG_STICKS));}) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}), }); areaTable[RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM] = Region("Deku Tree MQ Outside Boss Room", SCENE_DEKU_TREE, {}, { @@ -449,11 +450,11 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_BOSS_ROOM] = Region("Deku Tree Boss Room", SCENE_DEKU_TREE_BOSS, { // Events - EventAccess(&logic->DekuTreeClear, []{return logic->CanKillEnemy(RE_GOHMA);}), + EventAccess(LOGIC_DEKU_TREE_CLEAR, []{return logic->CanKillEnemy(RE_GOHMA);}), }, { // Locations - LOCATION(RC_QUEEN_GOHMA, logic->DekuTreeClear), - LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_HEART, logic->DekuTreeClear), + LOCATION(RC_QUEEN_GOHMA, logic->Get(LOGIC_DEKU_TREE_CLEAR)), + LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_HEART, logic->Get(LOGIC_DEKU_TREE_CLEAR)), LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_GRASS_3, logic->CanCutShrubs()), @@ -465,7 +466,7 @@ void RegionTable_Init_DekuTree() { }, { // Exits Entrance(RR_DEKU_TREE_BOSS_EXIT, []{return true;}), - Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return logic->DekuTreeClear;}, false), + Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return logic->Get(LOGIC_DEKU_TREE_CLEAR);}, false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp index d8e64f996..c21a7a33e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -24,10 +24,10 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_LOBBY] = Region("Dodongos Cavern Lobby", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->GossipStoneFairy, []{return (Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls();}) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CallGossipFairy();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return (Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls();}) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CallGossipFairy();}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})), + LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);), LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);}) && logic->CallGossipFairy()), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);}) && logic->CanUse(RG_SONG_OF_STORMS)), @@ -35,15 +35,18 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits Entrance(RR_DODONGOS_CAVERN_BEGINNING, []{return true;}), - Entrance(RR_DODONGOS_CAVERN_LOBBY_SWITCH, []{return logic->IsAdult;}), + Entrance(RR_DODONGOS_CAVERN_LOBBY_SWITCH, []{return logic->IsAdult || logic->CanGroundJump(true);}), Entrance(RR_DODONGOS_CAVERN_SE_CORRIDOR, []{return Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}), - Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return HasAccessTo(RR_DODONGOS_CAVERN_LOBBY_SWITCH);}), - Entrance(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return HasAccessTo(RR_DODONGOS_CAVERN_FAR_BRIDGE);}), - Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, []{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->HasExplosives();});}), + Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return logic->Get(LOGIC_DC_STAIRS_ROOM_DOOR);}), + Entrance(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->Get(LOGIC_DC_LIFT_PLATFORM);}), + Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, []{return logic->Get(LOGIC_DC_EYES_LIT);}), Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return false;}), }); - areaTable[RR_DODONGOS_CAVERN_LOBBY_SWITCH] = Region("Dodongos Cavern Lobby Switch", SCENE_DODONGOS_CAVERN, {}, {}, { + areaTable[RR_DODONGOS_CAVERN_LOBBY_SWITCH] = Region("Dodongos Cavern Lobby Switch", SCENE_DODONGOS_CAVERN, { + //Events + EventAccess(LOGIC_DC_STAIRS_ROOM_DOOR, []{return true;}), + }, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, []{return true;}), @@ -80,7 +83,10 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return true;}), }); - areaTable[RR_DODONGOS_CAVERN_LOWER_LIZALFOS] = Region("Dodongos Cavern Lower Lizalfos", SCENE_DODONGOS_CAVERN, {}, { + areaTable[RR_DODONGOS_CAVERN_LOWER_LIZALFOS] = Region("Dodongos Cavern Lower Lizalfos", SCENE_DODONGOS_CAVERN, { + //Events + EventAccess(LOGIC_DC_KILLED_LOWER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS, ED_CLOSE, true, 2);}), + }, { //Locations LOCATION(RC_DODONGOS_CAVERN_LIZALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_LIZALFOS_POT_2, logic->CanBreakPots()), @@ -89,8 +95,8 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_LOWER_LIZALFOS_HEART, true), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, []{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS, ED_CLOSE, true, 2);});}), - Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, []{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS, ED_CLOSE, true, 2);});}), + Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, []{return logic->Get(LOGIC_DC_KILLED_LOWER_LIZALFOS);}), + Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, []{return logic->Get(LOGIC_DC_KILLED_LOWER_LIZALFOS);}), }); areaTable[RR_DODONGOS_CAVERN_DODONGO_ROOM] = Region("Dodongos Cavern Dodongo Room", SCENE_DODONGOS_CAVERN, {}, { @@ -114,7 +120,10 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, []{return true;}), }); - areaTable[RR_DODONGOS_CAVERN_STAIRS_LOWER] = Region("Dodongos Cavern Stairs Lower", SCENE_DODONGOS_CAVERN, {}, {}, { + areaTable[RR_DODONGOS_CAVERN_STAIRS_LOWER] = Region("Dodongos Cavern Stairs Lower", SCENE_DODONGOS_CAVERN, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, ctx->GetTrickOption(RT_DC_VINES_GS) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT)), + }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, []{return logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DC_STAIRS_WITH_BOW) && logic->CanUse(RG_FAIRY_BOW));}), @@ -123,8 +132,8 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_STAIRS_UPPER] = Region("Dodongos Cavern Stairs Upper", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->HookshotOrBoomerang();}) || logic->CanUse(RG_LONGSHOT)), - LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, logic->IsAdult || logic->CanAttack() || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && logic->CanUse(RG_LONGSHOT) && ctx->GetTrickOption(RT_DC_VINES_GS))), + LOCATION(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, logic->Get(LOGIC_DC_LIFT_PLATFORM) ? ED_BOOMERANG : ED_LONGSHOT)), + LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, logic->IsAdult || logic->CanAttack()), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_3, logic->CanBreakPots()), @@ -160,7 +169,7 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_ARMOS_ROOM, []{return true;}), Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, []{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->CanBreakMudWalls() || (ctx->GetTrickOption(RT_DC_SCRUB_ROOM) && logic->HasItem(RG_GORONS_BRACELET));});}), Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, []{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}), - Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, []{return (logic->IsAdult && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), + Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, []{return (logic->IsAdult && (ctx->GetTrickOption(RT_DC_JUMP) || logic->CanGroundJump())) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), }); areaTable[RR_DODONGOS_CAVERN_2F_SIDE_ROOM] = Region("Dodongos Cavern 2F Side Room", SCENE_DODONGOS_CAVERN, {}, { @@ -180,7 +189,7 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return true;}), - Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP);}), + Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP) || (logic->IsAdult && logic->CanGroundJump());}), }); areaTable[RR_DODONGOS_CAVERN_UPPER_LIZALFOS] = Region("Dodongos Cavern Upper Lizalfos", SCENE_DODONGOS_CAVERN, {}, { @@ -188,11 +197,19 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_LOWER_LIZALFOS_HEART, true), LOCATION(RC_DODONGOS_CAVERN_UPPER_LIZALFOS_LEFT_HEART, true), LOCATION(RC_DODONGOS_CAVERN_UPPER_LIZALFOS_RIGHT_HEART, true), + //This room is in different states based on what entrance you entered by, + //So it's simpler to treat them as separate regions with shared checks in both + LOCATION(RC_DODONGOS_CAVERN_LIZALFOS_POT_1, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_LIZALFOS_POT_2, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_LIZALFOS_POT_3, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_LIZALFOS_POT_4, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_LOWER_LIZALFOS_HEART, true), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return true;}), - Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, []{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS, ED_CLOSE, true, 2);});}), - Entrance(RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, []{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS, ED_CLOSE, true, 2);});}), + Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, []{return Here(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS, ED_CLOSE, true, 2);});}), + Entrance(RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, []{return Here(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS, ED_CLOSE, true, 2);});}), + Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, []{return logic->Get(LOGIC_DC_KILLED_LOWER_LIZALFOS);}), + Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, []{return logic->Get(LOGIC_DC_KILLED_LOWER_LIZALFOS);}), }); areaTable[RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM] = Region("Dodongos Cavern Second Slingshot Room", SCENE_DODONGOS_CAVERN, {}, { @@ -217,9 +234,13 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return true;}), }); - areaTable[RR_DODONGOS_CAVERN_FAR_BRIDGE] = Region("Dodongos Cavern Far Bridge", SCENE_DODONGOS_CAVERN, {}, { + areaTable[RR_DODONGOS_CAVERN_FAR_BRIDGE] = Region("Dodongos Cavern Far Bridge", SCENE_DODONGOS_CAVERN, { + //Events + EventAccess(LOGIC_DC_EYES_LIT, []{return logic->HasExplosives();}), + EventAccess(LOGIC_DC_LIFT_PLATFORM, []{return true;}), + }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->CanBreakMudWalls();})), + LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, logic->CanBreakMudWalls()), }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), @@ -228,7 +249,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOSS_AREA] = Region("Dodongos Cavern Boss Region", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Location LOCATION(RC_DODONGOS_CAVERN_BEFORE_BOSS_GRASS, logic->CanCutShrubs()), @@ -273,13 +294,13 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}), Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}), Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls();}) || Here(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return logic->HasItem(RG_GORONS_BRACELET) && logic->TakeDamage();});}), //strength 1 and bunny speed works too - Entrance(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->IsAdult;}), - Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return Here(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return logic->HasExplosives() || (logic->ClearMQDCUpperLobbyRocks && logic->HasItem(RG_GORONS_BRACELET) && ((logic->IsAdult && ctx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (logic->IsChild && ctx->GetTrickOption(RT_DC_MQ_CHILD_EYES))));});}), + Entrance(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->IsAdult || logic->CanGroundJump(true);}), + Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return logic->Get(LOGIC_DC_EYES_LIT);}), }); areaTable[RR_DODONGOS_CAVERN_MQ_GOSSIP_STONE] = Region("Dodongos Cavern MQ Gossip Stone", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, true), @@ -292,11 +313,12 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE] = Region("Dodongos Cavern MQ Mouth Side Bridge", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->ClearMQDCUpperLobbyRocks, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), + EventAccess(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), + EventAccess(LOGIC_DC_EYES_LIT, []{return logic->HasExplosives() || (logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS) && logic->HasItem(RG_GORONS_BRACELET) && ((logic->IsAdult && ctx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (logic->IsChild && ctx->GetTrickOption(RT_DC_MQ_CHILD_EYES))));}), }, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return true;}), - Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return logic->ClearMQDCUpperLobbyRocks;}), + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS);}), //Bunny hood jump + jumpslash can also make it directly from the raising platform Entrance(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DC_MQ_CHILD_BOMBS) && logic->CanJumpslashExceptHammer() && logic->TakeDamage());}), //RANDOTODO is this possible with equip swapped hammer? //it is possible to use bunny hood speed, hovers and a jumpslash to go between here and the other bridge (included with TORCH_ROOM_LOWER), but this would be a trick @@ -304,7 +326,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER] = Region("Dodongos Cavern MQ Stairs Lower", SCENE_DODONGOS_CAVERN, { //Events - //EventAccess(&logic->CanClimbDCStairs, []{return logic->HasExplosives || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DC_STAIRS_WITH_BOW) && logic->CanUse(RG_FAIRY_BOW));}), + //EventAccess(LOGIC_DC_CAN_CLIMB_STAIRS, []{return logic->HasExplosives() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DC_STAIRS_WITH_BOW) && logic->CanUse(RG_FAIRY_BOW));}), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_1, logic->CanBreakPots()), @@ -323,8 +345,8 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_MUD_WALL] = Region("Dodongos Cavern MQ Stairs Past Mud Wall", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - //EventAccess(&logic->CanClimbDCStairs, []{return logic->HasItem(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + //EventAccess(LOGIC_DC_CAN_CLIMB_STAIRS, []{return logic->HasItem(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), @@ -353,7 +375,7 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return logic->TakeDamage();}), //If some case comes up where you can directly (void?)warp here without going through Dodongo room or climbing up from below, //the commented out logic is to handle going down and reclimbing to get silver rupees. A new eventVar will need decalring to handle this. - /*(logic->CanPassEnemy(RE_BIG_SKULLTULA) || CanUse(RG_HOVER_BOOTS)) && logic->CanClimbDCStairs;*/ + /*(logic->CanPassEnemy(RE_BIG_SKULLTULA) || CanUse(RG_HOVER_BOOTS)) && logic->Get(LOGIC_DC_CAN_CLIMB_STAIRS);*/ Entrance(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, []{return true;}),//if we add BONKO or other crate logic, logic for silver rupees goes here }); @@ -372,7 +394,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER] = Region("Dodongos Cavern MQ Torch Puzzle Lower", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->ClearMQDCUpperLobbyRocks, []{return (((logic->IsAdult /*or bunny hood jump*/) && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, []{return (((logic->IsAdult /*or bunny hood jump*/) && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_STICKS);}), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT, logic->CanUse(RG_BOOMERANG)), @@ -383,7 +405,8 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, []{return true;}), Entrance(RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM, []{return logic->HasFireSourceWithTorch();}),//torch checks here need strength 0 with sticks when that is implemented Entrance(RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM, []{return Here(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, []{return logic->HasFireSourceWithTorch();});}), //Includes an implied CanPass(RE_BIG_SKULLTULA) - Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return ((logic->IsAdult /*or bunny hood jump*/) && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), + //Bunny hood jump can make it as child + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return (logic->IsAdult && (ctx->GetTrickOption(RT_DC_JUMP) || logic->CanGroundJump())) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanUse(RG_STICKS) && logic->HasItem(RG_GORONS_BRACELET);}), //Implies access to RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM from here }); @@ -441,7 +464,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER] = Region("Dodongos Cavern MQ Torch Puzzle Upper", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->ClearMQDCUpperLobbyRocks, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, true), @@ -449,7 +472,7 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT, logic->CanBreakPots()), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return logic->ClearMQDCUpperLobbyRocks;}), + Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS);}), Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, []{return true;}), Entrance(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, []{return true;}), }); @@ -504,7 +527,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM] = Region("Dodongos Cavern Mad Scrub Room", SCENE_DODONGOS_CAVERN, {}, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG, true))), //Implies you can avoid/kill the enemies with what you use on the skull, if this assumption is broken, add - //&& (Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanKillEnemy(RE_FIRE_KEESE) && logic->CanKillEnemy(RE_MAD_SCRUB);}) || (logic->CanAvoidEnemy(RE_FIRE_KEESE) && logic->CanAvoidEnemy(RE_MAD_SCRUB))) + //&& (Here(RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM, []{return logic->CanKillEnemy(RE_FIRE_KEESE) && logic->CanKillEnemy(RE_MAD_SCRUB);}) || (logic->CanAvoidEnemy(RE_FIRE_KEESE) && logic->CanAvoidEnemy(RE_MAD_SCRUB))) LOCATION(RC_DODONGOS_CAVERN_MQ_SCRUB_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_MQ_SCRUB_GRASS_2, logic->CanCutShrubs()), }, { @@ -514,6 +537,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH] = Region("Dodongos Cavern MQ Behind Mouth", SCENE_DODONGOS_CAVERN, {}, { //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) /* || bunny jumps*/)), LOCATION(RC_DODONGOS_CAVERN_MQ_BEFORE_BOSS_SW_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BEFORE_BOSS_NE_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_SE_POT, logic->CanBreakPots()), @@ -527,9 +551,13 @@ void RegionTable_Init_DodongosCavern() { Entrance(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, []{return logic->IsAdult;}), }); - areaTable[RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE] = Region("Dodongos Cavern MQ Back Behind Fire", SCENE_DODONGOS_CAVERN, {}, { + areaTable[RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE] = Region("Dodongos Cavern MQ Back Behind Fire", SCENE_DODONGOS_CAVERN, { + //Events + EventAccess(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH, []{return logic->CanDetonateBombFlowers();}), + }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, true), //pulling the grave isn't required, as you can open the chest through it + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BACK_POE_GRASS, logic->CanCutShrubs()), @@ -537,16 +565,17 @@ void RegionTable_Init_DodongosCavern() { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return logic->CanAttack();}), //There's a trick N64 rolls into the child eyes trick for using armos blow up the bomb flowers when dieing, which would be killing an armos - Entrance(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, []{return Here(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, []{return logic->CanDetonateBombFlowers();}) || Here(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, []{return logic->CanAttack();});}), + //RANDOTODO investigate using hovers to go from the door ledge to the block directly + Entrance(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, []{return logic->Get(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH);}), }); areaTable[RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE] = Region("Dodongos Cavern MQ BossArea", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH, []{return true/*str0 || logic->CanHitSwitch() || logic->CanDetonateBombFlowers()*/;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) || logic->HasItem(RG_GORONS_BRACELET) || //even if you somehow warp to BACK_BEHIND_FIRE, if you can kill the skull at range, you can get to BEHIND_MOUTH - Here(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) /* || bunny jumps*/);})), + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) || logic->HasItem(RG_GORONS_BRACELET)), LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_NW_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_NE_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_GRASS, logic->CanCutShrubs()), @@ -573,19 +602,19 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] = Region("Dodongos Cavern Boss Room", SCENE_DODONGOS_CAVERN_BOSS, { // Events // Blue Fire Arrows need similar accuracy as hammer trick, only put in logic when both hammer & blue fire tricks enabled - EventAccess(&logic->DodongosCavernClear, []{return Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || + EventAccess(LOGIC_DODONGOS_CAVERN_CLEAR, []{return Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || (ctx->GetTrickOption(RT_DC_HAMMER_FLOOR) ? logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->BlueFire()) : ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE));}) && logic->CanKillEnemy(RE_KING_DODONGO);}), }, { // Locations LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true), - LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->DodongosCavernClear), - LOCATION(RC_KING_DODONGO, logic->DodongosCavernClear), + LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), + LOCATION(RC_KING_DODONGO, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), }, { // Exits Entrance(RR_DODONGOS_CAVERN_BOSS_EXIT, []{return true;}), - Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->DodongosCavernClear;}, false), + Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR);}, false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index f57d6bd21..d7ae81645 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -20,14 +20,14 @@ void RegionTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}), Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->FireTimer() >= 24;}), - Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked);}), + Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(SCENE_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked());}), Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return true;}), - Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24;}), + Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24;}), }); areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), + EventAccess(LOGIC_FAIRY_POT, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), }, { //Locations LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, true), @@ -38,12 +38,12 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return true;}), - Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return logic->CanUse(RG_MEGATON_HAMMER);}) || logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->Get(LOGIC_FIRE_HIT_PLATFORM) || logic->CanUse(RG_HOVER_BOOTS));}), }); areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Region("Fire Temple Loop Enemies", SCENE_FIRE_TEMPLE, {}, {}, { //Exits - Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked;}), + Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked();}), Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return Here(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return logic->CanKillEnemy(RE_TORCH_SLUG) && logic->CanKillEnemy(RE_FIRE_KEESE);});}), }); @@ -58,7 +58,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_FLARE_DANCER] = Region("Fire Temple Loop Flare Dancer", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, (logic->HasExplosives() || logic->CanUse(RG_MEGATON_HAMMER)) && logic->IsAdult), + LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, (logic->HasExplosives() || logic->CanUse(RG_MEGATON_HAMMER)) && (logic->IsAdult || logic->CanGroundJump())), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return true;}), @@ -67,11 +67,11 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Region("Fire Temple Loop Hammer Switch", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->FireLoopSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_FIRE_LOOP_SWITCH, []{return logic->CanUse(RG_MEGATON_HAMMER);}), }, {}, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_LOOP_GORON_ROOM, []{return logic->FireLoopSwitch;}), + Entrance(RR_FIRE_TEMPLE_LOOP_GORON_ROOM, []{return logic->Get(LOGIC_FIRE_LOOP_SWITCH);}), }); areaTable[RR_FIRE_TEMPLE_LOOP_GORON_ROOM] = Region("Fire Temple Loop Goron Room", SCENE_FIRE_TEMPLE, {}, { @@ -79,14 +79,14 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, true), }, { //Exits - Entrance(RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH, []{return logic->FireLoopSwitch;}), - Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return logic->FireLoopSwitch;}), + Entrance(RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH, []{return logic->Get(LOGIC_FIRE_LOOP_SWITCH);}), + Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return logic->Get(LOGIC_FIRE_LOOP_SWITCH);}), }); areaTable[RR_FIRE_TEMPLE_LOOP_EXIT] = Region("Fire Temple Loop Exit", SCENE_FIRE_TEMPLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return true;}), - Entrance(RR_FIRE_TEMPLE_LOOP_GORON_ROOM, []{return logic->FireLoopSwitch;}), + Entrance(RR_FIRE_TEMPLE_LOOP_GORON_ROOM, []{return logic->Get(LOGIC_FIRE_LOOP_SWITCH);}), }); areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM] = Region("Fire Temple Big Lava Room", SCENE_FIRE_TEMPLE, {}, { @@ -96,11 +96,11 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_POT_3, logic->CanBreakPots()), }, { //Exits - Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 2);}), + Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 2);}), Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, []{return true;}), Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, []{return logic->IsAdult && (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_FIRE_SOT));}), Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, []{return logic->IsAdult && logic->HasExplosives();}), - Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 3);}), + Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 3);}), }); areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON] = Region("Fire Temple Big Lava Room North Goron", SCENE_FIRE_TEMPLE, {}, { @@ -135,21 +135,22 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_FIRE_PILLAR_BACK_HEART, logic->FireTimer() >= 56), }, { //Exits - Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 3);}), - Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return logic->FireTimer() >= 56 && logic->SmallKeys(RR_FIRE_TEMPLE, 4);}), + Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 3);}), + Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return logic->FireTimer() >= 56 && logic->SmallKeys(SCENE_FIRE_TEMPLE, 4);}), }); areaTable[RR_FIRE_TEMPLE_SHORTCUT_ROOM] = Region("Fire Temple Shortcut Room", SCENE_FIRE_TEMPLE, {}, { - //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;})), }, { //Exits - Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 4);}), + Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 4);}), Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}), - Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_FIRE_STRENGTH)) && (logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT));}), + Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_FIRE_STRENGTH) || logic->CanGroundJump()) && (logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT));}), }); - areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Region("Fire Temple Shortcut Climb", SCENE_FIRE_TEMPLE, {}, {}, { + areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Region("Fire Temple Shortcut Climb", SCENE_FIRE_TEMPLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, true), + }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return true;}), Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, []{return true;}), @@ -163,7 +164,7 @@ void RegionTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return true;}), Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM, []{return true;}), - Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 5, 7);}), + Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 5);}), Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, []{return false;}), }); @@ -183,8 +184,8 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->TakeDamage();}), - Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 5, 8);}), - Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 6, 8);}), + Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 5);}), + Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 6);}), Entrance(RR_FIRE_TEMPLE_MAP_AREA, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW);}), }); @@ -195,10 +196,10 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_FIRE_WALL_EXIT_HEART, logic->FireTimer() >= 24), }, { //Exits - Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, []{return logic->FireTimer() >= 24 && logic->SmallKeys(RR_FIRE_TEMPLE, 6, 8);}), + Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, []{return logic->FireTimer() >= 24 && logic->SmallKeys(SCENE_FIRE_TEMPLE, 6);}), Entrance(RR_FIRE_TEMPLE_MAP_AREA, []{return logic->IsAdult;}), Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, []{return logic->FireTimer() >= 24 && logic->IsAdult;}), - Entrance(RR_FIRE_TEMPLE_CORRIDOR, []{return logic->FireTimer() >= 24 && logic->IsAdult && logic->SmallKeys(RR_FIRE_TEMPLE, 7);}), + Entrance(RR_FIRE_TEMPLE_CORRIDOR, []{return logic->FireTimer() >= 24 && logic->IsAdult && logic->SmallKeys(SCENE_FIRE_TEMPLE, 7);}), }); areaTable[RR_FIRE_TEMPLE_MAP_AREA] = Region("Fire Temple Map Region", SCENE_FIRE_TEMPLE, {}, { @@ -241,7 +242,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_CORRIDOR] = Region("Fire Temple Corridor", SCENE_FIRE_TEMPLE, {}, {}, { //Exits - Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 7);}), + Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 7);}), Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, []{return true;}), }); @@ -254,13 +255,16 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_CORRIDOR, []{return true;}), - Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump();}), Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM, []{return true;}), - Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8);}), + Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 8);}), Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, []{return ctx->GetTrickOption(RT_FIRE_FLAME_MAZE) || false;}), }); - areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_UPPER] = Region("Fire Temple Fire Maze Upper", SCENE_FIRE_TEMPLE, {}, {}, { + areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_UPPER] = Region("Fire Temple Fire Maze Upper", SCENE_FIRE_TEMPLE, { + //Events + EventAccess(LOGIC_FIRE_HIT_PLATFORM, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + }, {}, { //Exits Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}), Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, []{return true;}), @@ -275,17 +279,17 @@ void RegionTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, []{return true;}), }); - areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Region("Fire Temple West Central Lower", SCENE_FIRE_TEMPLE, {}, { - //Locations - LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER);})), - }, { + areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Region("Fire Temple West Central Lower", SCENE_FIRE_TEMPLE, {}, {}, { //Exits - Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8);}), + Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 8);}), Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME);}), Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, []{return true;}), }); - areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER] = Region("Fire Temple West Central Upper", SCENE_FIRE_TEMPLE, {}, {}, { + areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER] = Region("Fire Temple West Central Upper", SCENE_FIRE_TEMPLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER)), + }, { //Exits Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return false;}), Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return true;}), @@ -357,7 +361,7 @@ void RegionTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}), Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return true;}), Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, []{return logic->IsAdult || logic->CanUse(RG_HOOKSHOT);}), - Entrance(RR_FIRE_TEMPLE_MQ_STALFOS_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 5);}), + Entrance(RR_FIRE_TEMPLE_MQ_STALFOS_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 5);}), }); areaTable[RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER] = Region("Fire Temple MQ First Room Upper", SCENE_FIRE_TEMPLE, {}, {}, { @@ -373,7 +377,7 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return logic->CanKillEnemy(RE_LIKE_LIKE);});}), - Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE, []{return logic->OpenedLowestGoronCage;}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE, []{return logic->Get(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE);}), }); areaTable[RR_FIRE_TEMPLE_MQ_STALFOS_ROOM] = Region("Fire Temple MQ Stalfos Room", SCENE_FIRE_TEMPLE, {}, { @@ -382,12 +386,12 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM, []{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), + Entrance(RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM, []{return Here(RR_FIRE_TEMPLE_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), }); areaTable[RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM] = Region("Fire Temple MQ Iron Knuckle Room", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), @@ -402,7 +406,7 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_STALFOS_ROOM, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, []{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, []{return Here(RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), }); areaTable[RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER] = Region("Fire Temple MQ Lower Flare Dancer", SCENE_FIRE_TEMPLE, {}, { @@ -416,11 +420,11 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH] = Region("Fire Temple MQ Map Room North", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->OpenedLowestGoronCage, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE, []{return logic->CanUse(RG_MEGATON_HAMMER);}), }, {}, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE, []{return logic->OpenedLowestGoronCage;}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE, []{return logic->Get(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE);}), }); areaTable[RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE] = Region("Fire Temple MQ Map Room Cage", SCENE_FIRE_TEMPLE, {}, { @@ -428,8 +432,8 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, true), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH, []{return logic->OpenedLowestGoronCage;}), - Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return logic->OpenedLowestGoronCage;}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH, []{return logic->Get(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE);}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return logic->Get(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE);}), }); areaTable[RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM] = Region("Fire Temple MQ Near Boss Room", SCENE_FIRE_TEMPLE, {}, { @@ -444,7 +448,7 @@ void RegionTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, []{return true;}), //Child cannot make it to the north side torches without a hook without specifically bunny hood speed + hover boots Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM_NORTH, []{return logic->FireTimer() > 32 && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));}), - Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->FireTimer() >= 15 && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->IsAdult && logic->HitFireTemplePlatform) || (logic->HitFireTemplePlatform && logic->CanUse(RG_HOVER_BOOTS)));}), + Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->FireTimer() >= 15 && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))));}), }); //This room assumes tunic logic is handled on entry. @@ -485,13 +489,13 @@ void RegionTable_Init_FireTemple() { //Exits // Fewer tunic requirements ends here Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, []{return logic->FireTimer() >= 20;}), - Entrance(RR_FIRE_TEMPLE_MQ_ELEVATOR_ROOM, []{return logic->CanUse(RG_GORON_TUNIC) && logic->SmallKeys(RR_FIRE_TEMPLE, 2);}), + Entrance(RR_FIRE_TEMPLE_MQ_ELEVATOR_ROOM, []{return logic->CanUse(RG_GORON_TUNIC) && logic->SmallKeys(SCENE_FIRE_TEMPLE, 2);}), Entrance(RR_FIRE_TEMPLE_MQ_TORCH_FIREWALL_ROOM, []{return logic->HasFireSource() && ((logic->CanUse(RG_FAIRY_BOW) && logic->FireTimer() >= 25) || (ctx->GetTrickOption(RT_FIRE_MQ_BK_CHEST) && logic->FireTimer() >= 50)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && ctx->GetTrickOption(RT_FIRE_SOT)));}), }); areaTable[RR_FIRE_TEMPLE_MQ_TORCH_FIREWALL_ROOM] = Region("Fire Temple MQ Torch Firewall Room", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return logic->CanUse(RG_HOOKSHOT);}), + EventAccess(LOGIC_FAIRY_POT, []{return logic->CanUse(RG_HOOKSHOT);}), }, { //Locations LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT)), @@ -518,7 +522,7 @@ void RegionTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, []{return (logic->HasFireSource() && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->CanUse(RG_HOVER_BOOTS));}), Entrance(RR_FIRE_TEMPLE_MQ_ELEVATOR_ROOM, []{return logic->CanUse(RG_GORON_TUNIC);}), - Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE, []{return logic->OpenedUpperFireShortcut;}), + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), }); areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE] = Region("Fire Temple MQ Lower Maze", SCENE_FIRE_TEMPLE, {}, { @@ -556,7 +560,7 @@ void RegionTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT, []{return logic->HasExplosives();}), //Implies RR_FIRE_TEMPLE_MQ_LOWER_MAZE access Entrance(RR_FIRE_TEMPLE_MQ_BURNING_BLOCK_CLIMB, []{return logic->HasExplosives() && logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME)));}), - Entrance(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 3) && logic->CanUse(RG_GORON_TUNIC);}), + Entrance(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 3) && logic->CanUse(RG_GORON_TUNIC);}), }); areaTable[RR_FIRE_TEMPLE_MQ_UPPER_MAZE_BOX_CAGE] = Region("Fire Temple MQ Upper Maze Box Cage", SCENE_FIRE_TEMPLE, {}, { @@ -576,26 +580,26 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT] = Region("Fire Temple MQ Maze Shortcut", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->OpenedUpperFireShortcut, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_FIRE_OPENED_UPPER_SHORTCUT, []{return logic->CanUse(RG_MEGATON_HAMMER);}), }, {}, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE, []{return logic->OpenedUpperFireShortcut;}), + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), }); areaTable[RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE] = Region("Fire Temple MQ Maze Shortcut Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->OpenedUpperFireShortcut;), - LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_1, logic->OpenedUpperFireShortcut && logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_2, logic->OpenedUpperFireShortcut && logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_3, logic->OpenedUpperFireShortcut && logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_4, logic->OpenedUpperFireShortcut && logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_5, logic->OpenedUpperFireShortcut && logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_6, logic->OpenedUpperFireShortcut && logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);), + LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_1, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_2, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_3, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_4, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_5, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_6, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT, []{return logic->OpenedUpperFireShortcut;}), - Entrance(RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM, []{return logic->OpenedUpperFireShortcut;}), + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), + Entrance(RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), }); @@ -614,7 +618,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM] = Region("Fire Temple MQ Narrow Path Room", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_FIRE_TEMPLE_MQ_ABOVE_LAVA_POT_1, logic->CanBreakPots()), @@ -642,7 +646,7 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_TORCH_SMALL_CRATE_5, logic->CanBreakSmallCrates()), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 3);}), + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 3);}), Entrance(RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM, []{return true;}), //Child has issues navigating the higher points of this room without an equip swapped hookshot Entrance(RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, []{return Here(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, []{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT));}) && (logic->IsAdult || logic->CanUse(RG_HOOKSHOT));}), @@ -655,18 +659,18 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE_EAST_POT, logic->CanBreakPots()), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, []{return logic->HitFireTemplePlatform;}), + Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, []{return logic->Get(LOGIC_FIRE_HIT_PLATFORM);}), Entrance(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, []{return true;}), Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS, []{return logic->IsAdult || logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS);}), //Hover boots get there via the platforms Entrance(RR_FIRE_TEMPLE_MQ_NORTH_FIRE_MAZE, []{return (bool)ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}), - Entrance(RR_FIRE_TEMPLE_MQ_WEST_FIRE_MAZE, []{return logic->OpenedFireMQFireMazeDoor;}), + Entrance(RR_FIRE_TEMPLE_MQ_WEST_FIRE_MAZE, []{return logic->Get(LOGIC_FIRE_MQ_OPENED_FIRE_MAZE_DOOR);}), }); areaTable[RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS] = Region("Fire Temple MQ Fire Maze Platforms", SCENE_FIRE_TEMPLE, { //Events - EventAccess(&logic->HitFireTemplePlatform, []{return logic->CanUse(RG_MEGATON_HAMMER);}), - EventAccess(&logic->OpenedFireMQFireMazeDoor, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT);}), + EventAccess(LOGIC_FIRE_HIT_PLATFORM, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_FIRE_MQ_OPENED_FIRE_MAZE_DOOR, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT);}), }, {}, { Entrance(RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, []{return true;}), Entrance(RR_FIRE_TEMPLE_MQ_NORTH_FIRE_MAZE, []{return logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -705,7 +709,7 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, logic->CanKillEnemy(RE_FLARE_DANCER)), }, { Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PAST_WALL, []{return logic->CanKillEnemy(RE_FLARE_DANCER);}), - Entrance(RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, []{return logic->CanKillEnemy(RE_FLARE_DANCER) && logic->SmallKeys(RR_FIRE_TEMPLE, 4);}), + Entrance(RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, []{return logic->CanKillEnemy(RE_FLARE_DANCER) && logic->SmallKeys(SCENE_FIRE_TEMPLE, 4);}), }); areaTable[RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM] = Region("Fire Temple MQ Scarecrow Room", SCENE_FIRE_TEMPLE, {}, { @@ -718,8 +722,8 @@ void RegionTable_Init_FireTemple() { //Using this dropdown is in N64 logic elsewhere, but not here, probably because it requires good foreknowlege to determine where to land //This would be a logical method to reach the hammer switch without hookshot, but it practically requires access to the area that switch unlocks already. It could also be first child access to PLATFORMS if tricks ever enable that //If a practical use for this drop is found, it should be made a trick - Entrance(RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 4);}), - Entrance(RR_FIRE_TEMPLE_MQ_COLLAPSED_STAIRS, []{return Here(RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && logic->SmallKeys(RR_FIRE_TEMPLE, 5);}), + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 4);}), + Entrance(RR_FIRE_TEMPLE_MQ_COLLAPSED_STAIRS, []{return Here(RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && logic->SmallKeys(SCENE_FIRE_TEMPLE, 5);}), }); //The peg knocked down from here could have logical implications for child in the fire maze if tricks to gain height like bomb jumps exist @@ -744,15 +748,15 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", SCENE_FIRE_TEMPLE_BOSS, { // Events - EventAccess(&logic->FireTempleClear, []{return logic->FireTimer() >= 64 && logic->CanKillEnemy(RE_VOLVAGIA);}), + EventAccess(LOGIC_FIRE_TEMPLE_CLEAR, []{return logic->FireTimer() >= 64 && logic->CanKillEnemy(RE_VOLVAGIA);}), }, { // Locations - LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->FireTempleClear), - LOCATION(RC_VOLVAGIA, logic->FireTempleClear), + LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->Get(LOGIC_FIRE_TEMPLE_CLEAR)), + LOCATION(RC_VOLVAGIA, logic->Get(LOGIC_FIRE_TEMPLE_CLEAR)), }, { // Exits Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return false;}), - Entrance(RR_DMC_CENTRAL_LOCAL, []{return logic->FireTempleClear;}, false), + Entrance(RR_DMC_CENTRAL_LOCAL, []{return logic->Get(LOGIC_FIRE_TEMPLE_CLEAR);}, false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp index a4a558297..a4a0563cf 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -34,7 +34,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_LOBBY] = Region("Forest Temple Lobby", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleMeg, []{return logic->ForestTempleJoelle && logic->ForestTempleBeth && logic->ForestTempleAmy && logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_MEG, []{return logic->Get(LOGIC_FOREST_JOELLE) && logic->Get(LOGIC_FOREST_BETH) && logic->Get(LOGIC_FOREST_AMY) && logic->CanKillEnemy(RE_MEG);}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_GS_LOBBY, logic->HookshotOrBoomerang()), @@ -50,9 +50,9 @@ void RegionTable_Init_ForestTemple() { Entrance(RR_FOREST_TEMPLE_NORTH_CORRIDOR, []{return true;}), Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, []{return logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild;}), Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT);}), - Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 1, 5);}), + Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 1);}), Entrance(RR_FOREST_TEMPLE_EAST_CORRIDOR, []{return false;}), - Entrance(RR_FOREST_TEMPLE_BOSS_REGION, []{return logic->ForestTempleMeg;}), + Entrance(RR_FOREST_TEMPLE_BOSS_REGION, []{return logic->Get(LOGIC_FOREST_MEG);}), Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}), }); @@ -64,7 +64,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_LOWER_STALFOS] = Region("Forest Temple Lower Stalfos", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), @@ -77,30 +77,31 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER] = Region("Forest Temple NW Outdoors Lower", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, logic->CanUse(RG_LONGSHOT) || Here(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return logic->HookshotOrBoomerang();})), + LOCATION(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, logic->CanUse(RG_LONGSHOT)), LOCATION(RC_FOREST_TEMPLE_COURTYARD_RIGHT_HEART, logic->CanUse(RG_BOOMERANG) && ctx->GetTrickOption(RT_FOREST_OUTDOORS_HEARTS_BOOMERANG)), LOCATION(RC_FOREST_TEMPLE_COURTYARD_LEFT_HEART, logic->CanUse(RG_BOOMERANG) && ctx->GetTrickOption(RT_FOREST_OUTDOORS_HEARTS_BOOMERANG)), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, []{return logic->CanUse(RG_SONG_OF_TIME);}), - Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump()));}), Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}), - Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS) || HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}), + Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}), }); areaTable[RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER] = Region("Forest Temple NW Outdoors Upper", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_COURTYARD_RIGHT_HEART, true), - LOCATION(RC_FOREST_TEMPLE_COURTYARD_LEFT_HEART, true), + LOCATION(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, logic->HookshotOrBoomerang()), + LOCATION(RC_FOREST_TEMPLE_COURTYARD_RIGHT_HEART, true), + LOCATION(RC_FOREST_TEMPLE_COURTYARD_LEFT_HEART, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, []{return true;}), @@ -111,28 +112,32 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER] = Region("Forest Temple NE Outdoors Lower", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && logic->IsAdult && ctx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_FOREST_OUTDOORS_EAST_GS) && logic->CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives();})), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_FOREST_OUTDOORS_EAST_GS) && logic->CanUse(RG_BOOMERANG))), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}), Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, []{return logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT));}), - Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS) || HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}), + Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, []{return false;}), }); areaTable[RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER] = Region("Forest Temple NE Outdoors Upper", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), - }, {}, { + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), + }, { + //Locations + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->IsAdult && ctx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && logic->CanUse(RG_HOVER_BOOTS)), + }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, []{return true;}), Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return true;}), Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, []{return ctx->GetTrickOption(RT_FOREST_DOORFRAME) && logic->CanJumpslashExceptHammer() && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_SCARECROW);}), }); @@ -147,9 +152,20 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_SEWER] = Region("Forest Temple Sewer", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), - LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), - LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8), + LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), + LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), + }, { + //Exits + Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, []{return logic->HasItem(RG_BRONZE_SCALE);}), + Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, []{return logic->HasItem(RG_BRONZE_SCALE);}), + }); + + areaTable[RR_FOREST_TEMPLE_DRAINED_SEWER] = Region("Forest Temple Drained Well", SCENE_FOREST_TEMPLE, {}, { + //Locations + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, true), + LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, []{return true;}), @@ -171,7 +187,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_WEST_CORRIDOR] = Region("Forest Temple West Corridor", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_LOBBY, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 1, 5);}), + Entrance(RR_FOREST_TEMPLE_LOBBY, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 1);}), Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, []{return logic->CanAttack() || logic->CanUse(RG_NUTS);}), }); @@ -182,14 +198,14 @@ void RegionTable_Init_ForestTemple() { //Exits Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, []{return true;}), Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && logic->CanJumpslashExceptHammer() && logic->HasItem(RG_GORONS_BRACELET));}), - Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, []{return logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET) && logic->SmallKeys(RR_FOREST_TEMPLE, 2);}), - Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, []{return logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)) && logic->HasItem(RG_GORONS_BRACELET) && logic->SmallKeys(RR_FOREST_TEMPLE, 2);}), + Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, []{return logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET) && logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), + Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, []{return logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)) && logic->HasItem(RG_GORONS_BRACELET) && logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), }); areaTable[RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Region("Forest Temple NW Corridor Twisted", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 2);}), - Entrance(RR_FOREST_TEMPLE_RED_POE_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 3);}), + Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), + Entrance(RR_FOREST_TEMPLE_RED_POE_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), }); areaTable[RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED] = Region("Forest Temple NW Corridor Straightened", SCENE_FOREST_TEMPLE, {}, { @@ -198,18 +214,18 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return true;}), - Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 2);}), + Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), }); areaTable[RR_FOREST_TEMPLE_RED_POE_ROOM] = Region("Forest Temple Red Poe Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleJoelle, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->ForestTempleJoelle), + LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), }, { //Exits - Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 3);}), + Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), Entrance(RR_FOREST_TEMPLE_UPPER_STALFOS, []{return true;}), }); @@ -228,28 +244,28 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_BLUE_POE_ROOM] = Region("Forest Temple Blue Poe Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleBeth, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->ForestTempleBeth), + LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->Get(LOGIC_FOREST_BETH)), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_3, logic->CanBreakPots()), }, { //Exits Entrance(RR_FOREST_TEMPLE_UPPER_STALFOS, []{return true;}), - Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 4);}), + Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), }); areaTable[RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED] = Region("Forest Temple NE Corridor Straightened", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_BLUE_POE_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 4);}), - Entrance(RR_FOREST_TEMPLE_FROZEN_EYE_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 5);}), + Entrance(RR_FOREST_TEMPLE_BLUE_POE_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), + Entrance(RR_FOREST_TEMPLE_FROZEN_EYE_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 5);}), }); areaTable[RR_FOREST_TEMPLE_NE_CORRIDOR_TWISTED] = Region("Forest Temple NE Corridor Twisted", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_FROZEN_EYE_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 5);}), + Entrance(RR_FOREST_TEMPLE_FROZEN_EYE_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 5);}), Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, []{return true;}), }); @@ -259,13 +275,15 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_FROZEN_EYE_POT_2, logic->CanBreakPots()), }, { //Exits - Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 5);}), - Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_TWISTED, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 5) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE));}), + Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 5);}), + Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_TWISTED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 5) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE));}), }); areaTable[RR_FOREST_TEMPLE_FALLING_ROOM] = Region("Forest Temple Falling Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives()), + LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, []{return true;}), @@ -274,7 +292,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_GREEN_POE_ROOM] = Region("Forest Temple Green Poe Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleAmy, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_AMY, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_GREEN_POE_POT_1, logic->CanBreakPots()), @@ -282,7 +300,7 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, []{return true;}), - Entrance(RR_FOREST_TEMPLE_EAST_CORRIDOR, []{return logic->ForestTempleAmy;}), + Entrance(RR_FOREST_TEMPLE_EAST_CORRIDOR, []{return logic->Get(LOGIC_FOREST_AMY);}), }); areaTable[RR_FOREST_TEMPLE_EAST_CORRIDOR] = Region("Forest Temple East Corridor", SCENE_FOREST_TEMPLE, {}, {}, { @@ -313,12 +331,12 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 1) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), + Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 1) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), }); areaTable[RR_FOREST_TEMPLE_MQ_CENTRAL_AREA] = Region("Forest Temple MQ Central Region", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleMeg, []{return logic->ForestTempleJoelle && logic->ForestTempleBeth && logic->ForestTempleAmy && logic->CanKillEnemy(RE_MEG);}), + EventAccess(LOGIC_FOREST_MEG, []{return logic->Get(LOGIC_FOREST_JOELLE) && logic->Get(LOGIC_FOREST_BETH) && logic->Get(LOGIC_FOREST_AMY) && logic->CanKillEnemy(RE_MEG);}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_LOBBY_POT_1, logic->CanBreakPots()), @@ -334,69 +352,69 @@ void RegionTable_Init_ForestTemple() { Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, []{return logic->CanHitEyeTargets();}), Entrance(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, []{return Here(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->CanKillEnemy(RE_STALFOS);});}), //implies the other 3 poes - Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT, []{return logic->ForestTempleMeg;}), + Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT, []{return logic->Get(LOGIC_FOREST_MEG);}), }); areaTable[RR_FOREST_TEMPLE_MQ_WOLFOS_ROOM] = Region("Forest Temple MQ Wolfos Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), - EventAccess(&logic->ForestClearBelowBowChest, []{return logic->CanKillEnemy(RE_WOLFOS);}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), + EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->ForestClearBelowBowChest), + LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH)), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_2, logic->CanBreakPots()), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->ForestClearBelowBowChest && (logic->IsChild || logic->CanUse(RG_SONG_OF_TIME));}), + Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && (logic->IsChild || logic->CanUse(RG_SONG_OF_TIME));}), }); areaTable[RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE] = Region("Forest Temple MQ Lower Block Puzzle", SCENE_FOREST_TEMPLE, { //longshot is capable of hitting the switch, but some invisible collision makes the shot harder than you would think, so it may be trickworthy - EventAccess(&logic->MQForestBlockRoomTargets, []{return (ctx->GetTrickOption(RT_FOREST_MQ_BLOCK_PUZZLE) && logic->CanUse(RG_BOMBCHU_5));}), + EventAccess(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, []{return (ctx->GetTrickOption(RT_FOREST_MQ_BLOCK_PUZZLE) && logic->CanUse(RG_BOMBCHU_5));}), //It is barely possible to get this as child with master + hovers, but it's tight without bunny speed - EventAccess(&logic->ForestCanTwistHallway, []{return (ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && (logic->IsAdult && logic->CanJumpslash()) || (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || (logic->MQForestBlockRoomTargets && logic->CanUse(RG_MASTER_SWORD)))) || (ctx->GetTrickOption(RT_FOREST_MQ_RANG_HALLWAY_SWITCH) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH) && logic->CanUse(RG_HOOKSHOT));}), + EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return (ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && (logic->IsAdult && logic->CanJumpslash()) || (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_MASTER_SWORD)))) || (ctx->GetTrickOption(RT_FOREST_MQ_RANG_HALLWAY_SWITCH) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH) && logic->CanUse(RG_HOOKSHOT));}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return Here(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->CanKillEnemy(RE_STALFOS);});}), - Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return logic->HasItem(RG_GORONS_BRACELET) || (logic->MQForestBlockRoomTargets && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return Here(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, []{return logic->CanKillEnemy(RE_STALFOS);});}), + Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return logic->HasItem(RG_GORONS_BRACELET) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), //Assumes RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE access - Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)) || (logic->MQForestBlockRoomTargets && logic->CanUse(RG_HOOKSHOT));}), - Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, []{return logic->ForestCanTwistHallway && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}), }); areaTable[RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE] = Region("Forest Temple MQ Middle Block Puzzle", SCENE_FOREST_TEMPLE, { //longshot is capable of hitting the switch, but some invisible collision makes the shot more annoying than you would think, so it may be trickworthy - EventAccess(&logic->MQForestBlockRoomTargets, []{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_LONGSHOT));}), - EventAccess(&logic->ForestCanTwistHallway, []{return ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && (logic->IsAdult && logic->CanJumpslash()) || (logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD)));}), + EventAccess(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, []{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_LONGSHOT));}), + EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && (logic->IsAdult && logic->CanJumpslash()) || (logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD)));}), }, {}, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)) || (logic->MQForestBlockRoomTargets && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), //Hammer cannot recoil from here, but can make the jump forwards with a hammer jumpslash as adult - Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, []{return logic->ForestCanTwistHallway && logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (logic->CanJumpslashExceptHammer() || (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER))));}), + Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (logic->CanJumpslashExceptHammer() || (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER))));}), }); areaTable[RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE] = Region("Forest Temple MQ After Block Puzzle", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(RR_FOREST_TEMPLE, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3)), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 3);}), - Entrance(RR_FOREST_TEMPLE_MQ_JOELLE_ROOM, []{return logic->ForestCanTwistHallway && logic->SmallKeys(RR_FOREST_TEMPLE, 4);}), + Entrance(RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), + Entrance(RR_FOREST_TEMPLE_MQ_JOELLE_ROOM, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), //!QUANTUM LOGIC! //As there is no way in default logic to reach the other possible key use without going through RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, this is logically safe for now //Breaks if there's any other way to RR_FOREST_TEMPLE_MQ_FALLING_ROOM than going through the eye targets in RR_FOREST_TEMPLE_MQ_CENTRAL_AREA //Requires a bow/sling ammo source once ammo logic is done, to avoid edge cases. - Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 2) && Here(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return logic->CanKillEnemy(RE_FLOORMASTER);});}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2) && Here(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return logic->CanKillEnemy(RE_FLOORMASTER);});}), }); areaTable[RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY] = Region("Forest Temple MQ Straight Hallway", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(RR_FOREST_TEMPLE, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_FLOORMASTER_ROOM, []{return true;}), @@ -408,7 +426,7 @@ void RegionTable_Init_ForestTemple() { }); areaTable[RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE] = Region("Forest Temple MQ Outdoor Ledge", SCENE_FOREST_TEMPLE, { - EventAccess(&logic->ForestCanTwistHallway, []{return logic->CanHitSwitch();}), + EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return logic->CanHitSwitch();}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanKillEnemy(RE_REDEAD)), @@ -440,8 +458,8 @@ void RegionTable_Init_ForestTemple() { //The well only coniders the eye target here because the eye target is a temp flag, making it unwieldy to use as an EventAccess to make it it's own room areaTable[RR_FOREST_TEMPLE_MQ_NE_OUTDOORS] = Region("Forest Temple MQ NE Outdoors", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->CanHitEyeTargets() || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), @@ -483,39 +501,39 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_JOELLE_ROOM] = Region("Forest Temple MQ Joelle room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleJoelle, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->ForestTempleJoelle), + LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 4);}), + Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), Entrance(RR_FOREST_TEMPLE_MQ_3_STALFOS_ROOM, []{return true;}), }); areaTable[RR_FOREST_TEMPLE_MQ_3_STALFOS_ROOM] = Region("Forest Temple MQ 3 Stalfos Room", SCENE_FOREST_TEMPLE, { //Events //technically happens in RR_FOREST_TEMPLE_MQ_WOLFOS_ROOM, but the way this room blocks the hole means it cannot be logical to do anything else there. - EventAccess(&logic->ForestClearBelowBowChest, []{return logic->CanKillEnemy(RE_WOLFOS);}), + EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->ForestClearBelowBowChest && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_3, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_4, logic->CanBreakPots()), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_JOELLE_ROOM, []{return logic->ForestClearBelowBowChest && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3);}), - Entrance(RR_FOREST_TEMPLE_MQ_BETH_ROOM, []{return logic->ForestClearBelowBowChest && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3);}), + Entrance(RR_FOREST_TEMPLE_MQ_JOELLE_ROOM, []{return logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3);}), + Entrance(RR_FOREST_TEMPLE_MQ_BETH_ROOM, []{return logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3);}), }); areaTable[RR_FOREST_TEMPLE_MQ_BETH_ROOM] = Region("Forest Temple MQ Beth Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleBeth, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->ForestTempleBeth), + LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FOREST_BETH)), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_3, logic->CanBreakPots()), @@ -524,8 +542,8 @@ void RegionTable_Init_ForestTemple() { //!QUANTUM LOGIC! //This key logic assumes that you can get to falling room either by spending the 5th key here, or by wasting a key in falling room itself. //While being the 5th key makes this simpler in theory, if a different age can waste the key compared to reaching this room it breaks - Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 5) && Here(RR_FOREST_TEMPLE_MQ_BETH_ROOM, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE);});}), - Entrance(RR_FOREST_TEMPLE_MQ_TORCH_SHOT_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 6);}), + Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 5) && Here(RR_FOREST_TEMPLE_MQ_BETH_ROOM, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE);});}), + Entrance(RR_FOREST_TEMPLE_MQ_TORCH_SHOT_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 6);}), Entrance(RR_FOREST_TEMPLE_MQ_3_STALFOS_ROOM, []{return true;}), }); @@ -538,7 +556,7 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE);}), - Entrance(RR_FOREST_TEMPLE_MQ_BETH_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 6);}), + Entrance(RR_FOREST_TEMPLE_MQ_BETH_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 6);}), }); areaTable[RR_FOREST_TEMPLE_MQ_FALLING_ROOM] = Region("Forest Temple MQ Falling Room", SCENE_FOREST_TEMPLE, {}, { @@ -547,34 +565,34 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_AMY_ROOM, []{return logic->SmallKeys(RR_FOREST_TEMPLE, 6);}), + Entrance(RR_FOREST_TEMPLE_MQ_AMY_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 6);}), }); areaTable[RR_FOREST_TEMPLE_MQ_AMY_ROOM] = Region("Forest Temple MQ Amy Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(&logic->ForestTempleAmy, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_AMY, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_GREEN_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_GREEN_POE_POT_2, logic->CanBreakPots()), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->ForestTempleAmy;}), + Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->Get(LOGIC_FOREST_AMY);}), Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return true;}), }); areaTable[RR_FOREST_TEMPLE_MQ_BASEMENT] = Region("Forest Temple MQ Basement", SCENE_FOREST_TEMPLE, { //Events //Implies CanHitSwitch() - EventAccess(&logic->ForestOpenBossCorridor, []{return logic->CanHitEyeTargets();}), + EventAccess(LOGIC_FOREST_OPEN_BOSS_CORRIDOR, []{return logic->CanHitEyeTargets();}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, true), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->ForestTempleMeg;}), + Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->Get(LOGIC_FOREST_MEG);}), Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT_POT_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage();}), - Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, []{return logic->ForestOpenBossCorridor;}), + Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, []{return logic->Get(LOGIC_FOREST_OPEN_BOSS_CORRIDOR);}), }); areaTable[RR_FOREST_TEMPLE_MQ_BASEMENT_POT_ROOM] = Region("Forest Temple MQ Basement Pot Room", SCENE_FOREST_TEMPLE, {}, { @@ -590,7 +608,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_BOSS_REGION] = Region("Forest Temple MQ Boss Region", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT, []{return logic->ForestOpenBossCorridor;}), + Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT, []{return logic->Get(LOGIC_FOREST_OPEN_BOSS_CORRIDOR);}), Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return true;}), }); @@ -606,15 +624,15 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Region("Forest Temple Boss Room", SCENE_FOREST_TEMPLE_BOSS, { // Events - EventAccess(&logic->ForestTempleClear, []{return logic->CanKillEnemy(RE_PHANTOM_GANON);}), + EventAccess(LOGIC_FOREST_TEMPLE_CLEAR, []{return logic->CanKillEnemy(RE_PHANTOM_GANON);}), }, { // Locations - LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->ForestTempleClear), - LOCATION(RC_PHANTOM_GANON, logic->ForestTempleClear), + LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->Get(LOGIC_FOREST_TEMPLE_CLEAR)), + LOCATION(RC_PHANTOM_GANON, logic->Get(LOGIC_FOREST_TEMPLE_CLEAR)), }, { // Exits Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}), - Entrance(RR_SACRED_FOREST_MEADOW, []{return logic->ForestTempleClear;}, false), + Entrance(RR_SACRED_FOREST_MEADOW, []{return logic->Get(LOGIC_FOREST_TEMPLE_CLEAR);}, false), }); // clang-format on 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 8571ba384..3f52a231c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -35,7 +35,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_DEKU_SCRUBS] = Region("Ganon's Castle Deku Scrubs", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->FreeFairies, []{return true;}), + EventAccess(LOGIC_FREE_FAIRIES, []{return true;}), }, { //Locations LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku()), @@ -54,7 +54,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_FOREST_TRIAL] = Region("Ganon's Castle Forest Trial", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->ForestTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE));}), + EventAccess(LOGIC_FOREST_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE));}), }, { //Locations LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS)), @@ -64,7 +64,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_FIRE_TRIAL] = Region("Ganon's Castle Fire Trial", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->FireTrialClear, []{return logic->CanUse(RG_GORON_TUNIC) && logic->CanUse(RG_GOLDEN_GAUNTLETS) && logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_LONGSHOT);}), + EventAccess(LOGIC_FIRE_TRIAL_CLEAR, []{return logic->CanUse(RG_GORON_TUNIC) && logic->CanUse(RG_GOLDEN_GAUNTLETS) && logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_LONGSHOT);}), }, { //Locations LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_POT_1, logic->CanBreakPots() && logic->CanUse(RG_GORON_TUNIC) && logic->CanUse(RG_GOLDEN_GAUNTLETS) && logic->CanUse(RG_LONGSHOT)), @@ -74,9 +74,9 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->BlueFireAccess, []{return true;}), - EventAccess(&logic->FairyPot, []{return logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD);}), - EventAccess(&logic->WaterTrialClear, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}), + EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD);}), + EventAccess(LOGIC_WATER_TRIAL_CLEAR, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}), }, { //Locations LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, true), @@ -88,7 +88,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL] = Region("Ganon's Castle Shadow Trial", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->ShadowTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_MEGATON_HAMMER) && ((logic->CanUse(RG_FIRE_ARROWS) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_DINS_FIRE) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))))));}), + EventAccess(LOGIC_SHADOW_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_MEGATON_HAMMER) && ((logic->CanUse(RG_FIRE_ARROWS) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_DINS_FIRE) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))))));}), }, { //Locations LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), @@ -104,21 +104,21 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Region("Ganon's Castle Spirit Trial", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->NutPot, []{return ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}), - EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->CanUse(RG_BOMBCHU_5) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}), + EventAccess(LOGIC_NUT_POT, []{return ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}), + EventAccess(LOGIC_SPIRIT_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanJumpslashExceptHammer() || logic->CanUse(RG_BOMBCHU_5))), - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_1, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_2, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanJumpslashExceptHammer() || (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))))), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_1, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_2, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_HEART, true), }, {}); areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL] = Region("Ganon's Castle Light Trial", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->LightTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH));}), + EventAccess(LOGIC_LIGHT_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH));}), }, { //Locations LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, true), @@ -128,10 +128,10 @@ void RegionTable_Init_GanonsCastle() { LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, true), LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, true), LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(RR_GANONS_CASTLE, 1)), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_BOULDER_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_GANONS_CASTLE, 2)), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_POT_1, logic->CanBreakPots() && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_POT_2, logic->CanBreakPots() && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 1)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_BOULDER_POT_1, logic->CanBreakPots() && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_POT_1, logic->CanBreakPots() && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_POT_2, logic->CanBreakPots() && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), }, {}); #pragma endregion @@ -163,7 +163,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_DEKU_SCRUBS] = Region("Ganon's Castle MQ Deku Scrubs", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->FreeFairies, []{return true;}), + EventAccess(LOGIC_FREE_FAIRIES, []{return true;}), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku()), @@ -206,7 +206,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_FOREST_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Forest Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->ForestTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS);}), + EventAccess(LOGIC_FOREST_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS);}), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_POT_1, logic->CanBreakPots()), @@ -225,7 +225,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Fire Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->FireTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS);}), + EventAccess(LOGIC_FIRE_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS);}), //There's no way back across the lava without glitches }, { //Locations @@ -235,7 +235,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM] = Region("Ganon's Castle MQ Water Trial Geyser Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->BlueFireAccess, []{return logic->CanJumpslash() || logic->HasExplosives();}), + EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->CanJumpslash() || logic->HasExplosives();}), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire()), @@ -243,19 +243,19 @@ void RegionTable_Init_GanonsCastle() { }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return true;}), - Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM, []{return logic->SmallKeys(RR_GANONS_CASTLE, 3) && Here(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, []{return logic->BlueFire();});}), + Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3) && Here(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, []{return logic->BlueFire();});}), }); areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM] = Region("Ganon's Castle MQ Water Trial Block Room", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { //Exits - Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, []{return logic->SmallKeys(RR_GANONS_CASTLE, 3);}), + Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3);}), //This assumes there's no way for child to have blue fire and not adult. Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_FINAL_ROOM, []{return logic->IsAdult && logic->BlueFire();}), }); areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Water Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->WaterTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS);}), + EventAccess(LOGIC_WATER_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS);}), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_POT_1, logic->CanBreakPots()), @@ -267,19 +267,19 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE] = Region("Ganon's Castle MQ Shadow Trial Starting Ledge", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->ShadowTrialFirstChest, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_SHADOW_TRIAL_FIRST_CHEST, []{return logic->CanUse(RG_FAIRY_BOW);}), }, {}, { //Exits Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return true;}), - Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM, []{return (logic->ShadowTrialFirstChest && logic->CanUse(RG_HOOKSHOT)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM, []{return (logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}), }); areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM] = Region("Ganon's Castle MQ Shadow Trial Chest Platform", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->ShadowTrialFirstChest, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_SHADOW_TRIAL_FIRST_CHEST, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->ShadowTrialFirstChest), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST)), }, { //Exits //Hookshot here is possible but very tight, but it's basically never relevant @@ -290,7 +290,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM] = Region("Ganon's Castle MQ Shadow Trial Moving Platform", SCENE_INSIDE_GANONS_CASTLE, { //Events //A torch run from RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE is possible but tight, so would be a trick - EventAccess(&logic->ShadowTrialFirstChest, []{return logic->CanDetonateUprightBombFlower();}), + EventAccess(LOGIC_SHADOW_TRIAL_FIRST_CHEST, []{return logic->CanDetonateUprightBombFlower();}), }, {}, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM, []{return logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -323,7 +323,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Shadow Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->ShadowTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS);}), + EventAccess(LOGIC_SHADOW_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS);}), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_POT_1, logic->CanBreakPots()), @@ -365,8 +365,8 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Spirit Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS);}), - EventAccess(&logic->NutPot, []{return true;}), + EventAccess(LOGIC_SPIRIT_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS);}), + EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_POT_1, logic->CanBreakPots()), @@ -388,13 +388,13 @@ void RegionTable_Init_GanonsCastle() { }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return true;}), - Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_FRONT, []{return logic->SmallKeys(RR_GANONS_CASTLE, 2);}), + Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_FRONT, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2);}), }); areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_FRONT] = Region("Ganon's Castle MQ Light Trial Boulder Room Front", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { //Exits - Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_TRIFORCE_ROOM, []{return logic->SmallKeys(RR_GANONS_CASTLE, 2);}), - Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_BACK, []{return logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_GANON_MQ_LIGHT_TRIAL);}), + Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_TRIFORCE_ROOM, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2);}), + Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_BACK, []{return logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_GANON_MQ_LIGHT_TRIAL) || logic->CanGroundJump();}), }); areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_BACK] = Region("Ganon's Castle MQ Light Trial Boulder Room Back", SCENE_INSIDE_GANONS_CASTLE, {}, { @@ -404,13 +404,13 @@ void RegionTable_Init_GanonsCastle() { }, { //Exits //I got the trick going backwards, but only while taking damage. this isn't relevant anyway though - Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_FRONT, []{return logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_GANON_MQ_LIGHT_TRIAL);}), - Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_FINAL_ROOM, []{return logic->SmallKeys(RR_GANONS_CASTLE, 3) && (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanJumpslash() || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_BOOMERANG));}), + Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_FRONT, []{return logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_GANON_MQ_LIGHT_TRIAL) || logic->CanGroundJump();}), + Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_FINAL_ROOM, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3) && (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanJumpslash() || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_BOOMERANG));}), }); areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Light Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->LightTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS);}), + EventAccess(LOGIC_LIGHT_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS);}), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_POT_1, logic->CanBreakPots()), @@ -426,12 +426,12 @@ void RegionTable_Init_GanonsCastle() { Entrance(RR_GANONS_CASTLE_LOBBY, []{return ctx->GetDungeon(GANONS_CASTLE)->IsVanilla();}), Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return ctx->GetDungeon(GANONS_CASTLE)->IsMQ();}), //RANDOTODO could we just set these events automatically based on the setting? - Entrance(RR_GANONS_TOWER_FLOOR_1, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) && - (logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) && - (logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) && - (logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) && - (logic->SpiritTrialClear || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) && - (logic->LightTrialClear || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}), + Entrance(RR_GANONS_TOWER_FLOOR_1, []{return (logic->Get(LOGIC_FOREST_TRIAL_CLEAR) || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) && + (logic->Get(LOGIC_FIRE_TRIAL_CLEAR) || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) && + (logic->Get(LOGIC_WATER_TRIAL_CLEAR) || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) && + (logic->Get(LOGIC_SHADOW_TRIAL_CLEAR) || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) && + (logic->Get(LOGIC_SPIRIT_TRIAL_CLEAR) || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) && + (logic->Get(LOGIC_LIGHT_TRIAL_CLEAR) || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}), }); areaTable[RR_GANONS_TOWER_FLOOR_1] = Region("Ganon's Tower Floor 1", SCENE_GANONS_TOWER, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 6c891abc0..6d75dffb6 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp @@ -35,14 +35,14 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE] = Region("Gerudo Training Ground Central Maze", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 4)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 6)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 7)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 9)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9)), }, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 9);}), + Entrance(RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9);}), }); areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT] = Region("Gerudo Training Ground Central Maze Right", SCENE_GERUDO_TRAINING_GROUND, {}, { @@ -96,8 +96,8 @@ void RegionTable_Init_GerudoTrainingGround() { LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 4, true)), }, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER, []{return (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)));}), - Entrance(RR_GERUDO_TRAINING_GROUND_LIKE_LIKE_ROOM, []{return (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanUse(RG_SILVER_GAUNTLETS);}), + Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER, []{return (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanGroundJump()));}), + Entrance(RR_GERUDO_TRAINING_GROUND_LIKE_LIKE_ROOM, []{return (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanGroundJump())) && logic->CanUse(RG_SILVER_GAUNTLETS);}), }); areaTable[RR_GERUDO_TRAINING_GROUND_LIKE_LIKE_ROOM] = Region("Gerudo Training Ground Like Like Room", SCENE_GERUDO_TRAINING_GROUND, {}, { @@ -126,7 +126,7 @@ void RegionTable_Init_GerudoTrainingGround() { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return true;}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_HIDDEN_ROOM, []{return ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}), - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_FIRST_LOCK, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 1);}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_FIRST_LOCK, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 1);}), //It's possible to use the torch in RR_GERUDO_TRAINING_GROUND_MQ_MAZE_HIDDEN_ROOM with flame storage to light these Entrance(RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return logic->HasFireSource();});}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_ROOM, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT));});}), @@ -145,20 +145,20 @@ void RegionTable_Init_GerudoTrainingGround() { LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, true), }, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 1);}), - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 3);}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 1);}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3);}), }); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER] = Region("Gerudo Training Ground MQ Center", SCENE_GERUDO_TRAINING_GROUND, { //Events - EventAccess(&logic->MQGTGMazeSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_GTG_MQ_MAZE_SWITCH, []{return logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_CRATE, logic->CanBreakCrates()), }, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_FIRST_LOCK, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 3);}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_FIRST_LOCK, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3);}), }); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM] = Region("Gerudo Training Ground MQ Sand Room", SCENE_GERUDO_TRAINING_GROUND, {}, { @@ -178,7 +178,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM] = Region("Gerudo Training Ground MQ Stalfos Room", SCENE_GERUDO_TRAINING_GROUND, { //Events - EventAccess(&logic->BlueFireAccess, []{return true;}), + EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations //implies logic->CanKillEnemy(RE_BIG_SKULLTULA) @@ -186,7 +186,7 @@ void RegionTable_Init_GerudoTrainingGround() { }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) && logic->CanUse(RG_SILVER_GAUNTLETS);}), - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return logic->IsAdult && Here(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) && (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)));}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return logic->IsAdult && Here(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) && (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->BlueFire() && logic->IsAdult && (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanGroundJump());}), }); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK] = Region("Gerudo Training Ground MQ Behind Block", SCENE_GERUDO_TRAINING_GROUND, {}, { @@ -205,7 +205,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAGENTA_FIRE_ROOM] = Region("Gerudo Training Ground MQ Magenta Fire Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->MQGTGMazeSwitch), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->Get(LOGIC_GTG_MQ_MAZE_SWITCH)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return true;}), @@ -233,14 +233,14 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_SWITCH_LEDGE] = Region("Gerudo Training Ground MQ Switch Ledge", SCENE_GERUDO_TRAINING_GROUND, { //Events - EventAccess(&logic->MQGTGRightSideSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}), - EventAccess(&logic->GTGPlatformSilverRupees, []{return logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS);}), + EventAccess(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_GTG_PLATFORM_SILVER_RUPEES, []{return logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS);}), }, {}, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, []{return logic->CanUse(RG_FIRE_ARROWS);}), //the fire bubble here is a jerk if you are aiming for the nearest hook platform, you have to aim to the right hand side with hook to dodge it - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return logic->CanUse(RG_LONGSHOT) || (logic->GTGPlatformSilverRupees && logic->CanUse(RG_HOOKSHOT)) || ((logic->CanUse(RG_FIRE_ARROWS) && logic->GTGPlatformSilverRupees) && logic->CanUse(RG_HOVER_BOOTS));}), - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, []{return logic->MQGTGRightSideSwitch && logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return logic->CanUse(RG_LONGSHOT) || (logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES) && logic->CanUse(RG_HOOKSHOT)) || ((logic->CanUse(RG_FIRE_ARROWS) && logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES)) && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, []{return logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_LONGSHOT);}), }); //this region exists to place silver rupee items on later, normally it's all on fire and cannot be stood on without access from another area @@ -263,24 +263,24 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH] = Region("Gerudo Training Ground MQ Platforms Unlit Torch", SCENE_GERUDO_TRAINING_GROUND, { //Events - EventAccess(&logic->GTGPlatformSilverRupees, []{return logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS);}), + EventAccess(LOGIC_GTG_PLATFORM_SILVER_RUPEES, []{return logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS);}), }, {}, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER, []{return logic->GTGPlatformSilverRupees;}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER, []{return logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES);}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, []{return logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, []{return logic->HasFireSource() || logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, []{return logic->MQGTGRightSideSwitch && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->HasFireSource()));}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, []{return logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->HasFireSource()));}), }); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS] = Region("Gerudo Training Ground Torch Side Platforms", SCENE_GERUDO_TRAINING_GROUND, { //Events //this torch shot is possible as child but tight and obtuse enough to be a trick - EventAccess(&logic->GTGPlatformSilverRupees, []{return ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && logic->CanUse(RG_HOVER_BOOTS);}), + EventAccess(LOGIC_GTG_PLATFORM_SILVER_RUPEES, []{return ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && logic->CanUse(RG_HOVER_BOOTS);}), }, {}, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, []{return ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, []{return logic->MQGTGRightSideSwitch && ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT));}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, []{return logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT));}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_ROOM, []{return true;}), }); @@ -296,7 +296,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT] = Region("Gerudo Training Ground MQ Maze Right", SCENE_GERUDO_TRAINING_GROUND, { //Events - EventAccess(&logic->GTGPlatformSilverRupees, []{return logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS);}), + EventAccess(LOGIC_GTG_PLATFORM_SILVER_RUPEES, []{return logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS);}), }, { //Locations LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, true), @@ -305,7 +305,7 @@ void RegionTable_Init_GerudoTrainingGround() { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, []{return logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT) || (logic->GTGPlatformSilverRupees && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT) || (logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES) && logic->CanUse(RG_HOVER_BOOTS));}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, []{return logic->CanUse(RG_FIRE_ARROWS);}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM, []{return logic->CanUse(RG_FIRE_ARROWS);}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp index 5151377ce..823ff2eca 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -27,10 +27,10 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_MAIN] = Region("Ice Cavern", SCENE_ICE_CAVERN, { //Events - EventAccess(&logic->BlueFireAccess, []{return logic->IsAdult;}), + EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump());}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && logic->IsAdult), + LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && (logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump()))), LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, logic->BlueFire()), LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS)), LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS) && logic->IsAdult), @@ -45,11 +45,11 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_SPINNING_BLADE_POT_3, logic->CanBreakPots()), LOCATION(RC_ICE_CAVERN_NEAR_END_POT_1, logic->CanBreakPots() && logic->BlueFire()), LOCATION(RC_ICE_CAVERN_NEAR_END_POT_2, logic->CanBreakPots() && logic->BlueFire()), - LOCATION(RC_ICE_CAVERN_FROZEN_POT_1, logic->CanBreakPots() && logic->BlueFire() && logic->IsAdult), + LOCATION(RC_ICE_CAVERN_FROZEN_POT_1, logic->CanBreakPots() && logic->BlueFire() && (logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump()))), LOCATION(RC_ICE_CAVERN_LOBBY_RUPEE, logic->BlueFire()), - LOCATION(RC_ICE_CAVERN_MAP_ROOM_LEFT_HEART, logic->IsAdult), - LOCATION(RC_ICE_CAVERN_MAP_ROOM_MIDDLE_HEART, logic->IsAdult), - LOCATION(RC_ICE_CAVERN_MAP_ROOM_RIGHT_HEART, logic->IsAdult), + LOCATION(RC_ICE_CAVERN_MAP_ROOM_LEFT_HEART, logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())), + LOCATION(RC_ICE_CAVERN_MAP_ROOM_MIDDLE_HEART, logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())), + LOCATION(RC_ICE_CAVERN_MAP_ROOM_RIGHT_HEART, logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())), LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG))), @@ -71,7 +71,7 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_MQ_HUB] = Region("Ice Cavern MQ Hub", SCENE_ICE_CAVERN, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_ICE_CAVERN_MQ_FIRST_CRYSTAL_POT_1, logic->CanBreakPots()), @@ -85,15 +85,15 @@ void RegionTable_Init_IceCavern() { //the switch for the glass blocking the entrance is linked to the switch that controls the glass around the skulltulla in RR_ICE_CAVERN_MQ_SCARECROW_ROOM //if you clear the ice, you can hit it with a pot from here. Entrance(RR_ICE_CAVERN_MQ_BEGINNING, []{return logic->BlueFire();}), - Entrance(RR_ICE_CAVERN_MQ_MAP_ROOM, []{return Here(RR_ICE_CAVERN_MQ_BEGINNING, []{return logic->CanKillEnemy(RE_WHITE_WOLFOS) && logic->CanKillEnemy(RE_FREEZARD);});}), - Entrance(RR_ICE_CAVERN_MQ_COMPASS_ROOM, []{return logic->IsAdult && logic->BlueFire();}), + Entrance(RR_ICE_CAVERN_MQ_MAP_ROOM, []{return Here(RR_ICE_CAVERN_MQ_HUB, []{return logic->CanKillEnemy(RE_WHITE_WOLFOS) && logic->CanKillEnemy(RE_FREEZARD);});}), + Entrance(RR_ICE_CAVERN_MQ_COMPASS_ROOM, []{return (logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())) && logic->BlueFire();}), Entrance(RR_ICE_CAVERN_MQ_SCARECROW_ROOM, []{return logic->BlueFire();}), }); areaTable[RR_ICE_CAVERN_MQ_MAP_ROOM] = Region("Ice Cavern MQ Map Room", SCENE_ICE_CAVERN, { //Events //Child can fit between the stalagmites on the left hand side - EventAccess(&logic->BlueFireAccess, []{return logic->IsChild || logic->CanJumpslash() || logic->HasExplosives();}), + EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->IsChild || logic->CanJumpslash() || logic->HasExplosives();}), }, { //Locations LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire() && Here(RR_ICE_CAVERN_MQ_MAP_ROOM, []{return logic->CanHitSwitch();})), @@ -132,7 +132,7 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_MQ_COMPASS_ROOM] = Region("Ice Cavern MQ Compass Room", SCENE_ICE_CAVERN, { //Events - EventAccess(&logic->BlueFireAccess, []{return true;}), + EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp index 51e80fc0c..c473f6764 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -25,31 +25,31 @@ void RegionTable_Init_JabuJabusBelly() { //Combines Lift room middle and lower, 1F holes room, the forked corridor, and it's side rooms areaTable[RR_JABU_JABUS_BELLY_MAIN] = Region("Jabu Jabus Belly Main", SCENE_JABU_JABU, { //Events - EventAccess(&logic->JabuWestTentacle, []{return logic->JabuRutoIn1F && logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), + EventAccess(LOGIC_JABU_WEST_TENTACLE, []{return logic->Get(LOGIC_JABU_RUTO_IN_1F) && logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku()), //We can kill the Stingers with ruto - LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->JabuRutoIn1F), - LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->JabuWestTentacle), + LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->Get(LOGIC_JABU_RUTO_IN_1F)), + LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->Get(LOGIC_JABU_WEST_TENTACLE)), LOCATION(RC_JABU_JABUS_BELLY_PLATFORM_ROOM_SMALL_CRATE_1, logic->CanBreakSmallCrates()), LOCATION(RC_JABU_JABUS_BELLY_PLATFORM_ROOM_SMALL_CRATE_2, logic->CanBreakSmallCrates()), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_BEGINNING, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_COMPASS_ROOM, []{return logic->JabuWestTentacle;}), - Entrance(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, []{return logic->JabuWestTentacle;}), - Entrance(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, []{return logic->JabuEastTentacle;}), - Entrance(RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE, []{return logic->JabuNorthTentacle;}), - Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, []{return logic->LoweredJabuPath || (ctx->GetTrickOption(RT_JABU_BOSS_HOVER) && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_JABU_JABUS_BELLY_COMPASS_ROOM, []{return logic->Get(LOGIC_JABU_WEST_TENTACLE);}), + Entrance(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, []{return logic->Get(LOGIC_JABU_WEST_TENTACLE);}), + Entrance(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, []{return logic->Get(LOGIC_JABU_EAST_TENTACLE);}), + Entrance(RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE, []{return logic->Get(LOGIC_JABU_NORTH_TENTACLE);}), + Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, []{return logic->Get(LOGIC_JABU_LOWERED_PATH) || (ctx->GetTrickOption(RT_JABU_BOSS_HOVER) && logic->CanUse(RG_HOVER_BOOTS));}), }); //contains B1 of hole room (aside from the ledge leading to big octo), 2 octorock room and north water switch room areaTable[RR_JABU_JABUS_BELLY_B1_NORTH] = Region("Jabu Jabus Belly B1 North", SCENE_JABU_JABU, { //Events - EventAccess(&logic->JabuRutoIn1F, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), - EventAccess(&logic->FairyPot, []{return logic->CanUse(RG_BOOMERANG) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanKillEnemy(RE_OCTOROK));}), + EventAccess(LOGIC_JABU_RUTO_IN_1F, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), + EventAccess(LOGIC_FAIRY_POT, []{return logic->CanUse(RG_BOOMERANG) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanKillEnemy(RE_OCTOROK));}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, logic->HookshotOrBoomerang()), @@ -70,7 +70,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE] = Region("Jabu Jabus Belly Water Switch Room Ledge", SCENE_JABU_JABU, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations //this is the logic for climbing back and forth to use the pots to kill the skull... or killing the skull before climbing to grab the token @@ -105,19 +105,19 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_BLUE_TENTACLE] = Region("Jabu Jabus Belly Blue Tentacle", SCENE_JABU_JABU, { //Events - EventAccess(&logic->JabuEastTentacle, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), + EventAccess(LOGIC_JABU_EAST_TENTACLE, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), }, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->JabuEastTentacle;}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->Get(LOGIC_JABU_EAST_TENTACLE);}), }); areaTable[RR_JABU_JABUS_BELLY_GREEN_TENTACLE] = Region("Jabu Jabus Belly Green Tentacle", SCENE_JABU_JABU, { //Events - EventAccess(&logic->JabuNorthTentacle, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), + EventAccess(LOGIC_JABU_NORTH_TENTACLE, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), }, {}, { //Exits //implied logic->CanKillEnemy(RE_BARI) - Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->JabuNorthTentacle;}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->Get(LOGIC_JABU_NORTH_TENTACLE);}), }); areaTable[RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE] = Region("Jabu Jabus Belly Bigocto Room", SCENE_JABU_JABU, {}, { @@ -128,13 +128,13 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, []{return logic->JabuRutoIn1F && Here(RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE, []{return logic->CanKillEnemy(RE_BIG_OCTO);});}), + Entrance(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, []{return logic->Get(LOGIC_JABU_RUTO_IN_1F) && Here(RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE, []{return logic->CanKillEnemy(RE_BIG_OCTO);});}), }); areaTable[RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO] = Region("Jabu Jabus Belly Above Bigocto", SCENE_JABU_JABU, { //Events - EventAccess(&logic->FairyPot, []{return true;}), - EventAccess(&logic->NutPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_ABOVE_BIG_OCTO_POT_1, logic->CanBreakPots()), @@ -147,7 +147,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_LIFT_UPPER] = Region("Jabu Jabus Belly Lift Upper", SCENE_JABU_JABU, { //Events - EventAccess(&logic->LoweredJabuPath, []{return true;}), + EventAccess(LOGIC_JABU_LOWERED_PATH, []{return true;}), }, {}, { //Exits Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return true;}), @@ -168,7 +168,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_BEGINNING] = Region("Jabu Jabus Belly MQ Beginning", SCENE_JABU_JABU, { //Events - EventAccess(&logic->NutPot, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash()), @@ -185,7 +185,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM] = Region("Jabu Jabus Belly MQ Lift Room", SCENE_JABU_JABU, { //Events - EventAccess(&logic->MQJabuLiftRoomCow, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);}), + EventAccess(LOGIC_JABU_MQ_LIFT_ROOM_COW, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, true), @@ -198,14 +198,14 @@ void RegionTable_Init_JabuJabusBelly() { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_MQ_UNDERWATER_ALCOVE, []{return logic->HasItem(RG_SILVER_SCALE) || (logic->HasItem(RG_BRONZE_SCALE) && ((logic->IsChild || logic->CanUse(RG_IRON_BOOTS) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE))));}), - Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->MQJabuHolesRoomDoor;}), - Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE, []{return logic->LoweredJabuPath || logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_HOOKSHOT) && logic->MQJabuLiftRoomCow);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->Get(LOGIC_JABU_MQ_HOLES_ROOM_DOOR);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE, []{return logic->Get(LOGIC_JABU_LOWERED_PATH) || logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_HOOKSHOT) && logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW));}), //If opening RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM by lowering the geyser as 1 age is to let the other through is relevant, it needs an eventAccess }); areaTable[RR_JABU_JABUS_BELLY_MQ_UNDERWATER_ALCOVE] = Region("Jabu Jabus Belly MQ Underwater Alcove", SCENE_JABU_JABU, { //Events - EventAccess(&logic->MQJabuHolesRoomDoor, []{return true;}), + EventAccess(LOGIC_JABU_MQ_HOLES_ROOM_DOOR, []{return true;}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))), @@ -234,8 +234,8 @@ void RegionTable_Init_JabuJabusBelly() { Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->CanUse(RG_BOOMERANG) && logic->HasExplosives() && Here(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);});}), - Entrance(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, []{return logic->JabuNorthTentacle;}), - Entrance(RR_JABU_JABUS_BELLY_MQ_PAST_OCTO, []{return logic->JabuWestTentacle && Here(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanKillEnemy(RE_BIG_OCTO);}) && logic->CanUse(RG_FAIRY_SLINGSHOT);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, []{return logic->Get(LOGIC_JABU_NORTH_TENTACLE);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_PAST_OCTO, []{return logic->Get(LOGIC_JABU_WEST_TENTACLE) && Here(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanKillEnemy(RE_BIG_OCTO);}) && logic->CanUse(RG_FAIRY_SLINGSHOT);}), }); areaTable[RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM] = Region("Jabu Jabus Belly MQ Water Switch Room", SCENE_JABU_JABU, {}, { @@ -257,7 +257,7 @@ void RegionTable_Init_JabuJabusBelly() { //Includes Like Like room areaTable[RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR] = Region("Jabu Jabus Belly MQ Forked Corridor", SCENE_JABU_JABU, { //Events - EventAccess(&logic->JabuNorthTentacle, []{return Here(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->BlastOrSmash();}) && logic->CanUse(RG_BOOMERANG);}), + EventAccess(LOGIC_JABU_NORTH_TENTACLE, []{return Here(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->BlastOrSmash();}) && logic->CanUse(RG_BOOMERANG);}), }, { //Locations //Implies CanKillEnemy(RE_LIKE_LIKE) @@ -276,7 +276,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS] = Region("Jabu Jabus Belly MQ West Forked Rooms", SCENE_JABU_JABU, { //Events - EventAccess(&logic->JabuWestTentacle, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), + EventAccess(LOGIC_JABU_WEST_TENTACLE, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, Here(RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS, []{return logic->HasExplosives();}) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), @@ -302,13 +302,13 @@ void RegionTable_Init_JabuJabusBelly() { && ((logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS)))))), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return (logic->JabuNorthTentacle || logic->TakeDamage()) && logic->HasItem(RG_BRONZE_SCALE);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return (logic->Get(LOGIC_JABU_NORTH_TENTACLE) || logic->TakeDamage()) && logic->HasItem(RG_BRONZE_SCALE);}), }); areaTable[RR_JABU_JABUS_BELLY_MQ_PAST_OCTO] = Region("Jabu Jabus Belly MQ Past Octo", SCENE_JABU_JABU, { //Events //if a hover up to the path is added, this will want it's own room - EventAccess(&logic->LoweredJabuPath, []{return logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_FAIRY_SLINGSHOT);}), + EventAccess(LOGIC_JABU_LOWERED_PATH, []{return logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_FAIRY_SLINGSHOT);}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_COW, logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_FAIRY_SLINGSHOT)), @@ -326,16 +326,16 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE] = Region("Jabu Jabus Belly MQ Lift Room East Ledge", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->MQJabuLiftRoomCow), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_MQ_EAST_ROOM, []{return logic->JabuNorthTentacle;}), + Entrance(RR_JABU_JABUS_BELLY_MQ_EAST_ROOM, []{return logic->Get(LOGIC_JABU_NORTH_TENTACLE);}), }); areaTable[RR_JABU_JABUS_BELLY_MQ_EAST_ROOM] = Region("Jabu Jabus Belly MQ Boss Region", SCENE_JABU_JABU, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), @@ -365,7 +365,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_BOSS_ROOM] = Region("Jabu Jabus Belly Boss Room", SCENE_JABU_JABU_BOSS, { // Events //todo: add pot kill trick - EventAccess(&logic->JabuJabusBellyClear, []{return logic->CanKillEnemy(RE_BARINADE);}), + EventAccess(LOGIC_JABU_JABUS_BELLY_CLEAR, []{return logic->CanKillEnemy(RE_BARINADE);}), }, { // Locations LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_1, logic->CanBreakPots()), @@ -374,12 +374,12 @@ void RegionTable_Init_JabuJabusBelly() { LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_4, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_5, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_6, logic->CanBreakPots()), - LOCATION(RC_JABU_JABUS_BELLY_BARINADE_HEART, logic->JabuJabusBellyClear), - LOCATION(RC_BARINADE, logic->JabuJabusBellyClear), + LOCATION(RC_JABU_JABUS_BELLY_BARINADE_HEART, logic->Get(LOGIC_JABU_JABUS_BELLY_CLEAR)), + LOCATION(RC_BARINADE, logic->Get(LOGIC_JABU_JABUS_BELLY_CLEAR)), }, { // Exits Entrance(RR_JABU_JABUS_BELLY_BOSS_EXIT, []{return false;}), - Entrance(RR_ZORAS_FOUNTAIN, []{return logic->JabuJabusBellyClear;}, false), + Entrance(RR_ZORAS_FOUNTAIN, []{return logic->Get(LOGIC_JABU_JABUS_BELLY_CLEAR);}, false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp index d276fc418..590af4d93 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -18,7 +18,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_BEGINNING] = Region("Shadow Temple Beginning", SCENE_SHADOW_TEMPLE, { //Events - EventAccess(&logic->NutPot, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanJumpslashExceptHammer()), @@ -39,7 +39,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_FIRST_BEAMOS] = Region("Shadow Temple First Beamos", SCENE_SHADOW_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), //This fairy pot is only on 3DS + EventAccess(LOGIC_FAIRY_POT, []{return true;}), //This fairy pot is only on 3DS }, { //Locations LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanJumpslashExceptHammer()), @@ -48,7 +48,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_HUGE_PIT, []{return logic->HasExplosives() && logic->IsAdult && logic->SmallKeys(RR_SHADOW_TEMPLE, 1, 2);}), + Entrance(RR_SHADOW_TEMPLE_HUGE_PIT, []{return logic->HasExplosives() && logic->IsAdult && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 1);}), Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, []{return false;}), }); @@ -57,24 +57,24 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanJumpslashExceptHammer()), LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanJumpslashExceptHammer()), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, (ctx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->CanUse(RG_HOVER_BOOTS)) || logic->HasItem(RG_GORONS_BRACELET)), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, (ctx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->CanUse(RG_HOVER_BOOTS)) || logic->HasItem(RG_GORONS_BRACELET)), - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_SHADOW_TEMPLE_FREESTANDING_KEY, logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_BOMB_BAG) || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_SHADOW_FREESTANDING_KEY) && logic->CanUse(RG_BOMBCHU_5)))), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_FREESTANDING_KEY, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_BOMB_BAG) || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_SHADOW_FREESTANDING_KEY) && logic->CanUse(RG_BOMBCHU_5)))), LOCATION(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, logic->CanJumpslashExceptHammer()), - LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)) || (logic->IsAdult && logic->CanGroundJump())), + LOCATION(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_2, logic->CanBreakPots()), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_3, logic->CanBreakPots() && (ctx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->CanUse(RG_HOVER_BOOTS)) || logic->HasItem(RG_GORONS_BRACELET)), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_4, logic->CanBreakPots() && (ctx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->CanUse(RG_HOVER_BOOTS)) || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_3, logic->CanBreakPots() && (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_4, logic->CanBreakPots() && (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)), //We cannot repeat the MQ invisible blades trick for these hearts as the like-like does not respawn if the room is cleared LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_LEFT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_RIGHT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_PIT_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, []{return ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_SHADOW_TEMPLE, 3, 4);}), + Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, []{return ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3);}), }); areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Region("Shadow Temple Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, { @@ -82,15 +82,15 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, true), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2)), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives()), - LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, logic->CanUse(RG_LONGSHOT) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5)), + LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, logic->CanUse(RG_LONGSHOT) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_2, logic->CanBreakPots()), - LOCATION(RC_SHADOW_TEMPLE_SCARECROW_NORTH_HEART, logic->CanUse(RG_DISTANT_SCARECROW) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5)), - LOCATION(RC_SHADOW_TEMPLE_SCARECROW_SOUTH_HEART, logic->CanUse(RG_DISTANT_SCARECROW) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5)), + LOCATION(RC_SHADOW_TEMPLE_SCARECROW_NORTH_HEART, logic->CanUse(RG_DISTANT_SCARECROW) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), + LOCATION(RC_SHADOW_TEMPLE_SCARECROW_SOUTH_HEART, logic->CanUse(RG_DISTANT_SCARECROW) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, []{return logic->CanJumpslashExceptHammer() && logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}), + Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, []{return logic->CanJumpslashExceptHammer() && logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4);}), }); areaTable[RR_SHADOW_TEMPLE_BEYOND_BOAT] = Region("Shadow Temple Beyond Boat", SCENE_SHADOW_TEMPLE, {}, { @@ -112,7 +112,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_AFTER_SHIP_LOWER_HEART, (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DISTANT_SCARECROW) || (ctx->GetTrickOption(RT_SHADOW_STATUE) && logic->CanUse(RG_BOMBCHU_5))) && logic->CanUse(RG_SONG_OF_TIME) || (logic->CanUse(RG_DISTANT_SCARECROW) && logic->CanUse(RG_HOVER_BOOTS))), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, []{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DISTANT_SCARECROW) || (ctx->GetTrickOption(RT_SHADOW_STATUE) && logic->CanUse(RG_BOMBCHU_5))) && logic->SmallKeys(RR_SHADOW_TEMPLE, 5) && logic->CanUse(RG_HOVER_BOOTS);}) + Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, []{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DISTANT_SCARECROW) || (ctx->GetTrickOption(RT_SHADOW_STATUE) && logic->CanUse(RG_BOMBCHU_5))) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 5) && logic->CanUse(RG_HOVER_BOOTS);}) }); #pragma endregion @@ -138,7 +138,7 @@ void RegionTable_Init_ShadowTemple() { //Exits Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, []{return true;}), Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return Here(RR_SHADOW_TEMPLE_MQ_SPINNER_ROOM, []{return logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}) && (logic->CanUse(RG_HOVER_BOOTS) || Here(RR_SHADOW_TEMPLE_MQ_SPINNER_ROOM, []{return logic->CanUse(RG_FIRE_ARROWS);}) || (ctx->GetTrickOption(RT_SHADOW_MQ_GAP) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslashExceptHammer()));}), - Entrance(RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, []{return Here(RR_SHADOW_TEMPLE_MQ_SPINNER_ROOM, []{return logic->HasExplosives();}) && logic->SmallKeys(RR_SHADOW_TEMPLE, 6) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}), + Entrance(RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, []{return Here(RR_SHADOW_TEMPLE_MQ_SPINNER_ROOM, []{return logic->HasExplosives();}) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 6) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}), }); //Assumes we're in the "main" area and needed lens to enter. logic will need changes if a void warp puts us somewhere weird @@ -164,7 +164,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, []{return logic->HasExplosives() && logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}), + Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, []{return logic->HasExplosives() && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2);}), Entrance(RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM, []{return ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}), }); @@ -183,14 +183,14 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - Entrance(RR_SHADOW_TEMPLE_MQ_DOCK, []{return logic->ShadowShortcutBlock;}), + Entrance(RR_SHADOW_TEMPLE_MQ_DOCK, []{return logic->Get(LOGIC_SHADOW_SHORTCUT_BLOCK);}), //WARNING if there's any way past here to ship without already reaching the other side the key logic in this dungeon becomes Quantum }); //Room exists for if it's ever possible to go backwards or void warp into the middle of shadow areaTable[RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR] = Region("Shadow Temple MQ B2 to B3 Corridor", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}), + Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2);}), Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, []{return true;}), //bunnyhovers + lens lets you go from the very top of upper pit to the stationary invisible platform below quite easily }); @@ -226,30 +226,29 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM, []{return Here(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, []{return logic->CanJumpslash() || logic->HasExplosives();});}), - Entrance(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->SmallKeys(RR_SHADOW_TEMPLE, 3);}), + Entrance(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3);}), }); areaTable[RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM] = Region("Shadow Temple MQ Stone Umbrella Room", SCENE_SHADOW_TEMPLE, {}, { //Locations LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, true), - //Assuming the known setup for RT_SHADOW_UMBRELLA and RT_SHADOW_UMBRELLA_GS, probably possible without sword + shield. - //Handling the trick here instead of upper as using the block to climb is not a valid method for getting this skull without other tricks to use the block before it is intended - LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || - (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && ctx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD))), + LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || logic->CanGroundJump()), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_WEST_POT, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_EAST_POT, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_UPPER_UMBRELLA_SOUTH_POT, logic->CanUse(RG_BOOMERANG)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, []{return Here(RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM, []{return ctx->GetTrickOption(RT_VISIBLE_COLLISION) || logic->CanHitSwitch();});}), - //Assuming the known setup for RT_SHADOW_UMBRELLA, probably possible without sword + shield - Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_STONE_UMBRELLA, []{return logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)));}), + //Assuming the known setup for RT_SHADOW_UMBRELLA_HOVER, probably possible without sword + shield + Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_STONE_UMBRELLA, []{return ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || (logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD))));}), }); areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_STONE_UMBRELLA] = Region("Shadow Temple MQ Upper Stone Umbrella", SCENE_SHADOW_TEMPLE, {}, { //Locations LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, true), LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, true), + //Assuming the known setup for RT_SHADOW_UMBRELLA_HOVER and RT_SHADOW_UMBRELLA_GS, probably possible without sword + shield. + LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)), LOCATION(RC_SHADOW_TEMPLE_MQ_UPPER_UMBRELLA_NORTH_POT, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_UPPER_UMBRELLA_SOUTH_POT, logic->CanBreakPots()), }, { @@ -260,7 +259,7 @@ void RegionTable_Init_ShadowTemple() { //while the spikes here are annoying, they don't really stop you doing anything, so I'll assume either lens trick, lens to see them, or taking damage from them. Not hovers though as a new player won't see the threat without lens to react properly areaTable[RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM] = Region("Shadow Temple MQ Floor Spikes Room", SCENE_SHADOW_TEMPLE, { //Events //lens or trick is always required for hookshot targets. We handle it here to not complicate the RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_UPPER_DOOR logic - EventAccess(&logic->MQShadowFloorSpikeRupees, []{return (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && + EventAccess(LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES, []{return (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && //Upper door side high rupee needs (hookshot and redead kill(as either age) for chest and adult) or longshot. hovers can cross from the left side with a backflip but that would be a trick //East midair rupee needs (hookshot and(hover boots or jumpslash from the upper door platform)) or longshot. //Combined these are longshot or (IsAdult && hookshot && (CanJumpslash || (Hover Boots && Here(CanKillRedeads)))) @@ -272,9 +271,9 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM, []{return logic->MQShadowFloorSpikeRupees;}), + Entrance(RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM, []{return logic->Get(LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES);}), //We need to assume we can get here with or without the glass platforms - Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 4) && (logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && (logic->MQShadowFloorSpikeRupees || Here(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return logic->CanKillEnemy(RE_REDEAD);})))) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4) && (logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && (logic->Get(LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES) || Here(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return logic->CanKillEnemy(RE_REDEAD);})))) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}), }); areaTable[RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM] = Region("Shadow Temple MQ Stalfos Room", SCENE_SHADOW_TEMPLE, {}, { @@ -287,7 +286,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL] = Region("Shadow Temple MQ Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 4) && logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4) && logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_SHADOW_TEMPLE_MQ_WIND_HINT_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}), Entrance(RR_SHADOW_TEMPLE_MQ_B4_GIBDO_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}), }); @@ -304,7 +303,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_B4_GIBDO_ROOM] = Region("Shadow Temple MQ B4 Gibdo Room", SCENE_SHADOW_TEMPLE, { //Events - EventAccess(&logic->NutPot, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO)), @@ -316,20 +315,20 @@ void RegionTable_Init_ShadowTemple() { //Exits //child can make it using the wind strat Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, []{return (ctx->GetTrickOption(RT_SHADOW_MQ_WINDY_WALKWAY)) || logic->CanUse(RG_HOVER_BOOTS);}), - Entrance(RR_SHADOW_TEMPLE_MQ_DOCK, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 5);}), + Entrance(RR_SHADOW_TEMPLE_MQ_DOCK, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 5);}), }); areaTable[RR_SHADOW_TEMPLE_MQ_DOCK] = Region("Shadow Temple MQ Dock", SCENE_SHADOW_TEMPLE, { //Events - EventAccess(&logic->ShadowShortcutBlock, []{return logic->HasItem(RG_GORONS_BRACELET);}), + EventAccess(LOGIC_SHADOW_SHORTCUT_BLOCK, []{return logic->HasItem(RG_GORONS_BRACELET);}), }, { //Locations LOCATION(RC_SHADOW_TEMPLE_MQ_SCARECROW_NORTH_HEART, logic->CanUse(RG_DISTANT_SCARECROW)), LOCATION(RC_SHADOW_TEMPLE_MQ_SCARECROW_SOUTH_HEART, logic->CanUse(RG_DISTANT_SCARECROW)), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH, []{return logic->ShadowShortcutBlock;}), - Entrance(RR_SHADOW_TEMPLE_MQ_B4_GIBDO_ROOM, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 5);}), + Entrance(RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH, []{return logic->Get(LOGIC_SHADOW_SHORTCUT_BLOCK);}), + Entrance(RR_SHADOW_TEMPLE_MQ_B4_GIBDO_ROOM, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 5);}), //funnily enough, the wheel jump seems to be in logic as there's no strength requirement in N64 Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, []{return (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_ZELDAS_LULLABY);}), }); @@ -384,7 +383,7 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, []{return true;}), - Entrance(RR_SHADOW_TEMPLE_MQ_SPIKE_WALLS_ROOM, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 6);}), + Entrance(RR_SHADOW_TEMPLE_MQ_SPIKE_WALLS_ROOM, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 6);}), }); areaTable[RR_SHADOW_TEMPLE_MQ_SPIKE_WALLS_ROOM] = Region("Shadow Temple MQ Spike Walls Room", SCENE_SHADOW_TEMPLE, {}, { @@ -394,7 +393,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_BARICADE_POT, logic->CanBreakPots()), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 6) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}), + Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 6) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}), }); #pragma endregion @@ -409,15 +408,15 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_BOSS_ROOM] = Region("Shadow Temple Boss Room", SCENE_SHADOW_TEMPLE_BOSS, { // Events - EventAccess(&logic->ShadowTempleClear, []{return logic->CanKillEnemy(RE_BONGO_BONGO);}), + EventAccess(LOGIC_SHADOW_TEMPLE_CLEAR, []{return logic->CanKillEnemy(RE_BONGO_BONGO);}), }, { // Locations - LOCATION(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, logic->ShadowTempleClear), - LOCATION(RC_BONGO_BONGO, logic->ShadowTempleClear), + LOCATION(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, logic->Get(LOGIC_SHADOW_TEMPLE_CLEAR)), + LOCATION(RC_BONGO_BONGO, logic->Get(LOGIC_SHADOW_TEMPLE_CLEAR)), }, { // Exits Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, []{return false;}), - Entrance(RR_GRAVEYARD_WARP_PAD_REGION, []{return logic->ShadowTempleClear;}, false), + Entrance(RR_GRAVEYARD_WARP_PAD_REGION, []{return logic->Get(LOGIC_SHADOW_TEMPLE_CLEAR);}, false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index e2a13ecc1..207b9c76f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -29,7 +29,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHILD] = Region("Child Spirit Temple", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(&logic->NutCrate, []{return true;}), + EventAccess(LOGIC_NUT_CRATE, []{return true;}), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT))))), @@ -43,17 +43,17 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2, logic->CanBreakSmallCrates()), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}), + Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 1);}), }); areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) || (logic->TakeDamage() && (logic->CanJumpslashExceptHammer() || logic->HasProjectile(HasProjectileAge::Child))) || - (logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))), + (logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) || + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))), LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_POT_1, logic->CanBreakPots()), }, { //Exits @@ -64,46 +64,46 @@ void RegionTable_Init_SpiritTemple() { //Locations LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_ZELDAS_LULLABY)), LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslashExceptHammer())), - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3)), - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3)), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3)), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3)), LOCATION(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, logic->CanUse(RG_SONG_OF_TIME) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)))), LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}), + Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 1);}), }); areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Region("Spirit Temple Central Chamber", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && + LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)) && (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), - LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), + LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)) && (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY)), - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))), + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))), LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives() && logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_HOOKSHOT)) || - (logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) || - (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2))), - LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && + (logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) || + (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2))), + LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)) && ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) || - (ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_BOOMERANG)) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))), - LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), - LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + (ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_BOOMERANG)) || + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))), + LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, []{return logic->CanJumpslashExceptHammer() || logic->HasExplosives();}), - Entrance(RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS);}), + Entrance(RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS);}), Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, []{return true;}), // RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, []{return ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT);}), @@ -111,11 +111,11 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_OUTDOOR_HANDS] = Region("Spirit Temple Outdoor Hands", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_LONGSHOT) && logic->HasExplosives()) || logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)), - LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasExplosives()), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_LONGSHOT) && logic->HasExplosives()) || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasExplosives()), }, { //Exits - Entrance(RR_DESERT_COLOSSUS, []{return (logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)) || (logic->CanUse(RG_SILVER_GAUNTLETS) && ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->HasExplosives()) || logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)));}), + Entrance(RR_DESERT_COLOSSUS, []{return (logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)) || (logic->CanUse(RG_SILVER_GAUNTLETS) && ((logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->HasExplosives()) || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)));}), }); areaTable[RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Region("Spirit Temple Beyond Central Locked Door", SCENE_SPIRIT_TEMPLE, {}, { @@ -127,13 +127,14 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, logic->HasExplosives() && logic->CanUse(RG_SUNS_SONG)), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && (ctx->GetTrickOption(RT_SPIRIT_WALL) || logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_BOMBCHU_5) || ((logic->CanUse(RG_BOMB_BAG) || logic->CanUse(RG_NUTS) || logic->CanUse(RG_DINS_FIRE)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_MEGATON_HAMMER))));}), + Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && (ctx->GetTrickOption(RT_SPIRIT_WALL) || logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_BOMBCHU_5) || ((logic->CanUse(RG_BOMB_BAG) || logic->CanUse(RG_NUTS) || logic->CanUse(RG_DINS_FIRE)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_MEGATON_HAMMER))));}), }); areaTable[RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Region("Spirit Temple Beyond Final Locked Door", SCENE_SPIRIT_TEMPLE, {}, { //Locations LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && ((logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS)) || (logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT)))), - LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) && logic->CanAttack()) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), + LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) && (logic->CanJumpslash() || logic->HasExplosives() || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOOKSHOT))))) || + (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), LOCATION(RC_SPIRIT_TEMPLE_ADULT_CLIMB_LEFT_HEART, logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_SPIRIT_TEMPLE_ADULT_CLIMB_RIGHT_HEART, logic->CanUse(RG_HOOKSHOT)), }, { @@ -156,7 +157,7 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, true), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG)), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Spirit1FSilverRupees), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES)), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_3, logic->CanBreakPots()), @@ -171,10 +172,10 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_1F_WEST] = Region("Spirit Temple MQ 1F West", SCENE_SPIRIT_TEMPLE, { //Events //not technically a rusted switch, but a boulder through a wall, but is part of the same trick on N64 - EventAccess(&logic->MQSpiritCrawlBoulder, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), + EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->MQSpiritTimeTravelChest), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_SLUGMA_POT, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_LEFT_HEART, logic->CanHitEyeTargets()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_RIGHT_HEART, logic->CanHitEyeTargets()), @@ -182,7 +183,7 @@ void RegionTable_Init_SpiritTemple() { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}), Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}), - Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->IsChild && logic->MQSpiritCrawlBoulder;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->IsChild && logic->Get(LOGIC_SPIRIT_MQ_CRAWL_BOULDER);}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH] = Region("Spirit Temple MQ 1F Gibdo Room South", SCENE_SPIRIT_TEMPLE, {}, {}, { @@ -202,7 +203,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM] = Region("Spirit Temple Turntable Room", SCENE_SPIRIT_TEMPLE, { //Events //For non-fairy pot items, you can also get them with rang without killing the stalfos - EventAccess(&logic->FairyPot, []{return Here(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}), + EventAccess(LOGIC_FAIRY_POT, []{return Here(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}), }, { //Locations //implies logic->CanBreakPots() @@ -218,10 +219,10 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_NORTH] = Region("Spirit Temple MQ Map Room North", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(&logic->MQSpiritMapRoomEnemies, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE);}), + EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE);}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->MQSpiritMapRoomEnemies), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->Get(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES)), }, { //Exits //Stalfos room blocks you in with fire until you kill the stalfos, which won't spawn from behind the fire @@ -231,7 +232,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH] = Region("Spirit Temple MQ Map Room South", SCENE_SPIRIT_TEMPLE, { //Events //You can lure the keese over by aggroing them with dins if you use it as close to the torch keese as possible, but it's a trick as it's not intuitive and basically never comes up - EventAccess(&logic->MQSpiritMapRoomEnemies, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE, ED_BOOMERANG);}), + EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE, ED_BOOMERANG);}), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, true), @@ -244,13 +245,13 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH] = Region("Spirit Temple MQ West 1F Rusted Switch", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(&logic->MQSpiritTimeTravelChest, []{return logic->CanUse(RG_MEGATON_HAMMER);}), - EventAccess(&logic->MQSpiritCrawlBoulder, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), + EventAccess(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, {}, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild && logic->MQSpiritCrawlBoulder;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild && logic->Get(LOGIC_SPIRIT_MQ_CRAWL_BOULDER);}), //This tracks possible child access, if adult has not entered STATUE_ROOM. Certain Child Access is checked for separately as 7 Keys - Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 1);}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE] = Region("Spirit Temple MQ Under Like Like", SCENE_SPIRIT_TEMPLE, {}, { @@ -259,7 +260,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits //This covers adult access only, as child arrives here from the other side of this door - Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanHitSwitch();}), }); @@ -274,7 +275,7 @@ void RegionTable_Init_SpiritTemple() { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanHitSwitch();}), //This exit only governs child possible access, adult access starts on the other side so never checks this - Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 2);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2);}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM] = Region("Spirit Temple MQ Statue Room", SCENE_SPIRIT_TEMPLE, {}, { @@ -292,7 +293,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits //we check possible adult access directly in MQSpiritSharedBrokenWallRoom, so this exit only covers Certain Access - Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), //We can use Here instead of Shared here because adult will never need to rely on child access to reach this room, and adult access is Certain Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return Here(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->HasFireSource() || (ctx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME));});}), Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || logic->CanUse(RG_SONG_OF_TIME);}), @@ -311,12 +312,12 @@ void RegionTable_Init_SpiritTemple() { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}), //This door causes the Universes to merge as it requires 7 keys for both ages - Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE] = Region("Spirit Temple MQ East Iron Knuckle", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);}), }); @@ -335,13 +336,13 @@ void RegionTable_Init_SpiritTemple() { Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return true;}), //The block here is unusual in that it is a permanent flag, but reset anyway as child. This is because there's a check that would be blocked off by pushing them otherwise //It may be worth considering making this always temp in future so adult doesn't have the same issue - Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return logic->IsChild ? logic->CanUse(RG_SILVER_GAUNTLETS) : Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanUse(RG_SILVER_GAUNTLETS);});}), + Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return logic->IsChild ? logic->CanUse(RG_SILVER_GAUNTLETS) : Here(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH, []{return logic->CanUse(RG_SILVER_GAUNTLETS);});}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH] = Region("Spirit Temple MQ Block Room North", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Does not need to be shared as it's hard child locked, because adult pushing the block is a permanent flag that blocks the eye target and cannot be undone - LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->CanHitEyeTargets()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7) && logic->CanHitEyeTargets()), }, { //Exits //if going to RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH from here is ever relevant, there needs to be an event to handle the block @@ -359,36 +360,36 @@ void RegionTable_Init_SpiritTemple() { //We only need 4 keys, access to Shield hand and longshot to reach Gauntlets hand, as if we waste the 5th key we have given ourselves Gauntlets hand access through child climb //This exit handles that possibility as cleanly as possible without quantum logic, but will not survive glitch logic //logic->CanKillEnemy(RE_FLOORMASTER) is implied - Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && + Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanJumpslash() && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, []{return logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE));}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F] = Region("Spirit Temple MQ Three Suns Room 2F", SCENE_SPIRIT_TEMPLE, { //Events //implies logic->CanKillEnemy(RE_WALLMASTER). If we have lights, we can kill stalfos and wallmasters with bow - EventAccess(&logic->MQSpirit3SunsEnemies, []{return (logic->CanUse(RG_MIRROR_SHIELD) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}), + EventAccess(LOGIC_SPIRIT_MQ_3SUNS_ENEMIES, []{return (logic->CanUse(RG_MIRROR_SHIELD) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}), }, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, []{return logic->MQSpirit3SunsEnemies;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, []{return logic->Get(LOGIC_SPIRIT_MQ_3SUNS_ENEMIES);}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F] = Region("Spirit Temple MQ Three Suns Room 1F", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, []{return logic->MQSpirit3SunsEnemies;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, []{return logic->Get(LOGIC_SPIRIT_MQ_3SUNS_ENEMIES);}), Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return true;}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_1F_EAST] = Region("Spirit Temple MQ 1F East", SCENE_SPIRIT_TEMPLE, { //Events //Assumes RR_SPIRIT_TEMPLE_MQ_LOBBY access - EventAccess(&logic->Spirit1FSilverRupees, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_SPIRIT_1F_SILVER_RUPEES, []{return logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_POT_1, logic->CanBreakPots()), @@ -398,7 +399,7 @@ void RegionTable_Init_SpiritTemple() { Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanUse(RG_MEGATON_HAMMER);}), Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_MQ_LEEVER_ROOM, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_LEEVER_ROOM] = Region("Spirit Temple MQ Leever Room", SCENE_SPIRIT_TEMPLE, {}, { @@ -412,7 +413,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM] = Region("Spirit Temple MQ Symphony Room", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), //Implies CanPassEnemy(RE_MOBLIN_CHIEF) Entrance(RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY);}), }); @@ -432,9 +433,9 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME);}), - Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6);}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM] = Region("Spirit Temple MQ SoT Sun Room", SCENE_SPIRIT_TEMPLE, {}, { @@ -457,7 +458,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE] = Region("Spirit Temple MQ East Iron Knuckle", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, []{return Here(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), + Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, []{return Here(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Region("Spirit Temple MQ Mirror Shield Hand", SCENE_SPIRIT_TEMPLE, {}, { @@ -497,7 +498,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }); @@ -555,15 +556,15 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BOSS_ROOM] = Region("Spirit Temple Boss Room", SCENE_SPIRIT_TEMPLE_BOSS, { // Events - EventAccess(&logic->SpiritTempleClear, []{return logic->CanKillEnemy(RE_TWINROVA);}), + EventAccess(LOGIC_SPIRIT_TEMPLE_CLEAR, []{return logic->CanKillEnemy(RE_TWINROVA);}), }, { // Locations - LOCATION(RC_SPIRIT_TEMPLE_TWINROVA_HEART, logic->SpiritTempleClear), - LOCATION(RC_TWINROVA, logic->SpiritTempleClear), + LOCATION(RC_SPIRIT_TEMPLE_TWINROVA_HEART, logic->Get(LOGIC_SPIRIT_TEMPLE_CLEAR)), + LOCATION(RC_TWINROVA, logic->Get(LOGIC_SPIRIT_TEMPLE_CLEAR)), }, { // Exits Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return false;}), - Entrance(RR_DESERT_COLOSSUS, []{return logic->SpiritTempleClear;}, false), + Entrance(RR_DESERT_COLOSSUS, []{return logic->Get(LOGIC_SPIRIT_TEMPLE_CLEAR);}, false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp index 03cc44645..aee55c972 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp @@ -19,38 +19,38 @@ void RegionTable_Init_WaterTemple() { //Water Temple logic currently assumes that the locked door leading to the upper water raising location is unlocked from the start areaTable[RR_WATER_TEMPLE_LOBBY] = Region("Water Temple Lobby", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MAIN_LEVEL_2_POT_1, logic->CanBreakPots() && (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)))), - LOCATION(RC_WATER_TEMPLE_MAIN_LEVEL_2_POT_2, logic->CanBreakPots() && (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)))), + LOCATION(RC_WATER_TEMPLE_MAIN_LEVEL_2_POT_1, logic->CanBreakPots() && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)))), + LOCATION(RC_WATER_TEMPLE_MAIN_LEVEL_2_POT_2, logic->CanBreakPots() && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)))), }, { //Exits Entrance(RR_WATER_TEMPLE_ENTRYWAY, []{return true;}), - Entrance(RR_WATER_TEMPLE_EAST_LOWER, []{return logic->CanWaterTempleLowFromHigh || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && (logic->CanUse(RG_IRON_BOOTS) || (logic->CanUse(RG_LONGSHOT) && ctx->GetTrickOption(RT_WATER_LONGSHOT_TORCH))));}), - Entrance(RR_WATER_TEMPLE_NORTH_LOWER, []{return logic->CanWaterTempleLowFromHigh || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}), - Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, []{return logic->CanWaterTempleLowFromHigh && logic->HasExplosives() && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}), - Entrance(RR_WATER_TEMPLE_WEST_LOWER, []{return logic->CanWaterTempleLowFromHigh && logic->HasItem(RG_GORONS_BRACELET) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}), - Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, []{return logic->CanWaterTempleLowFromHigh && logic->SmallKeys(RR_WATER_TEMPLE, 5);}), - Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, []{return (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle) && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}), - Entrance(RR_WATER_TEMPLE_EAST_MIDDLE, []{return (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16)) && logic->CanUse(RG_HOOKSHOT);}), - Entrance(RR_WATER_TEMPLE_WEST_MIDDLE, []{return logic->CanWaterTempleMiddle;}), + Entrance(RR_WATER_TEMPLE_EAST_LOWER, []{return logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && (logic->CanUse(RG_IRON_BOOTS) || (logic->CanUse(RG_LONGSHOT) && ctx->GetTrickOption(RT_WATER_LONGSHOT_TORCH))));}), + Entrance(RR_WATER_TEMPLE_NORTH_LOWER, []{return logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}), + Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, []{return logic->Get(LOGIC_WATER_LOW_FROM_HIGH) && logic->HasExplosives() && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}), + Entrance(RR_WATER_TEMPLE_WEST_LOWER, []{return logic->Get(LOGIC_WATER_LOW_FROM_HIGH) && logic->HasItem(RG_GORONS_BRACELET) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}), + Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, []{return logic->Get(LOGIC_WATER_LOW_FROM_HIGH) && logic->SmallKeys(SCENE_WATER_TEMPLE, 5);}), + Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, []{return (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE)) && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}), + Entrance(RR_WATER_TEMPLE_EAST_MIDDLE, []{return (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16)) && logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_WATER_TEMPLE_WEST_MIDDLE, []{return logic->Get(LOGIC_WATER_MIDDLE);}), Entrance(RR_WATER_TEMPLE_HIGH_WATER, []{return logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DAMAGE_BOOST) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage()));}), - Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, []{return (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_WATER_CENTRAL_BOW) && (logic->IsAdult || logic->CanWaterTempleMiddle)));}), - Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, []{return logic->CanWaterTempleHigh && logic->SmallKeys(RR_WATER_TEMPLE, 4);}), - Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, []{return (logic->CanWaterTempleHigh && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, []{return (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE)) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_WATER_CENTRAL_BOW) && (logic->IsAdult || logic->Get(LOGIC_WATER_MIDDLE))));}), + Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, []{return logic->Get(LOGIC_WATER_HIGH) && logic->SmallKeys(SCENE_WATER_TEMPLE, 4);}), + Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, []{return (logic->Get(LOGIC_WATER_HIGH) && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS));}), }); areaTable[RR_WATER_TEMPLE_EAST_LOWER] = Region("Water Temple East Lower", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->CanWaterTempleLowFromHigh, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_WATER_LOW_FROM_HIGH, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_TORCH_POT_1, logic->CanBreakPots() && (logic->CanWaterTempleLowFromHigh || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)))), - LOCATION(RC_WATER_TEMPLE_TORCH_POT_2, logic->CanBreakPots() && (logic->CanWaterTempleLowFromHigh || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)))), + LOCATION(RC_WATER_TEMPLE_TORCH_POT_1, logic->CanBreakPots() && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)))), + LOCATION(RC_WATER_TEMPLE_TORCH_POT_2, logic->CanBreakPots() && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)))), }, { //Exits - Entrance(RR_WATER_TEMPLE_LOBBY, []{return logic->CanWaterTempleLowFromHigh || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}), - Entrance(RR_WATER_TEMPLE_MAP_ROOM, []{return logic->CanWaterTempleHigh;}), - Entrance(RR_WATER_TEMPLE_CRACKED_WALL, []{return logic->CanWaterTempleMiddle || (logic->CanWaterTempleHigh && logic->CanWaterTempleLowFromHigh && ((logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_WATER_CRACKED_WALL_HOVERS)) || ctx->GetTrickOption(RT_WATER_CRACKED_WALL)));}), - Entrance(RR_WATER_TEMPLE_TORCH_ROOM, []{return logic->CanWaterTempleLowFromHigh && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}), + Entrance(RR_WATER_TEMPLE_LOBBY, []{return logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}), + Entrance(RR_WATER_TEMPLE_MAP_ROOM, []{return logic->Get(LOGIC_WATER_HIGH);}), + Entrance(RR_WATER_TEMPLE_CRACKED_WALL, []{return logic->Get(LOGIC_WATER_MIDDLE) || (logic->Get(LOGIC_WATER_HIGH) && logic->Get(LOGIC_WATER_LOW_FROM_HIGH) && ((logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_WATER_CRACKED_WALL_HOVERS)) || ctx->GetTrickOption(RT_WATER_CRACKED_WALL)));}), + Entrance(RR_WATER_TEMPLE_TORCH_ROOM, []{return logic->Get(LOGIC_WATER_LOW_FROM_HIGH) && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}), }); areaTable[RR_WATER_TEMPLE_MAP_ROOM] = Region("Water Temple Map Room", SCENE_WATER_TEMPLE, {}, { @@ -80,15 +80,15 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_NORTH_LOWER] = Region("Water Temple North Lower", SCENE_WATER_TEMPLE, {}, {}, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, []{return true;}), - Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, []{return (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_BK_REGION) && logic->CanUse(RG_HOVER_BOOTS))) && logic->SmallKeys(RR_WATER_TEMPLE, 4);}), + Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, []{return (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_BK_REGION) && logic->CanUse(RG_HOVER_BOOTS))) && logic->SmallKeys(SCENE_WATER_TEMPLE, 4);}), }); areaTable[RR_WATER_TEMPLE_BOULDERS_LOWER] = Region("Water Temple Boulders Lower", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanUse(RG_LONGSHOT) || Here(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return (logic->IsAdult && logic->HookshotOrBoomerang()) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT));})), + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanUse(RG_LONGSHOT)), }, { //Exits - Entrance(RR_WATER_TEMPLE_NORTH_LOWER, []{return logic->SmallKeys(RR_WATER_TEMPLE, 4);}), + Entrance(RR_WATER_TEMPLE_NORTH_LOWER, []{return logic->SmallKeys(SCENE_WATER_TEMPLE, 4);}), Entrance(RR_WATER_TEMPLE_BLOCK_ROOM, []{return true;}), Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP))) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_IRON_BOOTS));}), }); @@ -109,16 +109,19 @@ void RegionTable_Init_WaterTemple() { Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return true;}), }); - areaTable[RR_WATER_TEMPLE_BOULDERS_UPPER] = Region("Water Temple Boulders Upper", SCENE_WATER_TEMPLE, {}, {}, { + areaTable[RR_WATER_TEMPLE_BOULDERS_UPPER] = Region("Water Temple Boulders Upper", SCENE_WATER_TEMPLE, {}, { + //Locations + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, (logic->IsAdult && logic->HookshotOrBoomerang()) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), + }, { //Exits Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, []{return true;}), Entrance(RR_WATER_TEMPLE_JETS_ROOM, []{return logic->IsAdult;}), - Entrance(RR_WATER_TEMPLE_BOSS_KEY_ROOM, []{return (logic->CanUse(RG_IRON_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_WATER_BK_JUMP_DIVE))) && logic->SmallKeys(RR_WATER_TEMPLE, 5);}), + Entrance(RR_WATER_TEMPLE_BOSS_KEY_ROOM, []{return (logic->CanUse(RG_IRON_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_WATER_BK_JUMP_DIVE))) && logic->SmallKeys(SCENE_WATER_TEMPLE, 5);}), }); areaTable[RR_WATER_TEMPLE_BOSS_KEY_ROOM] = Region("Water Temple Boss Key Room", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, true), @@ -126,7 +129,7 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_BOSS_KEY_POT_2, logic->CanBreakPots()), }, { //Exits - Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return (logic->CanUse(RG_IRON_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_WATER_BK_JUMP_DIVE)) || logic->IsChild || logic->HasItem(RG_SILVER_SCALE)) && logic->SmallKeys(RR_WATER_TEMPLE, 5);}), + Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return (logic->CanUse(RG_IRON_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_WATER_BK_JUMP_DIVE)) || logic->IsChild || logic->HasItem(RG_SILVER_SCALE)) && logic->SmallKeys(SCENE_WATER_TEMPLE, 5);}), }); areaTable[RR_WATER_TEMPLE_SOUTH_LOWER] = Region("Water Temple South Lower", SCENE_WATER_TEMPLE, {}, { @@ -149,8 +152,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Region("Water Temple Dragon Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_BOMBCHU_5))) || (logic->IsChild && ctx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5)))) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))) || - Here(RR_WATER_TEMPLE_RIVER, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW) && ((ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))) || ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE));})), + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_BOMBCHU_5))) || (logic->IsChild && ctx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5)))) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)))), }, { //Exits Entrance(RR_WATER_TEMPLE_WEST_LOWER, []{return true;}), @@ -158,17 +160,17 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER] = Region("Water Temple Central Pillar Lower", SCENE_WATER_TEMPLE, {}, {}, { //Exits - Entrance(RR_WATER_TEMPLE_LOBBY, []{return logic->SmallKeys(RR_WATER_TEMPLE, 5);}), + Entrance(RR_WATER_TEMPLE_LOBBY, []{return logic->SmallKeys(SCENE_WATER_TEMPLE, 5);}), Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, []{return logic->CanUse(RG_HOOKSHOT);}), - Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, []{return logic->CanWaterTempleMiddle && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40;}), + Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, []{return logic->Get(LOGIC_WATER_MIDDLE) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40;}), }); areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Region("Water Temple Central Pillar Upper", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->CanWaterTempleMiddle, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_WATER_MIDDLE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, logic->CanUse(RG_LONGSHOT) || (((ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(RR_WATER_TEMPLE, 5))) || (ctx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->CanWaterTempleHigh && logic->HookshotOrBoomerang())), + LOCATION(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, logic->CanUse(RG_LONGSHOT) || (((ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(SCENE_WATER_TEMPLE, 5))) || (ctx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->Get(LOGIC_WATER_HIGH) && logic->HookshotOrBoomerang())), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, []{return true;}), @@ -202,7 +204,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_HIGH_WATER] = Region("Water Temple High Water", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->CanWaterTempleHigh, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_WATER_HIGH, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, {}, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, []{return true;}), @@ -210,9 +212,9 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BLOCK_CORRIDOR] = Region("Water Temple Block Corridor", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle)), - LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_1, logic->CanBreakPots() && logic->HasItem(RG_GORONS_BRACELET) && (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle)), - LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_2, logic->CanBreakPots() && logic->HasItem(RG_GORONS_BRACELET) && (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle)), + LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE))), + LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_1, logic->CanBreakPots() && logic->HasItem(RG_GORONS_BRACELET) && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE))), + LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_2, logic->CanBreakPots() && logic->HasItem(RG_GORONS_BRACELET) && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE))), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, []{return logic->CanUse(RG_HOOKSHOT);}), @@ -223,8 +225,8 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_RANG_FALLING_PLATFORM_GS) && logic->IsChild && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT))), }, { //Exits - Entrance(RR_WATER_TEMPLE_LOBBY, []{return logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_WATER_TEMPLE, 4);}), - Entrance(RR_WATER_TEMPLE_DRAGON_PILLARS_ROOM, []{return logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_WATER_TEMPLE, 5);}), + Entrance(RR_WATER_TEMPLE_LOBBY, []{return logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(SCENE_WATER_TEMPLE, 4);}), + Entrance(RR_WATER_TEMPLE_DRAGON_PILLARS_ROOM, []{return logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(SCENE_WATER_TEMPLE, 5);}), }); areaTable[RR_WATER_TEMPLE_DRAGON_PILLARS_ROOM] = Region("Water Temple Dragon Pillars Room", SCENE_WATER_TEMPLE, {}, { @@ -262,6 +264,7 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_RIVER_HEART_2, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_WATER_TEMPLE_RIVER_HEART_3, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_WATER_TEMPLE_RIVER_HEART_4, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24) || logic->HasItem(RG_BRONZE_SCALE)), + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->IsAdult && logic->CanUse(RG_FAIRY_BOW) && ((ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))) || ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE))), }, { //Exits Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, []{return (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}), @@ -269,7 +272,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_PRE_BOSS_ROOM] = Region("Water Temple Pre Boss Room", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { // Locations LOCATION(RC_WATER_TEMPLE_MAIN_LEVEL_1_POT_1, logic->CanBreakPots()), @@ -310,10 +313,10 @@ void RegionTable_Init_WaterTemple() { //A special entry as we can't set it to high after entering at a lower height Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH, []{return logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT));}), Entrance(RR_WATER_TEMPLE_MQ_LIZALFOS_HALLWAY, []{return (logic->MQWaterLevel(WL_MID) || (logic->MQWaterLevel(WL_HIGH_OR_MID) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16)) && logic->HasItem(RG_BRONZE_SCALE);}), - Entrance(RR_WATER_TEMPLE_MQ_B1_GATE_SWITCH, []{return logic->MQWaterB1Switch && (logic->MQWaterLevel(WL_LOW) || ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24) && logic->HasItem(RG_BRONZE_SCALE)));}), - Entrance(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM, []{return logic->MQWaterB1Switch && ((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))));}), + Entrance(RR_WATER_TEMPLE_MQ_B1_GATE_SWITCH, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && (logic->MQWaterLevel(WL_LOW) || ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24) && logic->HasItem(RG_BRONZE_SCALE)));}), + Entrance(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && ((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))));}), //Adult needs to jump in instead of dive for swim access, but you just hold forward. RT_WATER_BK_REGION Isn't relevant unless the Dark Link loop can be done without longshot with other tricks - Entrance(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM, []{return logic->MQWaterB1Switch && ((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT))) && (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_BK_REGION) && logic->CanUse(RG_HOVER_BOOTS)));}), + Entrance(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && ((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT))) && (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_BK_REGION) && logic->CanUse(RG_HOVER_BOOTS)));}), }); //This region specifically covers the topmost platform around central pillar @@ -327,7 +330,7 @@ void RegionTable_Init_WaterTemple() { //Jumping across is possible but a trick due to the janky ledge Entrance(RR_WATER_TEMPLE_MQ_HIGH_EMBLEM, []{return logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}), //room access is (logic->IsAdult || (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))) - Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, []{return logic->SmallKeys(RR_WATER_TEMPLE, 1) && logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, []{return logic->SmallKeys(SCENE_WATER_TEMPLE, 1) && logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_LONGSHOT);}), //this swimless jump with irons may be a trick as you have to put irons on quite late. Entrance(RR_WATER_TEMPLE_MQ_LIZALFOS_HALLWAY, []{return (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->MQWaterLevel(WL_LOW_OR_MID);}), }); @@ -346,8 +349,8 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_HIGH_EMBLEM] = Region("Water Temple MQ High Emblem", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->ReachedWaterHighEmblem, []{return true;}), - EventAccess(&logic->CanWaterTempleHigh, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_WATER_REACHED_HIGH_EMBLEM, []{return true;}), + EventAccess(LOGIC_WATER_HIGH, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, {}, { //Exits Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, []{return true;}), @@ -372,10 +375,10 @@ void RegionTable_Init_WaterTemple() { //Events //if we can't reach these, we can't move the water at all, so no need to specify level or account for WL_LOW access here //review is some way to play ocarina underwater exists - EventAccess(&logic->CouldWaterTempleLow, []{return true;}), - EventAccess(&logic->CanWaterTempleLowFromHigh, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_WATER_COULD_LOW, []{return true;}), + EventAccess(LOGIC_WATER_LOW_FROM_HIGH, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), //Reserved for glitches/tricks that could do this - //EventAccess(&logic->CanWaterTempleLowFromMid, []{return false;}), + //EventAccess(LOGIC_WATER_LOW_FROM_MIDDLE, []{return false;}), }, { //Locations LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->MQWaterLevel(WL_HIGH) && logic->HasFireSource() && logic->CanUse(RG_HOOKSHOT)), @@ -398,48 +401,48 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_1F] = Region("Water Temple MQ Central Pillar 1F", SCENE_WATER_TEMPLE, { //Events //This is harder than the other possibilities as you have to move between shots on top of the extra range, but there's basically no universe this should matter. - EventAccess(&logic->MQWaterB1Switch, []{return ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS);}), + EventAccess(LOGIC_WATER_MQ_B1_SWITCH, []{return ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS);}), }, {}, { //Exits Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH, []{return logic->MQWaterLevel(WL_HIGH) && ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && logic->HasItem(RG_BRONZE_SCALE);}), //I don't know if this FW trick can ever matter but maybe it's needed to get child to CENTRAL_2F or something Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_2F, []{return logic->CanUse(RG_HOOKSHOT) || (logic->MQWaterLevel(WL_MID) && ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && logic->HasItem(RG_BRONZE_SCALE));}), //if the gate is open, you sink straight in, so you can't climb up this way in logic without swimming - Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, []{return logic->MQWaterOpenedPillarB1 && logic->MQWaterLevel(WL_HIGH_OR_MID) && ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}), + Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, []{return logic->Get(LOGIC_WATER_MQ_B1_OPENED_PILLAR) && logic->MQWaterLevel(WL_HIGH_OR_MID) && ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}), }); //If we enter here in WL_HIGH, go to RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH instead, Assumes WL_MID_OR_LOW areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_2F] = Region("Water Temple MQ Central Pillar 2F", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->CouldWaterTempleMiddle, []{return true;}), - EventAccess(&logic->CanWaterTempleMiddle, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_WATER_COULD_MIDDLE, []{return true;}), + EventAccess(LOGIC_WATER_MIDDLE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), //It's possible to do this even on low water, but more awkward. I'm not sure if it's even possible for it to be relevant though. - EventAccess(&logic->MQWaterOpenedPillarB1, []{return ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS);}), + EventAccess(LOGIC_WATER_MQ_B1_OPENED_PILLAR, []{return ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS);}), //this could theoretically matter once OI and equip swap is in logic, as one age may be able to get here dry and not wet, and the other may not be able to OI, but as you can OI with hookshot it probably never happens - //EventAccess(&logic->MQWaterPillarSoTBlock, []{return logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME);}), + //EventAccess(LOGIC_WATER_MQ_PILLAR_SOT_BLOCK, []{return logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME);}), }, {}, { //Exits Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH, []{return logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_FARORES_WIND) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}), - Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, []{return logic->MQWaterOpenedPillarB1 && logic->MQWaterLevel(WL_MID) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}), + Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, []{return logic->Get(LOGIC_WATER_MQ_B1_OPENED_PILLAR) && logic->MQWaterLevel(WL_MID) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}), }); areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH] = Region("Water Temple MQ Central Pillar High", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->MQWaterOpenedPillarB1, []{return ((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_DINS_FIRE)) || (ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS))) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslash()));}), + EventAccess(LOGIC_WATER_MQ_B1_OPENED_PILLAR, []{return ((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_DINS_FIRE)) || (ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS))) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslash()));}), }, { //Locations LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_UPPER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_UPPER_CRATE_2, logic->CanBreakCrates()), }, { //Exits - Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, []{return logic->MQWaterB1Switch && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}), + Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}), }); //Assuming tunic and irons was checked on entry areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1] = Region("Water Temple MQ Central Pillar B1", SCENE_WATER_TEMPLE, {}, {}, { //Exits //Can't know water level, so we'll just assume any possibility and skip to MAIN - Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->MQWaterOpenedPillarB1 && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE);}), + Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->Get(LOGIC_WATER_MQ_B1_OPENED_PILLAR) && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE);}), //Child needs to release irons for height to push down the larger "peg", however they can push the lower one down by climbing and then hit the switch through the larger peg, but it's a trick Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1_FINAL, []{return ((logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE)));}), }); @@ -553,27 +556,27 @@ void RegionTable_Init_WaterTemple() { //This room exists to hold the wonderitems that drop from the emblems here. Specifically this assumes you are standing on the final ledge areaTable[RR_WATER_TEMPLE_MQ_WATERFALL] = Region("Water Temple Waterfall", SCENE_WATER_TEMPLE, {}, {}, { //Exits - Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, []{return logic->SmallKeys(RR_WATER_TEMPLE, 1) && logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, []{return logic->SmallKeys(SCENE_WATER_TEMPLE, 1) && logic->CanUse(RG_LONGSHOT);}), Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT, []{return true;}), - Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, []{return (logic->MQWaterStalfosPit && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS);}), - Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, []{return logic->MQWaterStalfosPit && logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, []{return (logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, []{return logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && logic->CanUse(RG_LONGSHOT);}), }); areaTable[RR_WATER_TEMPLE_MQ_STALFOS_PIT] = Region("Water Temple MQ Stalfos Pit", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->MQWaterStalfosPit, []{return ((logic->IsAdult && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3, false, true)) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->CanKillEnemy(RE_STALFOS, ED_BOMB_THROW, true, 3, false, true)));}), + EventAccess(LOGIC_WATER_MQ_STALFOS_PIT, []{return ((logic->IsAdult && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3, false, true)) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->CanKillEnemy(RE_STALFOS, ED_BOMB_THROW, true, 3, false, true)));}), }, {}, { //Exits - Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, []{return logic->MQWaterStalfosPit && logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8);}), - Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, []{return (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && (logic->CanUse(RG_HOVER_BOOTS) || logic->MQWaterStalfosPit));}), - Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, []{return logic->MQWaterStalfosPit && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, []{return logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8);}), + Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, []{return (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && (logic->CanUse(RG_HOVER_BOOTS) || logic->Get(LOGIC_WATER_MQ_STALFOS_PIT)));}), + Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, []{return logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && logic->CanUse(RG_HOOKSHOT);}), }); //also includes the suns fairy in the middle areaTable[RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS] = Region("Water Temple MQ Stalfos Pit Pots", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), - EventAccess(&logic->NutPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations LOCATION(RC_WATER_TEMPLE_MQ_STALFOS_PIT_SOUTH_POT, logic->CanBreakPots()), @@ -582,9 +585,9 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits - Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, []{return logic->MQWaterStalfosPit && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT));}), + Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, []{return logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT));}), Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT, []{return true;}), - Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, []{return logic->MQWaterStalfosPit && logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, []{return logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && logic->CanUse(RG_HOOKSHOT);}), }); //specifically the area past the spikes @@ -603,7 +606,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_AFTER_DARK_LINK] = Region("Water Temple MQ After Dark Link", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_WATER_TEMPLE_MQ_AFTER_DARK_LINK_POT_1, logic->CanBreakPots()), @@ -625,7 +628,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_RIVER_POTS] = Region("Water Temple MQ River Pots", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->FairyPot, []{return true;}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations LOCATION(RC_WATER_TEMPLE_MQ_RIVER_POT_1, logic->CanBreakPots()), @@ -657,7 +660,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE] = Region("Water Temple MQ Dragon Room Alcove", SCENE_WATER_TEMPLE, { //Events - EventAccess(&logic->MQWaterDragonTorches, []{return logic->HasFireSource();}), + EventAccess(LOGIC_WATER_MQ_DRAGON_TORCHES, []{return logic->HasFireSource();}), }, { //Locations @@ -684,7 +687,7 @@ void RegionTable_Init_WaterTemple() { Entrance(RR_WATER_TEMPLE_MQ_RIVER_POTS, []{return logic->CanUse(RG_LONGSHOT);}), Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, []{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, []{return logic->HasItem(RG_SILVER_SCALE);}), - Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->MQWaterDragonTorches;}), + Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->Get(LOGIC_WATER_MQ_DRAGON_TORCHES);}), }); areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH] = Region("Water Temple MQ Boss Key Room Switch", SCENE_WATER_TEMPLE, {}, { @@ -726,27 +729,27 @@ void RegionTable_Init_WaterTemple() { //Events //If the water is low, the switch is underwater and needs irons to press, otherwise, the water is too low to climb up and you need irons to hookshot a target //If a glitch clips through the gate on low, have it logically press the switch and let entrance logic enter - EventAccess(&logic->MQWaterB1Switch, []{return logic->CanUse(RG_IRON_BOOTS);}), + EventAccess(LOGIC_WATER_MQ_B1_SWITCH, []{return logic->CanUse(RG_IRON_BOOTS);}), }, {}, { //Exits - Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->MQWaterB1Switch && (logic->MQWaterLevel(WL_LOW) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16));}), + Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && (logic->MQWaterLevel(WL_LOW) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16));}), Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && (logic->MQWaterLevel(WL_LOW) || logic->WaterTimer() >= 24);}) }); areaTable[RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM] = Region("Water Temple MQ Triangle Torch Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_1, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_2, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_3, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_4, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_5, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_6, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_1, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_2, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_3, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_4, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_5, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_6, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), }, { //Exits - Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->MQWaterB1Switch && ((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_GOLDEN_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))));}), - Entrance(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE, []{return logic->CanUse(RG_FIRE_ARROWS) && ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->CanUse(RG_LONGSHOT) && Here(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE, []{return logic->ScarecrowsSong();})));}) + Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && ((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_GOLDEN_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))));}), + Entrance(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE, []{return logic->CanUse(RG_FIRE_ARROWS) && ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->CanUse(RG_LONGSHOT) && Here(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM, []{return logic->ScarecrowsSong();})));}) }); areaTable[RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE] = Region("Water Temple MQ Triangle Torch Cage", SCENE_WATER_TEMPLE, {}, { @@ -777,7 +780,7 @@ void RegionTable_Init_WaterTemple() { { //Exits //we can backflip over the spikes, but land in water. - Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->MQWaterB1Switch && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && (logic->CanUse(RG_LONGSHOT) || logic->HasItem(RG_BRONZE_SCALE));}), + Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && (logic->CanUse(RG_LONGSHOT) || logic->HasItem(RG_BRONZE_SCALE));}), //Child can use the crate to get the height to make it with hovers, but it's annoyingly tight so would be a trick Entrance(RR_WATER_TEMPLE_MQ_SINGLE_STALFOS_ROOM, []{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && //We're putting the requirement to get out of the water here as the scarecrow method in includes hook which satisfies it @@ -847,15 +850,15 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BOSS_ROOM] = Region("Water Temple Boss Room", SCENE_WATER_TEMPLE_BOSS, { // Events - EventAccess(&logic->WaterTempleClear, []{return logic->CanKillEnemy(RE_MORPHA);}), + EventAccess(LOGIC_WATER_TEMPLE_CLEAR, []{return logic->CanKillEnemy(RE_MORPHA);}), }, { // Locations - LOCATION(RC_WATER_TEMPLE_MORPHA_HEART, logic->WaterTempleClear), - LOCATION(RC_MORPHA, logic->WaterTempleClear), + LOCATION(RC_WATER_TEMPLE_MORPHA_HEART, logic->Get(LOGIC_WATER_TEMPLE_CLEAR)), + LOCATION(RC_MORPHA, logic->Get(LOGIC_WATER_TEMPLE_CLEAR)), }, { // Exits Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, []{return false;}), - Entrance(RR_LAKE_HYLIA, []{return logic->WaterTempleClear;}, false), + Entrance(RR_LAKE_HYLIA, []{return logic->Get(LOGIC_WATER_TEMPLE_CLEAR);}, false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index b9525386c..09ae6443f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -18,13 +18,13 @@ void RegionTable_Init_CastleGrounds() { areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), - EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}), - EventAccess(&logic->BugRock, []{return true;}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_BUG_ROCK, []{return true;}), }, { //Locations LOCATION(RC_HC_MALON_EGG, true), - LOCATION(RC_HC_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)), + LOCATION(RC_HC_GS_TREE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanBonkTrees()), LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), @@ -33,6 +33,16 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE, true), LOCATION(RC_HC_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_HC_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_HC_GROTTO_TREE, logic->CanBonkTrees()), + LOCATION(RC_HC_NL_TREE_1, false), + LOCATION(RC_HC_NL_TREE_2, false), + LOCATION(RC_HC_SKULLTULA_TREE, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_1, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_2, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_3, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_4, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_5, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_6, logic->CanBonkTrees()), }, { //Exits Entrance(RR_CASTLE_GROUNDS, []{return true;}), @@ -69,9 +79,9 @@ void RegionTable_Init_CastleGrounds() { areaTable[RR_HC_STORMS_GROTTO_BEHIND_WALLS] = Region("HC Storms Grotto Behind Walls", SCENE_GROTTOS, { //Events - EventAccess(&logic->NutPot, []{return true;}), - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), - EventAccess(&logic->WanderingBugs, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_WANDERING_BUGS, []{return true;}), }, { //Locations LOCATION(RC_HC_GS_STORMS_GROTTO, logic->HookshotOrBoomerang()), @@ -89,7 +99,7 @@ void RegionTable_Init_CastleGrounds() { areaTable[RR_GANONS_CASTLE_GROUNDS] = Region("Ganon's Castle Grounds", SCENE_OUTSIDE_GANONS_CASTLE, { //Events - EventAccess(&logic->BuiltRainbowBridge, []{return logic->CanBuildRainbowBridge();}), + EventAccess(LOGIC_BUILD_RAINBOW_BRIDGE, []{return logic->CanBuildRainbowBridge();}), }, { //Locations LOCATION(RC_OGC_GS, logic->CanJumpslashExceptHammer() || logic->CanUseProjectile() || (logic->CanShield() && logic->CanUse(RG_MEGATON_HAMMER)) || logic->CanUse(RG_DINS_FIRE)), @@ -97,7 +107,7 @@ void RegionTable_Init_CastleGrounds() { //Exits Entrance(RR_CASTLE_GROUNDS, []{return logic->AtNight;}), Entrance(RR_OGC_GREAT_FAIRY_FOUNTAIN, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS) && logic->AtNight;}), - Entrance(RR_GANONS_CASTLE_LEDGE, []{return logic->BuiltRainbowBridge;}), + Entrance(RR_GANONS_CASTLE_LEDGE, []{return logic->Get(LOGIC_BUILD_RAINBOW_BRIDGE);}), }); areaTable[RR_OGC_GREAT_FAIRY_FOUNTAIN] = Region("OGC Great Fairy Fountain", SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, {}, { @@ -116,7 +126,7 @@ void RegionTable_Init_CastleGrounds() { areaTable[RR_GANONS_CASTLE_LEDGE] = Region("Ganon's Castle Ledge", SCENE_OUTSIDE_GANONS_CASTLE, {}, {}, { // Exits - Entrance(RR_GANONS_CASTLE_GROUNDS, []{return logic->BuiltRainbowBridge;}), + Entrance(RR_GANONS_CASTLE_GROUNDS, []{return logic->Get(LOGIC_BUILD_RAINBOW_BRIDGE);}), Entrance(RR_GANONS_CASTLE_ENTRYWAY, []{return logic->IsAdult;}), }); 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 be1b2043a..15e80d6c2 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 @@ -14,7 +14,7 @@ void RegionTable_Init_DeathMountainCrater() { areaTable[RR_DMC_UPPER_LOCAL] = Region("DMC Upper Local", SCENE_DEATH_MOUNTAIN_CRATER, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->HasExplosives() && logic->CallGossipFairyExceptSuns() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3);}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->HasExplosives() && logic->CallGossipFairyExceptSuns() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3);}), }, { //Locations LOCATION(RC_DMC_WALL_FREESTANDING_POH, logic->FireTimer() >= 16 || logic->Hearts() >= 3), @@ -75,7 +75,7 @@ void RegionTable_Init_DeathMountainCrater() { areaTable[RR_DMC_CENTRAL_LOCAL] = Region("DMC Central Local", SCENE_DEATH_MOUNTAIN_CRATER, { //Events - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3);}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3);}), }, { //Locations LOCATION(RC_DMC_GS_BEAN_PATCH, (logic->FireTimer() >= 8 || logic->Hearts() >= 3) && logic->CanSpawnSoilSkull() && logic->CanAttack()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp index dbf218947..42fa22cf9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp @@ -7,14 +7,14 @@ void RegionTable_Init_DeathMountainTrail() { // clang-format off areaTable[RR_DEATH_MOUNTAIN_TRAIL] = Region("Death Mountain", SCENE_DEATH_MOUNTAIN_TRAIL, { //Events - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET));}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET));}), }, { //Locations LOCATION(RC_DMT_CHEST, logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))), LOCATION(RC_DMT_FREESTANDING_POH, logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET)))), LOCATION(RC_DMT_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)))), LOCATION(RC_DMT_GS_NEAR_KAK, logic->BlastOrSmash()), - LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DMT_HOOKSHOT_LOWER_GS) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (ctx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_DMT_JS_LOWER_GS)) && logic->CanGetNightTimeGS()), + LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (ctx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) || (ctx->GetTrickOption(RT_DMT_JS_LOWER_GS) && logic->CanJumpslash())) && logic->CanGetNightTimeGS()), LOCATION(RC_DMT_BLUE_RUPEE, logic->IsChild && logic->BlastOrSmash()), LOCATION(RC_DMT_RED_RUPEE, logic->IsChild && logic->BlastOrSmash()), LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), @@ -32,8 +32,8 @@ void RegionTable_Init_DeathMountainTrail() { areaTable[RR_DEATH_MOUNTAIN_SUMMIT] = Region("Death Mountain Summit", SCENE_DEATH_MOUNTAIN_TRAIL, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), - EventAccess(&logic->BugRock, []{return logic->IsChild;}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_BUG_ROCK, []{return logic->IsChild;}), }, { //Locations LOCATION(RC_DMT_TRADE_BROKEN_SWORD, logic->IsAdult && logic->CanUse(RG_BROKEN_SWORD)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp index f4b8b01c3..6f639d539 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp @@ -7,8 +7,8 @@ void RegionTable_Init_DesertColossus() { // clang-format off areaTable[RR_DESERT_COLOSSUS] = Region("Desert Colossus", SCENE_DESERT_COLOSSUS, { //Events - EventAccess(&logic->FairyPond, []{return logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->BugRock, []{return true;}), + EventAccess(LOGIC_FAIRY_POND, []{return logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BUG_ROCK, []{return true;}), }, { //Locations LOCATION(RC_COLOSSUS_FREESTANDING_POH, logic->IsAdult && CanPlantBean(RR_DESERT_COLOSSUS)), @@ -34,7 +34,7 @@ void RegionTable_Init_DesertColossus() { //specifically the full oasis, after the fairies have spawned areaTable[RR_DESERT_COLOSSUS_OASIS] = Region("Desert Colossus Oasis", SCENE_DESERT_COLOSSUS, { //Events - EventAccess(&logic->FairyPond, []{return true;}), + EventAccess(LOGIC_FAIRY_POND, []{return true;}), }, { //Locations LOCATION(RC_COLOSSUS_OASIS_FAIRY_1, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp index 3929faf86..0e460cabd 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -9,7 +9,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_OUTSKIRTS] = Region("Gerudo Fortress Outskirts", SCENE_GERUDOS_FORTRESS, { //Events - EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), //needs climb + EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), //needs climb }, { //Locations LOCATION(RC_GF_OUTSKIRTS_NE_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()), @@ -18,7 +18,7 @@ void RegionTable_Init_GerudoFortress() { //Exits Entrance(RR_GV_FORTRESS_SIDE, []{return true;}), Entrance(RR_TH_1_TORCH_CELL, []{return true;}), - Entrance(RR_GF_OUTSIDE_GATE, []{return logic->GF_GateOpen;}), + Entrance(RR_GF_OUTSIDE_GATE, []{return logic->Get(LOGIC_GF_GATE_OPEN);}), Entrance(RR_GF_NEAR_GROTTO, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), Entrance(RR_GF_OUTSIDE_GTG, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), //You can talk to the guards to get yourself thrown in jail, so long as you have a hookshot to actually end up there @@ -30,7 +30,7 @@ void RegionTable_Init_GerudoFortress() { LOCATION(RC_GF_SOUTHMOST_CENTER_CRATE, logic->CanBreakCrates()), LOCATION(RC_GF_MID_SOUTH_CENTER_CRATE, logic->CanBreakCrates()), LOCATION(RC_GF_MID_NORTH_CENTER_CRATE, logic->CanBreakCrates()), - LOCATION(RR_GF_NORTHMOST_CENTER_CRATE, logic->CanBreakCrates()), + LOCATION(RC_GF_NORTHMOST_CENTER_CRATE, logic->CanBreakCrates()), }, { //Exits Entrance(RR_TH_1_TORCH_CELL, []{return true;}), @@ -46,10 +46,10 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_OUTSIDE_GTG] = Region("GF Outside GTG", SCENE_GERUDOS_FORTRESS, { //Events - EventAccess(&logic->GtG_GateOpen, []{return (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}), + EventAccess(LOGIC_GTG_GATE_OPEN, []{return (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}), }, {}, { //Exits - Entrance(RR_GF_TO_GTG, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}), + Entrance(RR_GF_TO_GTG, []{return logic->Get(LOGIC_GTG_GATE_OPEN) && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}), //Jail Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_OUTSKIRTS, []{return true;}), @@ -94,6 +94,7 @@ void RegionTable_Init_GerudoFortress() { Entrance(RR_GF_NEAR_GROTTO, []{return true;}), Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true /* logic->CanClimb() */;}), Entrance(RR_GF_ABOVE_GTG, []{return true;}), + Entrance(RR_GF_BELOW_GS, []{return logic->IsAdult && logic->CanGroundJump();}), }); areaTable[RR_GF_TOP_OF_LOWER_VINES] = Region("GF Top of Lower Vines", SCENE_GERUDOS_FORTRESS, {}, {}, { @@ -114,7 +115,7 @@ void RegionTable_Init_GerudoFortress() { Entrance(RR_TH_KITCHEN_TOP, []{return true;}), Entrance(RR_GF_BOTTOM_OF_LOWER_VINES, []{return true;}), Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), - Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult;}), + Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult || logic->CanGroundJump();}), Entrance(RR_GF_LONG_ROOF, []{return logic->CanUse(RG_HOVER_BOOTS) /* || bunny hood jump */ || logic->IsAdult && ctx->GetTrickOption(RT_GF_JUMP);}), Entrance(RR_GF_NEAR_CHEST, []{return logic->CanUse(RG_LONGSHOT);}), Entrance(RR_GF_BELOW_GS, []{return true;}), @@ -132,7 +133,7 @@ void RegionTable_Init_GerudoFortress() { //Exits Entrance(RR_GF_OUTSIDE_GTG, []{return true;}), Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), - Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_GF_JUMP));}), Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return true /* logic->CanClimb() */;}), Entrance(RR_GF_TO_GTG, []{return logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get();}), }); @@ -233,16 +234,16 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_OUTSIDE_GATE] = Region("GF Outside Gate", SCENE_GERUDOS_FORTRESS, { //Events - EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), + EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), }, {}, { //Exits - Entrance(RR_GF_OUTSKIRTS, []{return logic->GF_GateOpen;}), + Entrance(RR_GF_OUTSKIRTS, []{return logic->Get(LOGIC_GF_GATE_OPEN);}), Entrance(RR_WASTELAND_NEAR_FORTRESS, []{return true;}), }); areaTable[RR_GF_STORMS_GROTTO] = Region("GF Storms Grotto", SCENE_GROTTOS, { //Events - EventAccess(&logic->FreeFairies, []{return true;}), + EventAccess(LOGIC_FREE_FAIRIES, []{return true;}), }, { //Locations LOCATION(RC_GF_FAIRY_GROTTO_FAIRY_1, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index a9f0299ba..f613e969a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -7,7 +7,7 @@ void RegionTable_Init_GerudoValley() { // clang-format off areaTable[RR_GERUDO_VALLEY] = Region("Gerudo Valley", SCENE_GERUDO_VALLEY, { //Events - EventAccess(&logic->BugRock, []{return logic->IsChild;}), + EventAccess(LOGIC_BUG_ROCK, []{return logic->IsChild;}), }, { //Locations LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), @@ -17,14 +17,14 @@ void RegionTable_Init_GerudoValley() { Entrance(RR_GV_UPPER_STREAM, []{return logic->IsChild || logic->HasItem(RG_BRONZE_SCALE) || logic->TakeDamage();}), Entrance(RR_GV_CRATE_LEDGE, []{return logic->IsChild || logic->CanUse(RG_LONGSHOT);}), Entrance(RR_GV_GROTTO_LEDGE, []{return true;}), - Entrance(RR_GV_FORTRESS_SIDE, []{return (logic->IsAdult && (logic->CanUse(RG_EPONA) || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->THRescuedAllCarpenters)) || (logic->IsChild && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_GV_FORTRESS_SIDE, []{return (logic->IsAdult && (logic->CanUse(RG_EPONA) || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS))) || ((logic->IsChild || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION)) && logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_GV_LOWER_STREAM, []{return logic->IsChild;}), //can use cucco as child }); areaTable[RR_GV_UPPER_STREAM] = Region("GV Upper Stream", SCENE_GERUDO_VALLEY, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), }, { //Locations LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || logic->HasItem(RG_BRONZE_SCALE)),//can use cucco as child @@ -80,7 +80,7 @@ void RegionTable_Init_GerudoValley() { //Exits Entrance(RR_GF_OUTSKIRTS, []{return true;}), Entrance(RR_GV_UPPER_STREAM, []{return true;}), - Entrance(RR_GERUDO_VALLEY, []{return logic->IsChild || logic->CanUse(RG_EPONA) || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->THRescuedAllCarpenters;}), + Entrance(RR_GERUDO_VALLEY, []{return logic->IsChild || logic->CanUse(RG_EPONA) || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS);}), Entrance(RR_GV_CARPENTER_TENT, []{return logic->IsAdult;}), Entrance(RR_GV_STORMS_GROTTO, []{return logic->IsAdult && logic->CanOpenStormsGrotto();}), Entrance(RR_GV_CRATE_LEDGE, []{return ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives();}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp index 9d155c3a0..2e4fa2fbe 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -7,23 +7,23 @@ void RegionTable_Init_GoronCity() { // clang-format off areaTable[RR_GORON_CITY] = Region("Goron City", SCENE_GORON_CITY, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(&logic->StickPot, []{return logic->IsChild;}), - EventAccess(&logic->BugRock, []{return logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS);}), - EventAccess(&logic->GoronCityChildFire, []{return logic->IsChild && logic->CanUse(RG_DINS_FIRE);}), - EventAccess(&logic->GCWoodsWarpOpen, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER) || logic->GoronCityChildFire;}), - EventAccess(&logic->GCDaruniasDoorOpenChild, []{return logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY);}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_STICK_POT, []{return logic->IsChild;}), + EventAccess(LOGIC_BUG_ROCK, []{return logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS);}), + EventAccess(LOGIC_GORON_CITY_CHILD_FIRE, []{return logic->IsChild && logic->CanUse(RG_DINS_FIRE);}), + EventAccess(LOGIC_GORON_CITY_WOODS_WARP_OPEN, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER) || logic->Get(LOGIC_GORON_CITY_CHILD_FIRE);}), + EventAccess(LOGIC_GORON_CITY_DARUNIAS_DOOR_OPEN_CHILD, []{return logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY);}), // bottle animation causes similar complications as stopping goron with Din's Fire, only put in logic when both din's & blue fire tricks enabled - EventAccess(&logic->StopGCRollingGoronAsAdult, []{return logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || + EventAccess(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT, []{return logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && (logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE)))));}), }, { //Locations LOCATION(RC_GC_MAZE_LEFT_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))), LOCATION(RC_GC_MAZE_CENTER_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), LOCATION(RC_GC_MAZE_RIGHT_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), - LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->GoronCityChildFire && (logic->CanUse(RG_BOMB_BAG) || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_GC_POT)))), + LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->Get(LOGIC_GORON_CITY_CHILD_FIRE) && (logic->CanUse(RG_BOMB_BAG) || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_GC_POT)))), LOCATION(RC_GC_ROLLING_GORON_AS_CHILD, logic->IsChild && (logic->HasExplosives() || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_ROLLING_STRENGTH)))), - LOCATION(RC_GC_ROLLING_GORON_AS_ADULT, logic->StopGCRollingGoronAsAdult), + LOCATION(RC_GC_ROLLING_GORON_AS_ADULT, logic->Get(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT)), LOCATION(RC_GC_GS_BOULDER_MAZE, logic->IsChild && logic->BlastOrSmash()), LOCATION(RC_GC_GS_CENTER_PLATFORM, logic->IsAdult && logic->CanAttack()), LOCATION(RC_GC_MEDIGORON, logic->IsAdult && (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET))), @@ -41,9 +41,9 @@ void RegionTable_Init_GoronCity() { //Exits Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return true;}), Entrance(RR_GC_MEDIGORON, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);}), - Entrance(RR_GC_WOODS_WARP, []{return logic->GCWoodsWarpOpen;}), - Entrance(RR_GC_SHOP, []{return (logic->IsAdult && logic->StopGCRollingGoronAsAdult) || (logic->IsChild && (logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET) || logic->GoronCityChildFire || logic->CanUse(RG_FAIRY_BOW)));}), - Entrance(RR_GC_DARUNIAS_CHAMBER, []{return (logic->IsAdult && logic->StopGCRollingGoronAsAdult) || (logic->IsChild && logic->GCDaruniasDoorOpenChild);}), + Entrance(RR_GC_WOODS_WARP, []{return logic->Get(LOGIC_GORON_CITY_WOODS_WARP_OPEN);}), + Entrance(RR_GC_SHOP, []{return (logic->IsAdult && logic->Get(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT)) || (logic->IsChild && (logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET) || logic->Get(LOGIC_GORON_CITY_CHILD_FIRE) || logic->CanUse(RG_FAIRY_BOW)));}), + Entrance(RR_GC_DARUNIAS_CHAMBER, []{return (logic->IsAdult && logic->Get(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT)) || (logic->IsChild && logic->Get(LOGIC_GORON_CITY_DARUNIAS_DOOR_OPEN_CHILD));}), Entrance(RR_GC_GROTTO_PLATFORM, []{return logic->IsAdult && ((logic->CanUse(RG_SONG_OF_TIME) && ((logic->EffectiveHealth() > 2) || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_NAYRUS_LOVE))) || (logic->EffectiveHealth() > 1 && logic->CanUse(RG_GORON_TUNIC) && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_HOOKSHOT)) || (logic->EffectiveHealth() > 2 && logic->CanUse(RG_HOOKSHOT) && ctx->GetTrickOption(RT_GC_GROTTO)));}), }); @@ -60,16 +60,16 @@ void RegionTable_Init_GoronCity() { areaTable[RR_GC_WOODS_WARP] = Region("GC Woods Warp", SCENE_GORON_CITY, { //Events - EventAccess(&logic->GCWoodsWarpOpen, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), + EventAccess(LOGIC_GORON_CITY_WOODS_WARP_OPEN, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), }, {}, { //Exits - Entrance(RR_GORON_CITY, []{return logic->GCWoodsWarpOpen;}), + Entrance(RR_GORON_CITY, []{return logic->Get(LOGIC_GORON_CITY_WOODS_WARP_OPEN);}), Entrance(RR_THE_LOST_WOODS, []{return true;}), }); areaTable[RR_GC_DARUNIAS_CHAMBER] = Region("GC Darunias Chamber", SCENE_GORON_CITY, { //Events - EventAccess(&logic->GoronCityChildFire, []{return logic->IsChild && logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_GORON_CITY_CHILD_FIRE, []{return logic->IsChild && logic->CanUse(RG_STICKS);}), }, { //Locations LOCATION(RC_GC_DARUNIAS_JOY, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index 2fce0854f..94a2c85c8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -7,10 +7,10 @@ void RegionTable_Init_Graveyard() { // clang-format off areaTable[RR_THE_GRAVEYARD] = Region("The Graveyard", SCENE_GRAVEYARD, { //Events - EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->BugRock, []{return true;}), - EventAccess(&logic->BorrowBunnyHood, []{return logic->IsChild && logic->AtDay && logic->BorrowSpookyMask && logic->HasItem(RG_CHILD_WALLET);}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BUG_ROCK, []{return true;}), + EventAccess(LOGIC_BORROW_BUNNY_HOOD, []{return logic->IsChild && logic->AtDay && logic->Get(LOGIC_BORROW_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), @@ -88,8 +88,8 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_DAMPES_GRAVE] = Region("Graveyard Dampes Grave", SCENE_WINDMILL_AND_DAMPES_GRAVE, { //Events - EventAccess(&logic->NutPot, []{return true;}), - EventAccess(&logic->DampesWindmillAccess, []{return logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME);}), + EventAccess(LOGIC_NUT_POT, []{return true;}), + EventAccess(LOGIC_DAMPES_WINDMILL_ACCESS, []{return logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME);}), }, { //Locations LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true), @@ -111,7 +111,7 @@ void RegionTable_Init_Graveyard() { }, { //Exits Entrance(RR_THE_GRAVEYARD, []{return true;}), - Entrance(RR_KAK_WINDMILL, []{return logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME);}, false), + Entrance(RR_KAK_WINDMILL, []{return (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME)) || (logic->IsChild && logic->CanGroundJump());}, false), }); areaTable[RR_GRAVEYARD_DAMPES_HOUSE] = Region("Graveyard Dampes House", SCENE_GRAVEKEEPERS_HUT, {}, { @@ -124,7 +124,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_WARP_PAD_REGION] = Region("Graveyard Warp Pad Region", SCENE_GRAVEYARD, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), }, { //Locations LOCATION(RC_GRAVEYARD_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp index 930ffcb4f..b1cefc144 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp @@ -17,14 +17,14 @@ void RegionTable_Init_HauntedWasteland() { areaTable[RR_HAUNTED_WASTELAND] = Region("Haunted Wasteland", SCENE_HAUNTED_WASTELAND, { //Events - EventAccess(&logic->FairyPot, []{return true;}), - EventAccess(&logic->NutPot, []{return true;}), - EventAccess(&logic->CarpetMerchant, []{return logic->HasItem(RG_ADULT_WALLET) && CanBuyAnother(RC_WASTELAND_BOMBCHU_SALESMAN) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}), + EventAccess(LOGIC_FAIRY_POT, []{return true;}), + EventAccess(LOGIC_NUT_POT, []{return true;}), + EventAccess(LOGIC_CARPET_MERCHANT, []{return logic->HasItem(RG_ADULT_WALLET) && CanBuyAnother(RC_WASTELAND_BOMBCHU_SALESMAN) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}), }, { //Locations LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource()), LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang()), + LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang() || (logic->IsAdult && logic->CanGroundJump() && logic->CanJumpslash())), LOCATION(RC_WASTELAND_NEAR_GS_POT_1, logic->CanBreakPots()), LOCATION(RC_WASTELAND_NEAR_GS_POT_2, logic->CanBreakPots()), LOCATION(RC_WASTELAND_NEAR_GS_POT_3, logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index 3d850be58..6c23dbcb8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -7,8 +7,8 @@ void RegionTable_Init_HyruleField() { // clang-format off areaTable[RR_HYRULE_FIELD] = Region("Hyrule Field", SCENE_HYRULE_FIELD, { //Events - EventAccess(&logic->BigPoeKill, []{return logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_EPONA) || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA));}), - EventAccess(&logic->BorrowRightMasks, []{return logic->IsChild && logic->BorrowBunnyHood && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET);}), + EventAccess(LOGIC_BIG_POE_KILL, []{return logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_EPONA) || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA));}), + EventAccess(LOGIC_BORROW_RIGHT_MASKS, []{return logic->IsChild && logic->Get(LOGIC_BORROW_BUNNY_HOOD) && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->StoneCount() == 3 && logic->HasItem(RG_BRONZE_SCALE)), @@ -62,6 +62,54 @@ void RegionTable_Init_HyruleField() { LOCATION(RC_HF_NEAR_KF_GRASS_10, logic->CanCutShrubs()), LOCATION(RC_HF_NEAR_KF_GRASS_11, logic->CanCutShrubs()), LOCATION(RC_HF_NEAR_KF_GRASS_12, logic->CanCutShrubs()), + LOCATION(RC_HF_NEAR_LLR_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_NEAR_LH_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_CHILD_NEAR_GV_TREE, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_HF_ADULT_NEAR_GV_TREE, logic->IsAdult && logic->CanBonkTrees()), + LOCATION(RC_HF_NEAR_ZR_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_NEAR_KAK_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_NEAR_KAK_SMALL_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_NEAR_MARKET_TREE_1, logic->CanBonkTrees()), + LOCATION(RC_HF_NEAR_MARKET_TREE_2, logic->CanBonkTrees()), + LOCATION(RC_HF_NEAR_MARKET_TREE_3, logic->CanBonkTrees()), + LOCATION(RC_HF_NORTHWEST_TREE_1, logic->CanBonkTrees()), + LOCATION(RC_HF_NORTHWEST_TREE_2, logic->CanBonkTrees()), + LOCATION(RC_HF_NORTHWEST_TREE_3, logic->CanBonkTrees()), + LOCATION(RC_HF_NORTHWEST_TREE_4, logic->CanBonkTrees()), + LOCATION(RC_HF_NORTHWEST_TREE_5, logic->CanBonkTrees()), + LOCATION(RC_HF_NORTHWEST_TREE_6, logic->CanBonkTrees()), + LOCATION(RC_HF_EAST_TREE_1, logic->CanBonkTrees()), + LOCATION(RC_HF_EAST_TREE_2, logic->CanBonkTrees()), + LOCATION(RC_HF_EAST_TREE_3, logic->CanBonkTrees()), + LOCATION(RC_HF_EAST_TREE_4, logic->CanBonkTrees()), + LOCATION(RC_HF_EAST_TREE_5, logic->CanBonkTrees()), + LOCATION(RC_HF_EAST_TREE_6, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_1, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_2, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_3, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_4, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_5, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_6, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_7, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_8, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_9, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_10, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_11, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_12, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_13, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_14, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_15, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_16, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_17, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_18, logic->CanBonkTrees()), + LOCATION(RC_HF_SOUTHEAST_TREE_19, logic->CanBonkTrees()), + LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_1, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_2, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_3, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_4, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_5, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_6, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_HF_TEKTITE_GROTTO_TREE, logic->CanBonkTrees()), }, { //Exits Entrance(RR_LW_BRIDGE, []{return true;}), @@ -135,8 +183,8 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_COW_GROTTO_BEHIND_WEBS] = Region("HF Cow Grotto Behind Webs", SCENE_GROTTOS, { //Events - EventAccess(&logic->BugShrub, []{return logic->CanCutShrubs();}), - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_BUG_SHRUB, []{return logic->CanCutShrubs();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), }, { //Locations LOCATION(RC_HF_GS_COW_GROTTO, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), @@ -173,7 +221,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_FAIRY_GROTTO] = Region("HF Fairy Grotto", SCENE_GROTTOS, { //Events - EventAccess(&logic->FreeFairies, []{return true;}), + EventAccess(LOGIC_FREE_FAIRIES, []{return true;}), }, { //Locations LOCATION(RC_HF_FAIRY_GROTTO_FAIRY_1, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 92bc9aa37..cb6bb78a1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -7,22 +7,22 @@ void RegionTable_Init_Kakariko() { // clang-format off areaTable[RR_KAKARIKO_VILLAGE] = Region("Kakariko Village", SCENE_KAKARIKO_VILLAGE, { //Events - EventAccess(&logic->BugRock, []{return true;}), + EventAccess(LOGIC_BUG_ROCK, []{return true;}), //Open Gate setting is applied in RR_ROOT - EventAccess(&logic->KakarikoVillageGateOpen, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}), + EventAccess(LOGIC_KAKARIKO_GATE_OPEN, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}), //Needs wallet to be able to get another mask after selling Keaton - EventAccess(&logic->BorrowSkullMask, []{return logic->IsChild && logic->CanBorrowMasks && logic->HasItem(RG_CHILD_WALLET);}), + EventAccess(LOGIC_BORROW_SKULL_MASK, []{return logic->IsChild && logic->Get(LOGIC_CAN_BORROW_MASKS) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay), LOCATION(RC_KAK_ANJU_AS_ADULT, logic->IsAdult && logic->AtDay), - LOCATION(RC_KAK_TRADE_POCKET_CUCCO, logic->IsAdult && logic->AtDay && (logic->CanUse(RG_POCKET_EGG) && logic->WakeUpAdultTalon)), + LOCATION(RC_KAK_TRADE_POCKET_CUCCO, logic->IsAdult && logic->AtDay && (logic->CanUse(RG_POCKET_EGG) && logic->Get(LOGIC_WAKE_UP_ADULT_TALON))), //Can kill lower kak skulls with pots LOCATION(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, logic->IsChild && logic->CanGetNightTimeGS()), LOCATION(RC_KAK_GS_SKULLTULA_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()), LOCATION(RC_KAK_GS_GUARDS_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()), - LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->CanGetNightTimeGS()), + LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->CanGetNightTimeGS() && logic->CanBonkTrees()), LOCATION(RC_KAK_GS_WATCHTOWER, logic->IsChild && (logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_1, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_2, logic->IsChild && logic->CanBreakPots()), @@ -59,6 +59,7 @@ void RegionTable_Init_Kakariko() { LOCATION(RC_KAK_NEAR_FENCE_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()), LOCATION(RC_KAK_NEAR_BOARDING_HOUSE_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()), LOCATION(RC_KAK_NEAR_BAZAAR_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_KAK_TREE, logic->CanBonkTrees()), }, { //Exits Entrance(RR_HYRULE_FIELD, []{return true;}), @@ -68,7 +69,7 @@ void RegionTable_Init_Kakariko() { Entrance(RR_KAK_WINDMILL, []{return logic->CanOpenOverworldDoor(RG_WINDMILL_KEY);}), Entrance(RR_KAK_BAZAAR, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_BAZAAR_KEY);}), Entrance(RR_KAK_SHOOTING_GALLERY, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_SHOOTING_GALLERY_KEY);}), - Entrance(RR_KAK_WELL, []{return logic->IsAdult || logic->DrainWell || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_BOTTOM_OF_THE_WELL_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash());}), + Entrance(RR_KAK_WELL, []{return logic->IsAdult || logic->Get(LOGIC_DRAIN_WELL) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_BOTTOM_OF_THE_WELL_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash());}), Entrance(RR_KAK_POTION_SHOP_FRONT, []{return (logic->AtDay || logic->IsChild) && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}), Entrance(RR_KAK_REDEAD_GROTTO, []{return logic->CanOpenBombGrotto();}), Entrance(RR_KAK_IMPAS_LEDGE, []{return (logic->IsChild && logic->AtDay) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION));}), @@ -76,7 +77,7 @@ void RegionTable_Init_Kakariko() { Entrance(RR_KAK_ROOFTOP, []{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_KAK_MAN_ON_ROOF) && logic->IsAdult);}), Entrance(RR_KAK_IMPAS_ROOFTOP, []{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_KAK_ROOFTOP_GS) && logic->CanUse(RG_HOVER_BOOTS));}), Entrance(RR_THE_GRAVEYARD, []{return true;}), - Entrance(RR_KAK_BEHIND_GATE, []{return logic->IsAdult || logic->KakarikoVillageGateOpen;}), + Entrance(RR_KAK_BEHIND_GATE, []{return logic->IsAdult || logic->Get(LOGIC_KAKARIKO_GATE_OPEN);}), //adult can jump from the fence near the windmill to ledgegrab the fence near granny's shop. is in logic on N64 Entrance(RR_KAK_BACKYARD, []{return logic->IsAdult || logic->AtDay;}), }); @@ -130,7 +131,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_CARPENTER_BOSS_HOUSE] = Region("Kak Carpenter Boss House", SCENE_KAKARIKO_CENTER_GUEST_HOUSE, { //Events - EventAccess(&logic->WakeUpAdultTalon, []{return logic->IsAdult && logic->CanUse(RG_POCKET_EGG);}), + EventAccess(LOGIC_WAKE_UP_ADULT_TALON, []{return logic->IsAdult && logic->CanUse(RG_POCKET_EGG);}), }, {}, { //Exits Entrance(RR_KAKARIKO_VILLAGE, []{return true;}), @@ -168,10 +169,10 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_WINDMILL] = Region("Kak Windmill", SCENE_WINDMILL_AND_DAMPES_GRAVE, { //Events - EventAccess(&logic->DrainWell, []{return logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_DRAIN_WELL, []{return logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS);}), }, { //Locations - LOCATION(RC_KAK_WINDMILL_FREESTANDING_POH, logic->CanUse(RG_BOOMERANG) || logic->DampesWindmillAccess || (logic->IsAdult && ctx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (logic->IsChild && logic->CanJumpslashExceptHammer() && ctx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH))), + LOCATION(RC_KAK_WINDMILL_FREESTANDING_POH, logic->CanUse(RG_BOOMERANG) || logic->Get(LOGIC_DAMPES_WINDMILL_ACCESS) || (logic->IsAdult && ctx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (logic->IsChild && logic->CanJumpslashExceptHammer() && ctx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH))), LOCATION(RC_SONG_FROM_WINDMILL, logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA)), }, { //Exits @@ -263,14 +264,14 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_BEHIND_GATE] = Region("Kak Behind Gate", SCENE_KAKARIKO_VILLAGE, {}, {}, { //Exits - Entrance(RR_KAKARIKO_VILLAGE, []{return logic->IsAdult || ctx->GetTrickOption(RT_VISIBLE_COLLISION) || logic->KakarikoVillageGateOpen;}), + Entrance(RR_KAKARIKO_VILLAGE, []{return logic->IsAdult || ctx->GetTrickOption(RT_VISIBLE_COLLISION) || logic->Get(LOGIC_KAKARIKO_GATE_OPEN);}), Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return true;}), }); areaTable[RR_KAK_WELL] = Region("Kak Well", SCENE_KAKARIKO_VILLAGE, {}, {}, { //Exits - Entrance(RR_KAKARIKO_VILLAGE, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->DrainWell;}), - Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild || (logic->DrainWell && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}), + Entrance(RR_KAKARIKO_VILLAGE, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->Get(LOGIC_DRAIN_WELL);}), + Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild || (logic->Get(LOGIC_DRAIN_WELL) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp index 5d8ef11ec..8c548745a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -7,9 +7,9 @@ void RegionTable_Init_KokiriForest() { // clang-format off areaTable[RR_KOKIRI_FOREST] = Region("Kokiri Forest", SCENE_KOKIRI_FOREST, { //Events - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}), }, { //Locations LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), @@ -83,17 +83,18 @@ void RegionTable_Init_KokiriForest() { Entrance(RR_KF_HOUSE_OF_TWINS, []{return true;}), Entrance(RR_KF_KNOW_IT_ALL_HOUSE, []{return true;}), Entrance(RR_KF_KOKIRI_SHOP, []{return true;}), - Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->ForestTempleClear)) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->ShowedMidoSwordAndShield;}), + Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->Get(LOGIC_FOREST_TEMPLE_CLEAR))) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->Get(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD);}), Entrance(RR_THE_LOST_WOODS, []{return true;}), - Entrance(RR_LW_BRIDGE_FROM_FOREST, []{return logic->IsAdult || ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || logic->DekuTreeClear;}), + Entrance(RR_LW_BRIDGE_FROM_FOREST, []{return logic->IsAdult || ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || logic->Get(LOGIC_DEKU_TREE_CLEAR);}), Entrance(RR_KF_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); areaTable[RR_KF_OUTSIDE_DEKU_TREE] = Region("KF Outside Deku Tree", SCENE_KOKIRI_FOREST, { //Events - EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), - EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}), + EventAccess(LOGIC_DEKU_BABA_STICKS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}), }, { //Locations LOCATION(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), @@ -104,13 +105,13 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, true), }, { //Exits - Entrance(RR_DEKU_TREE_ENTRYWAY, []{return logic->IsChild || (ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->ShowedMidoSwordAndShield));}), - Entrance(RR_KOKIRI_FOREST, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->ForestTempleClear)) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->ShowedMidoSwordAndShield;}), + Entrance(RR_DEKU_TREE_ENTRYWAY, []{return logic->IsChild || (ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->Get(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD)));}), + Entrance(RR_KOKIRI_FOREST, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->Get(LOGIC_DEKU_TREE_CLEAR))) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->Get(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD);}), }); areaTable[RR_KF_LINKS_HOUSE] = Region("KF Link's House", SCENE_LINKS_HOUSE, {}, { //Locations - LOCATION(RC_KF_LINKS_HOUSE_COW, logic->IsAdult && logic->CanUse(RG_EPONAS_SONG) && logic->LinksCow), + LOCATION(RC_KF_LINKS_HOUSE_COW, logic->IsAdult && logic->CanUse(RG_EPONAS_SONG) && logic->Get(LOGIC_LINKS_COW)), LOCATION(RC_KF_LINKS_HOUSE_POT, logic->CanBreakPots()), }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp index 964b781ce..f88a2cb6a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp @@ -7,16 +7,16 @@ void RegionTable_Init_LakeHylia() { // clang-format off areaTable[RR_LAKE_HYLIA] = Region("Lake Hylia", SCENE_LAKE_HYLIA, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}), - EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}), - EventAccess(&logic->ChildScarecrow, []{return logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2;}), - EventAccess(&logic->AdultScarecrow, []{return logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2;}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_BUG_SHRUB, []{return logic->IsChild && logic->CanCutShrubs();}), + EventAccess(LOGIC_CHILD_SCARECROW, []{return logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2;}), + EventAccess(LOGIC_ADULT_SCARECROW, []{return logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2;}), }, { //Locations LOCATION(RC_LH_UNDERWATER_ITEM, logic->IsChild && logic->HasItem(RG_SILVER_SCALE)), - LOCATION(RC_LH_SUN, logic->IsAdult && ((logic->WaterTempleClear && logic->HasItem(RG_BRONZE_SCALE)) || logic->CanUse(RG_DISTANT_SCARECROW)) && logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_LH_SUN, logic->IsAdult && ((logic->Get(LOGIC_WATER_TEMPLE_CLEAR) && logic->HasItem(RG_BRONZE_SCALE)) || logic->CanUse(RG_DISTANT_SCARECROW)) && logic->CanUse(RG_FAIRY_BOW)), LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA))), LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_LH_GS_LAB_WALL, logic->IsChild && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (ctx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), @@ -35,7 +35,7 @@ void RegionTable_Init_LakeHylia() { LOCATION(RC_LH_SOUTHEAST_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_LH_SOUTHWEST_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_LH_ISLAND_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && ((logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->WaterTempleClear)) || logic->CanUse(RG_DISTANT_SCARECROW))), + LOCATION(RC_LH_ISLAND_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && ((logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR))) || logic->CanUse(RG_DISTANT_SCARECROW))), LOCATION(RC_LH_LAB_GOSSIP_STONE, true), LOCATION(RC_LH_SOUTHEAST_GOSSIP_STONE, true), LOCATION(RC_LH_SOUTHWEST_GOSSIP_STONE, true), @@ -86,7 +86,7 @@ void RegionTable_Init_LakeHylia() { Entrance(RR_HYRULE_FIELD, []{return true;}), Entrance(RR_LH_FROM_SHORTCUT, []{return true;}), Entrance(RR_LH_OWL_FLIGHT, []{return logic->IsChild;}), - Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->WaterTempleClear) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA)));}), + Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR)) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA)));}), Entrance(RR_LH_LAB, []{return logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY);}), Entrance(RR_LH_FROM_WATER_TEMPLE, []{return true;}), Entrance(RR_LH_GROTTO, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp index c29a5924e..4bfae2f1e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp @@ -7,12 +7,12 @@ void RegionTable_Init_LonLonRanch() { // clang-format off areaTable[RR_LON_LON_RANCH] = Region("Lon Lon Ranch", SCENE_LON_LON_RANCH, { //Events - EventAccess(&logic->FreedEpona, []{return (logic->HasItem(RG_CHILD_WALLET) || ctx->GetOption(RSK_SKIP_EPONA_RACE)) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}), - EventAccess(&logic->LinksCow, []{return logic->HasItem(RG_CHILD_WALLET) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}), + EventAccess(LOGIC_FREED_EPONA, []{return (logic->HasItem(RG_CHILD_WALLET) || ctx->GetOption(RSK_SKIP_EPONA_RACE)) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}), + EventAccess(LOGIC_LINKS_COW, []{return logic->HasItem(RG_CHILD_WALLET) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}), }, { //Locations LOCATION(RC_SONG_FROM_MALON, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_FAIRY_OCARINA) && logic->AtDay), - LOCATION(RC_LLR_GS_TREE, logic->IsChild), + LOCATION(RC_LLR_GS_TREE, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_LLR_GS_RAIN_SHED, logic->IsChild && logic->CanGetNightTimeGS()), LOCATION(RC_LLR_GS_HOUSE_WINDOW, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_LLR_GS_BACK_WALL, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), @@ -24,6 +24,7 @@ void RegionTable_Init_LonLonRanch() { LOCATION(RC_LLR_RAIN_SHED_POT_2, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_LLR_RAIN_SHED_POT_3, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_LLR_NEAR_TREE_CRATE, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_LLR_TREE, logic->IsChild && logic->CanBonkTrees()), }, { //Exits Entrance(RR_HYRULE_FIELD, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index 6c6bdb536..dc6d84875 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -12,10 +12,10 @@ void RegionTable_Init_LostWoods() { areaTable[RR_THE_LOST_WOODS] = Region("Lost Woods", SCENE_LOST_WOODS, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}), - EventAccess(&logic->BorrowSpookyMask, []{return logic->IsChild && logic->BorrowSkullMask && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET);}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BUG_SHRUB, []{return logic->IsChild && logic->CanCutShrubs();}), + EventAccess(LOGIC_BORROW_SPOOKY_MASK, []{return logic->IsChild && logic->Get(LOGIC_BORROW_SKULL_MASK) && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), @@ -65,7 +65,7 @@ void RegionTable_Init_LostWoods() { areaTable[RR_LW_BEYOND_MIDO] = Region("LW Beyond Mido", SCENE_LOST_WOODS, { //Events - EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS);}), }, { //Locations LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku()), @@ -111,8 +111,8 @@ void RegionTable_Init_LostWoods() { areaTable[RR_DEKU_THEATER] = Region("Deku Theater", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->BorrowSkullMask), - LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->BorrowRightMasks), + LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->Get(LOGIC_BORROW_SKULL_MASK)), + LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->Get(LOGIC_BORROW_RIGHT_MASKS)), }, { //Exits Entrance(RR_LW_BEYOND_MIDO, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 4f62d437f..982601b3c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -27,6 +27,7 @@ void RegionTable_Init_Market() { LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/), LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/), LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/), + LOCATION(RC_MARKET_TREE, logic->IsChild && logic->CanBonkTrees()), }, { //Exits Entrance(RR_MARKET_ENTRANCE, []{return true;}), @@ -51,10 +52,10 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_GUARD_HOUSE] = Region("Market Guard House", SCENE_MARKET_GUARD_HOUSE, { //Events - EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}), + EventAccess(LOGIC_CAN_EMPTY_BIG_POES, []{return logic->IsAdult;}), }, { //Locations - LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())), + LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->Get(LOGIC_BIG_POE_KILL) || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())), LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()), @@ -141,11 +142,11 @@ void RegionTable_Init_Market() { //Currently, mask swap in menu doesn't need access to the mask shop //If it is forced on/a setting, a copy of these events should be added to root //it also doesn't need you to open kak gate, but that might be best treated as a bug - EventAccess(&logic->CanBorrowMasks, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->KakarikoVillageGateOpen;}), - EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), - EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), - EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), - EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(LOGIC_CAN_BORROW_MASKS, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->Get(LOGIC_KAKARIKO_GATE_OPEN);}), + EventAccess(LOGIC_BORROW_SKULL_MASK, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->Get(LOGIC_CAN_BORROW_MASKS);}), + EventAccess(LOGIC_BORROW_SPOOKY_MASK, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->Get(LOGIC_CAN_BORROW_MASKS);}), + EventAccess(LOGIC_BORROW_BUNNY_HOOD, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->Get(LOGIC_CAN_BORROW_MASKS);}), + EventAccess(LOGIC_BORROW_RIGHT_MASKS, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->Get(LOGIC_CAN_BORROW_MASKS);}), }, { //Locations LOCATION(RC_MASK_SHOP_HINT, true), @@ -164,11 +165,11 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_BOMBCHU_BOWLING] = Region("Market Bombchu Bowling", SCENE_BOMBCHU_BOWLING_ALLEY, { //Events - EventAccess(&logic->CouldPlayBowling, []{return (logic->HasItem(RG_CHILD_WALLET));}), + EventAccess(LOGIC_COULD_PLAY_BOWLING, []{return logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations - LOCATION(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, logic->CouldPlayBowling && logic->BombchusEnabled()), - LOCATION(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, logic->CouldPlayBowling && logic->BombchusEnabled()), + LOCATION(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, logic->Get(LOGIC_COULD_PLAY_BOWLING) && logic->BombchusEnabled()), + LOCATION(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, logic->Get(LOGIC_COULD_PLAY_BOWLING) && logic->BombchusEnabled()), }, { //Exits Entrance(RR_THE_MARKET, []{return true;}), @@ -192,17 +193,17 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Region("Market Treasure Chest Game", SCENE_TREASURE_BOX_SHOP, {}, { //Locations LOCATION(RC_GREG_HINT, logic->HasItem(RG_CHILD_WALLET)), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), }, { //Exits Entrance(RR_THE_MARKET, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp index 9d641ac98..34425e229 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp @@ -14,7 +14,7 @@ void RegionTable_Init_SacredForestMeadow() { areaTable[RR_SACRED_FOREST_MEADOW] = Region("Sacred Forest Meadow", SCENE_SACRED_FOREST_MEADOW, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), }, { //Locations LOCATION(RC_SONG_FROM_SARIA, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER)), @@ -39,7 +39,7 @@ void RegionTable_Init_SacredForestMeadow() { areaTable[RR_SFM_FAIRY_GROTTO] = Region("SFM Fairy Grotto", SCENE_GROTTOS, { //Events - EventAccess(&logic->FreeFairies, []{return true;}), + EventAccess(LOGIC_FREE_FAIRIES, []{return true;}), }, { //Locations LOCATION(RC_SFM_FAIRY_GROTTO_FAIRY_1, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp index 07efc4326..c3e214482 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp @@ -7,7 +7,7 @@ void RegionTable_Init_TempleOfTime() { // clang-format off areaTable[RR_TOT_ENTRANCE] = Region("ToT Entrance", SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), }, { //Locations LOCATION(RC_TOT_LEFTMOST_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns() || (logic->CanUse(RG_SUNS_SONG) && logic->IsAdult)), @@ -40,10 +40,7 @@ void RegionTable_Init_TempleOfTime() { Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, []{return ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN) || (logic->CanUse(RG_SONG_OF_TIME) && (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY) || (logic->StoneCount() == 3 && logic->HasItem(RG_OCARINA_OF_TIME))));}), }); - areaTable[RR_TOT_BEYOND_DOOR_OF_TIME] = Region("Beyond Door of Time", SCENE_TEMPLE_OF_TIME, { - //Events - //EventAccess(&logic->TimeTravel, []{return true;}), - }, { + areaTable[RR_TOT_BEYOND_DOOR_OF_TIME] = Region("Beyond Door of Time", SCENE_TEMPLE_OF_TIME, {}, { //Locations LOCATION(RC_TOT_MASTER_SWORD, logic->IsAdult), LOCATION(RC_GIFT_FROM_RAURU, logic->IsAdult), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp index 0a70e77e8..49a46bc9a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp @@ -8,8 +8,8 @@ using namespace Rando; void RegionTable_Init_ThievesHideout() { areaTable[RR_TH_1_TORCH_CELL] = Region("Thieves Hideout 1 Torch Cell", SCENE_THIEVES_HIDEOUT, { //Events - EventAccess(&logic->THCouldFree1TorchCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), - EventAccess(&logic->THRescuedAllCarpenters, []{return logic->SmallKeys(RR_GF_OUTSKIRTS, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}), + EventAccess(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), + EventAccess(LOGIC_TH_RESCUED_ALL_CARPENTERS, []{return logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER);}), }, { //Locations LOCATION(RC_TH_1_TORCH_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)), @@ -17,7 +17,7 @@ void RegionTable_Init_ThievesHideout() { LOCATION(RC_TH_1_TORCH_CELL_MID_POT, logic->CanBreakPots()), LOCATION(RC_TH_1_TORCH_CELL_LEFT_POT, logic->CanBreakPots()), LOCATION(RC_TH_1_TORCH_CELL_CRATE, logic->CanBreakCrates()), - LOCATION(RC_TH_FREED_CARPENTERS, logic->THRescuedAllCarpenters), + LOCATION(RC_TH_FREED_CARPENTERS, logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS)), }, { //Exits Entrance(RR_GF_OUTSKIRTS, []{return true;}), @@ -26,8 +26,8 @@ void RegionTable_Init_ThievesHideout() { areaTable[RR_TH_DOUBLE_CELL] = Region("Thieves Hideout Double Cell", SCENE_THIEVES_HIDEOUT, { //Events - EventAccess(&logic->THCouldFreeDoubleCellCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), - EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && logic->SmallKeys(RR_GF_OUTSKIRTS, 4) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}), + EventAccess(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), + EventAccess(LOGIC_TH_RESCUED_ALL_CARPENTERS, []{return logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER);}), }, { //Locations LOCATION(RC_TH_DOUBLE_CELL_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)), @@ -40,7 +40,7 @@ void RegionTable_Init_ThievesHideout() { LOCATION(RC_TH_LEFTMOST_JAILED_POT, logic->CanBreakPots()), LOCATION(RC_TH_DOUBLE_CELL_LEFT_CRATE, logic->CanBreakCrates()), LOCATION(RC_TH_DOUBLE_CELL_RIGHT_CRATE, logic->CanBreakCrates()), - LOCATION(RC_TH_FREED_CARPENTERS, logic->THRescuedAllCarpenters), + LOCATION(RC_TH_FREED_CARPENTERS, logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS)), }, { //Exits Entrance(RR_GF_OUTSKIRTS, []{return true;}), @@ -49,13 +49,13 @@ void RegionTable_Init_ThievesHideout() { areaTable[RR_TH_DEAD_END_CELL] = Region("Thieves Hideout Dead End Cell", SCENE_THIEVES_HIDEOUT, { //Events - EventAccess(&logic->TH_CouldFreeDeadEndCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), - EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && logic->SmallKeys(RR_GF_OUTSKIRTS, 4) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}), + EventAccess(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), + EventAccess(LOGIC_TH_RESCUED_ALL_CARPENTERS, []{return logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER);}), }, { //Locations LOCATION(RC_TH_DEAD_END_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)), LOCATION(RC_TH_DEAD_END_CELL_CRATE, logic->CanBreakCrates()), - LOCATION(RC_TH_FREED_CARPENTERS, logic->THRescuedAllCarpenters), + LOCATION(RC_TH_FREED_CARPENTERS, logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS)), }, { //Exits Entrance(RR_GF_BELOW_GS, []{return true;}), @@ -63,14 +63,14 @@ void RegionTable_Init_ThievesHideout() { areaTable[RR_TH_STEEP_SLOPE_CELL] = Region("Thieves Hideout Steep Slope Cell", SCENE_THIEVES_HIDEOUT, { //Events - EventAccess(&logic->THCouldRescueSlopeCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), - EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && logic->SmallKeys(RR_GF_OUTSKIRTS, 4) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}), + EventAccess(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}), + EventAccess(LOGIC_TH_RESCUED_ALL_CARPENTERS, []{return logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER);}), }, { //Locations LOCATION(RC_TH_STEEP_SLOPE_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)), LOCATION(RC_TH_STEEP_SLOPE_RIGHT_POT, logic->CanBreakPots()), LOCATION(RC_TH_STEEP_SLOPE_LEFT_POT, logic->CanBreakPots()), - LOCATION(RC_TH_FREED_CARPENTERS, logic->THRescuedAllCarpenters), + LOCATION(RC_TH_FREED_CARPENTERS, logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS)), }, { //Exits Entrance(RR_GF_ABOVE_GTG, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp index 3a626a2f9..5202e7fff 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp @@ -7,18 +7,18 @@ void RegionTable_Init_ZorasDomain() { // clang-format off areaTable[RR_ZORAS_DOMAIN] = Region("Zoras Domain", SCENE_ZORAS_DOMAIN, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(&logic->NutPot, []{return true;}), - EventAccess(&logic->StickPot, []{return logic->IsChild;}), - EventAccess(&logic->FishGroup, []{return logic->IsChild;}), - EventAccess(&logic->KingZoraThawed, []{return logic->IsAdult && logic->BlueFire();}), - EventAccess(&logic->DeliverLetter, []{return logic->CanUse(RG_RUTOS_LETTER) && logic->IsChild && ctx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN);}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_NUT_POT, []{return true;}), + EventAccess(LOGIC_STICK_POT, []{return logic->IsChild;}), + EventAccess(LOGIC_FISH_GROUP, []{return logic->IsChild;}), + EventAccess(LOGIC_KING_ZORA_THAWED, []{return logic->IsAdult && logic->BlueFire();}), + EventAccess(LOGIC_DELIVER_RUTOS_LETTER, []{return logic->CanUse(RG_RUTOS_LETTER) && logic->IsChild && ctx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN);}), }, { //Locations LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->IsChild), LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS)), - LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->KingZoraThawed), - LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->IsAdult && logic->KingZoraThawed && logic->CanUse(RG_PRESCRIPTION)), + LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED)), + LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED) && logic->CanUse(RG_PRESCRIPTION)), LOCATION(RC_ZD_GS_FROZEN_WATERFALL, logic->IsAdult && (logic->HookshotOrBoomerang() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || (logic->CanUse(RG_MAGIC_SINGLE) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (ctx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), LOCATION(RC_ZD_FISH_1, logic->IsChild && logic->HasBottle()), LOCATION(RC_ZD_FISH_2, logic->IsChild && logic->HasBottle()), @@ -39,7 +39,7 @@ void RegionTable_Init_ZorasDomain() { //Exits Entrance(RR_ZR_BEHIND_WATERFALL, []{return true;}), Entrance(RR_LH_FROM_SHORTCUT, []{return logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS));}), - Entrance(RR_ZD_BEHIND_KING_ZORA, []{return logic->DeliverLetter || ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && logic->IsAdult) || (ctx->GetTrickOption(RT_ZD_KING_ZORA_SKIP) && logic->IsAdult);}), + Entrance(RR_ZD_BEHIND_KING_ZORA, []{return logic->Get(LOGIC_DELIVER_RUTOS_LETTER) || ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && logic->IsAdult) || (ctx->GetTrickOption(RT_ZD_KING_ZORA_SKIP) && logic->IsAdult);}), Entrance(RR_ZD_SHOP, []{return logic->IsChild || logic->BlueFire();}), Entrance(RR_ZORAS_DOMAIN_ISLAND, []{return true;}), }); @@ -52,13 +52,13 @@ void RegionTable_Init_ZorasDomain() { areaTable[RR_ZD_BEHIND_KING_ZORA] = Region("ZD Behind King Zora", SCENE_ZORAS_DOMAIN, { //Events - EventAccess(&logic->KingZoraThawed, []{return logic->IsAdult && logic->BlueFire();}), + EventAccess(LOGIC_KING_ZORA_THAWED, []{return logic->IsAdult && logic->BlueFire();}), }, { //Locations LOCATION(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, logic->IsChild && logic->CanBreakUpperBeehives()), }, { //Exits - Entrance(RR_ZORAS_DOMAIN, []{return logic->DeliverLetter || ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && logic->IsAdult);}), + Entrance(RR_ZORAS_DOMAIN, []{return logic->Get(LOGIC_DELIVER_RUTOS_LETTER) || ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && logic->IsAdult);}), Entrance(RR_ZORAS_FOUNTAIN, []{return true;}), }); @@ -79,7 +79,7 @@ void RegionTable_Init_ZorasDomain() { areaTable[RR_ZD_STORMS_GROTTO] = Region("ZD Storms Grotto", SCENE_GROTTOS, { //Events - EventAccess(&logic->FreeFairies, []{return true;}), + EventAccess(LOGIC_FREE_FAIRIES, []{return true;}), }, { //Locations LOCATION(RC_ZD_FAIRY_GROTTO_FAIRY_1, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index e1062caf9..0a8a1d2bc 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -7,11 +7,11 @@ void RegionTable_Init_ZorasFountain() { // clang-format off areaTable[RR_ZORAS_FOUNTAIN] = Region("Zoras Fountain", SCENE_ZORAS_FOUNTAIN, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), }, { //Locations - LOCATION(RC_ZF_GS_TREE, logic->IsChild), + LOCATION(RC_ZF_GS_TREE, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_ZF_GS_ABOVE_THE_LOG, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), @@ -23,6 +23,7 @@ void RegionTable_Init_ZorasFountain() { LOCATION(RC_ZF_NEAR_JABU_POT_2, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_NEAR_JABU_POT_3, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_NEAR_JABU_POT_4, logic->IsChild && logic->CanBreakPots()), + LOCATION(RC_ZF_TREE, logic->IsChild && logic->CanBonkTrees()), }, { //Exits Entrance(RR_ZD_BEHIND_KING_ZORA, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp index 5473ee2ca..bfd228523 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -7,7 +7,7 @@ void RegionTable_Init_ZoraRiver() { // clang-format off areaTable[RR_ZR_FRONT] = Region("ZR Front", SCENE_ZORAS_RIVER, {}, { //Locations - LOCATION(RC_ZR_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)), + LOCATION(RC_ZR_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanBonkTrees()), LOCATION(RC_ZR_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_ZR_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_ZR_GRASS_3, logic->CanCutShrubs()), @@ -20,6 +20,7 @@ void RegionTable_Init_ZoraRiver() { LOCATION(RC_ZR_GRASS_10, logic->CanCutShrubs()), LOCATION(RC_ZR_GRASS_11, logic->CanCutShrubs()), LOCATION(RC_ZR_GRASS_12, logic->CanCutShrubs()), + LOCATION(RC_ZR_TREE, logic->IsChild && logic->CanBonkTrees()), }, { //Exits Entrance(RR_ZORAS_RIVER, []{return logic->IsAdult || logic->BlastOrSmash();}), @@ -28,13 +29,13 @@ void RegionTable_Init_ZoraRiver() { areaTable[RR_ZORAS_RIVER] = Region("Zora River", SCENE_ZORAS_RIVER, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}), - EventAccess(&logic->BugShrub, []{return logic->CanCutShrubs();}), + EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_BUG_SHRUB, []{return logic->CanCutShrubs();}), }, { //Locations - LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->HasItem(RG_CHILD_WALLET) && logic->IsChild), + LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->IsChild), LOCATION(RC_ZR_FROGS_OCARINA_GAME, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanUse(RG_SARIAS_SONG) && logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_ZR_FROGS_IN_THE_RAIN, logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_ZR_FROGS_ZELDAS_LULLABY, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY)), @@ -103,7 +104,7 @@ void RegionTable_Init_ZoraRiver() { areaTable[RR_ZR_FAIRY_GROTTO] = Region("ZR Fairy Grotto", SCENE_GROTTOS, { //Event - EventAccess(&logic->FreeFairies, []{return true;}), + EventAccess(LOGIC_FREE_FAIRIES, []{return true;}), }, { //Locations LOCATION(RC_ZR_FAIRY_GROTTO_FAIRY_1, true), diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 2fea752cc..e13e2f5b3 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -104,10 +104,40 @@ std::vector Rando::StaticData::GetAllDungeonLocations() { return dungeonLocations; } -std::vector Rando::StaticData::GetOverworldFairyLocations() { +std::vector Rando::StaticData::GetFountainFairyLocations() { std::vector fairyLocations = {}; for (Location& location : locationTable) { - if (location.GetRCType() == RCTYPE_FAIRY && location.GetRandomizerCheck() != RC_UNKNOWN_CHECK) { + if (location.GetRCType() == RCTYPE_FOUNTAIN_FAIRY && location.GetRandomizerCheck() != RC_UNKNOWN_CHECK) { + fairyLocations.push_back(location.GetRandomizerCheck()); + } + } + return fairyLocations; +} + +std::vector Rando::StaticData::GetStoneFairyLocations() { + std::vector fairyLocations = {}; + for (Location& location : locationTable) { + if (location.GetRCType() == RCTYPE_STONE_FAIRY && location.GetRandomizerCheck() != RC_UNKNOWN_CHECK) { + fairyLocations.push_back(location.GetRandomizerCheck()); + } + } + return fairyLocations; +} + +std::vector Rando::StaticData::GetBeanFairyLocations() { + std::vector fairyLocations = {}; + for (Location& location : locationTable) { + if (location.GetRCType() == RCTYPE_BEAN_FAIRY && location.GetRandomizerCheck() != RC_UNKNOWN_CHECK) { + fairyLocations.push_back(location.GetRandomizerCheck()); + } + } + return fairyLocations; +} + +std::vector Rando::StaticData::GetSongFairyLocations() { + std::vector fairyLocations = {}; + for (Location& location : locationTable) { + if (location.GetRCType() == RCTYPE_SONG_FAIRY && location.GetRandomizerCheck() != RC_UNKNOWN_CHECK) { fairyLocations.push_back(location.GetRandomizerCheck()); } } diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index eea79e92d..17a665624 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -13,7 +13,7 @@ #include "macros.h" #include "variables.h" #include -#include "StringHelper.h" +#include #include "soh/resource/type/Scene.h" #include "soh/resource/type/scenecommand/SetTransitionActorList.h" #include "src/overlays/actors/ovl_En_Door/z_en_door.h" @@ -56,7 +56,8 @@ bool Logic::HasItem(RandomizerGet itemName) { case RG_BOMBCHU_5: case RG_BOMBCHU_10: case RG_BOMBCHU_20: - return (BombchusEnabled() && (GetInLogic(LOGIC_BUY_BOMBCHUS) || CouldPlayBowling || CarpetMerchant)) || + return (BombchusEnabled() && + (Get(LOGIC_BUY_BOMBCHUS) || Get(LOGIC_COULD_PLAY_BOWLING) || Get(LOGIC_CARPET_MERCHANT))) || CheckInventory(ITEM_BOMBCHU, true); case RG_FAIRY_SLINGSHOT: return CheckInventory(ITEM_SLINGSHOT, true); @@ -173,7 +174,7 @@ bool Logic::HasItem(RandomizerGet itemName) { return CheckRandoInf(RandoGetToRandInf.at(itemName)); // Boss Keys case RG_EPONA: - return FreedEpona; + return Get(LOGIC_FREED_EPONA); case RG_FOREST_TEMPLE_BOSS_KEY: case RG_FIRE_TEMPLE_BOSS_KEY: case RG_WATER_TEMPLE_BOSS_KEY: @@ -263,7 +264,7 @@ bool Logic::CanUse(RandomizerGet itemName) { switch (itemName) { // Magic items case RG_MAGIC_SINGLE: - return AmmoCanDrop || (HasBottle() && GetInLogic(LOGIC_BUY_MAGIC_POTION)); + return true; // AmmoCanDrop || (HasBottle() && Get(LOGIC_BUY_MAGIC_POTION)) case RG_DINS_FIRE: case RG_FARORES_WIND: case RG_NAYRUS_LOVE: @@ -277,7 +278,7 @@ bool Logic::CanUse(RandomizerGet itemName) { // Adult items // TODO: Uncomment those if we ever implement more item usability settings case RG_FAIRY_BOW: - return IsAdult && (AmmoCanDrop || GetInLogic(LOGIC_BUY_ARROW)); // || BowAsChild; + return IsAdult; // || BowAsChild && (AmmoCanDrop || Get(LOGIC_BUY_ARROW)); case RG_MEGATON_HAMMER: return IsAdult; // || HammerAsChild; case RG_IRON_BOOTS: @@ -316,20 +317,21 @@ bool Logic::CanUse(RandomizerGet itemName) { // Child items case RG_FAIRY_SLINGSHOT: - return IsChild && (AmmoCanDrop || GetInLogic(LOGIC_BUY_SEED)); // || SlingshotAsAdult; + return IsChild; // || SlingshotAsAdult && (AmmoCanDrop || Get(LOGIC_LOGIC_BUY_SEED)); case RG_BOOMERANG: return IsChild; // || BoomerangAsAdult; case RG_KOKIRI_SWORD: return IsChild; // || KokiriSwordAsAdult; case RG_NUTS: - return ((NutPot || NutCrate || DekuBabaNuts) && AmmoCanDrop) || GetInLogic(LOGIC_BUY_NUTS); + return Get(LOGIC_NUT_POT) || Get(LOGIC_NUT_CRATE) || Get(LOGIC_DEKU_BABA_NUTS) || Get(LOGIC_BUY_NUTS); case RG_STICKS: - return IsChild /* || StickAsAdult;*/ && (StickPot || DekuBabaSticks || GetInLogic(LOGIC_BUY_STICKS)); + return IsChild /* || StickAsAdult;*/ && + (Get(LOGIC_STICK_POT) || Get(LOGIC_DEKU_BABA_STICKS) || Get(LOGIC_BUY_STICKS)); case RG_DEKU_SHIELD: return IsChild; // || DekuShieldAsAdult; case RG_PROGRESSIVE_BOMB_BAG: case RG_BOMB_BAG: - return AmmoCanDrop || GetInLogic(LOGIC_BUY_BOMB); + return true; // AmmoCanDrop || Get(LOGIC_BUY_BOMB) case RG_PROGRESSIVE_BOMBCHUS: case RG_BOMBCHU_5: case RG_BOMBCHU_10: @@ -377,15 +379,16 @@ bool Logic::CanUse(RandomizerGet itemName) { // Bottle Items case RG_BOTTLE_WITH_BUGS: - return BugShrub || WanderingBugs || BugRock || GetInLogic(LOGIC_BUGS_ACCESS); + return Get(LOGIC_BUG_SHRUB) || Get(LOGIC_WANDERING_BUGS) || Get(LOGIC_BUG_ROCK) || Get(LOGIC_BUGS_ACCESS); case RG_BOTTLE_WITH_FISH: - return LoneFish || FishGroup || - GetInLogic(LOGIC_FISH_ACCESS); // is there any need to care about lone vs group? - case RG_BOTTLE_WITH_BLUE_FIRE: // RANDOTODO should probably be better named - return BlueFireAccess || GetInLogic(LOGIC_BLUE_FIRE_ACCESS); + return Get(LOGIC_LONE_FISH) || Get(LOGIC_FISH_GROUP) || + Get(LOGIC_FISH_ACCESS); // is there any need to care about lone vs group? + case RG_BOTTLE_WITH_BLUE_FIRE: // RANDOTODO should probably be better named + return Get(LOGIC_BLUE_FIRE_ACCESS); case RG_BOTTLE_WITH_FAIRY: - return FairyPot || GossipStoneFairy || BeanPlantFairy || ButterflyFairy || FreeFairies || FairyPond || - GetInLogic(LOGIC_FAIRY_ACCESS); + return Get(LOGIC_FAIRY_POT) || Get(LOGIC_GOSSIP_STONE_FAIRY) || Get(LOGIC_BEAN_PLANT_FAIRY) || + Get(LOGIC_BUTTERFLY_FAIRY) || Get(LOGIC_FREE_FAIRIES) || Get(LOGIC_FAIRY_POND) || + Get(LOGIC_FAIRY_ACCESS); default: SPDLOG_ERROR("CanUse reached `default` for {}. Assuming intention is no extra requirements for use so " @@ -441,6 +444,11 @@ bool Logic::CanOpenOverworldDoor(RandomizerGet key) { return HasItem(key); } +bool Logic::CanGroundJump(bool hasBombflower) { + return ctx->GetTrickOption(RT_GROUND_JUMP) && CanStandingShield() && + (CanUse(RG_BOMB_BAG) || (hasBombflower && HasItem(RG_GORONS_BRACELET))); +} + bool Logic::CanOpenUnderwaterChest() { return ctx->GetTrickOption(RT_OPEN_UNDERWATER_CHEST) && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT); } @@ -996,17 +1004,17 @@ bool Logic::MQWaterLevel(RandoWaterLevel level) { // WL_LOW in logic. Alternativly a way to reach WL_LOW from WL_MID could exist, but all glitchless methods need // you to do a Low-locked action case WL_LOW: - return (CanWaterTempleHigh && CanWaterTempleLowFromHigh) || - (CanWaterTempleLowFromMid && CanWaterTempleLowFromHigh); + return (Get(LOGIC_WATER_HIGH) && Get(LOGIC_WATER_LOW_FROM_HIGH)) || + (Get(LOGIC_WATER_LOW_FROM_MID) && Get(LOGIC_WATER_LOW_FROM_HIGH)); case WL_LOW_OR_MID: - return (CanWaterTempleHigh && CanWaterTempleLowFromHigh) || - (CanWaterTempleLowFromHigh && CanWaterTempleMiddle) || - (CanWaterTempleLowFromMid && CanWaterTempleLowFromHigh); + return (Get(LOGIC_WATER_HIGH) && Get(LOGIC_WATER_LOW_FROM_HIGH)) || + (Get(LOGIC_WATER_LOW_FROM_HIGH) && Get(LOGIC_WATER_MIDDLE)) || + (Get(LOGIC_WATER_LOW_FROM_MID) && Get(LOGIC_WATER_LOW_FROM_HIGH)); // If we can set it to High out of logic we can just repeat what we did to lower the water in the first place as // High is the default. Because of this you only need to be able to use the Low and Mid Emblems, WL_LOW could be // skipped if it was ever possible to play ZL underwater. case WL_MID: - return CanWaterTempleLowFromHigh && CanWaterTempleMiddle; + return Get(LOGIC_WATER_LOW_FROM_HIGH) && Get(LOGIC_WATER_MIDDLE); // Despite being the initial state of water temple, WL_HIGH has the extra requirement of making sure that, if we // were to lower the water out of logic, we could put it back to WL_HIGH However because it is the default // state, we do not need to check if we can actually change the water level, only to make sure we can return to @@ -1016,9 +1024,9 @@ bool Logic::MQWaterLevel(RandoWaterLevel level) { // but we assume the water is WL_MID (as if we can set it to WL_LOW, we can set it to WL_MID, as Mid Emblem has // no requirements) The latter check can be assumed for now but will want a revisit once OI tricks are added. case WL_HIGH: - return ReachedWaterHighEmblem; + return Get(LOGIC_WATER_REACHED_HIGH_EMBLEM); case WL_HIGH_OR_MID: - return ReachedWaterHighEmblem || (CanWaterTempleLowFromHigh && CanWaterTempleMiddle); + return Get(LOGIC_WATER_REACHED_HIGH_EMBLEM) || (Get(LOGIC_WATER_LOW_FROM_HIGH) && Get(LOGIC_WATER_MIDDLE)); } SPDLOG_ERROR("MQWaterLevel reached `return false;`. Missing case for a Water Level"); assert(false); @@ -1034,12 +1042,12 @@ uint8_t Logic::BottleCount() { uint8_t item = GetSaveContext()->inventory.items[i]; switch (item) { case ITEM_LETTER_RUTO: - if (DeliverLetter) { + if (Get(LOGIC_DELIVER_RUTOS_LETTER)) { count++; } break; case ITEM_BIG_POE: - if (CanEmptyBigPoes) { + if (Get(LOGIC_CAN_EMPTY_BIG_POES)) { count++; } break; @@ -1123,7 +1131,7 @@ bool Logic::BombchusEnabled() { // TODO: Implement Ammo Drop Setting in place of bombchu drops bool Logic::BombchuRefill() { - return GetInLogic(LOGIC_BUY_BOMBCHUS) || CouldPlayBowling || CarpetMerchant || + return Get(LOGIC_BUY_BOMBCHUS) || Get(LOGIC_COULD_PLAY_BOWLING) || Get(LOGIC_CARPET_MERCHANT) || (ctx->GetOption(RSK_ENABLE_BOMBCHU_DROPS).Is(RO_AMMO_DROPS_ON /*_PLUS_BOMBCHU*/)); } @@ -1133,7 +1141,7 @@ bool Logic::HookshotOrBoomerang() { bool Logic::ScarecrowsSong() { return (ctx->GetOption(RSK_SKIP_SCARECROWS_SONG) && HasItem(RG_FAIRY_OCARINA) && OcarinaButtons() >= 2) || - (ChildScarecrow && AdultScarecrow); + (Get(LOGIC_CHILD_SCARECROW) && Get(LOGIC_ADULT_SCARECROW)); } bool Logic::BlueFire() { @@ -1152,6 +1160,10 @@ bool Logic::CanBreakSmallCrates() { return true; } +bool Logic::CanBonkTrees() { + return true; +} + bool Logic::HasExplosives() { return CanUse(RG_BOMB_BAG) || CanUse(RG_BOMBCHU_5); } @@ -1213,8 +1225,9 @@ uint8_t Logic::Hearts() { } uint8_t Logic::DungeonCount() { - return DekuTreeClear + DodongosCavernClear + JabuJabusBellyClear + ForestTempleClear + FireTempleClear + - WaterTempleClear + SpiritTempleClear + ShadowTempleClear; + return Get(LOGIC_DEKU_TREE_CLEAR) + Get(LOGIC_DODONGOS_CAVERN_CLEAR) + Get(LOGIC_JABU_JABUS_BELLY_CLEAR) + + Get(LOGIC_FOREST_TEMPLE_CLEAR) + Get(LOGIC_FIRE_TEMPLE_CLEAR) + Get(LOGIC_WATER_TEMPLE_CLEAR) + + Get(LOGIC_SPIRIT_TEMPLE_CLEAR) + Get(LOGIC_SHADOW_TEMPLE_CLEAR); } uint8_t Logic::StoneCount() { @@ -1253,7 +1266,8 @@ bool Logic::CanGetNightTimeGS() { } bool Logic::CanBreakUpperBeehives() { - return HookshotOrBoomerang() || (ctx->GetTrickOption(RT_BOMBCHU_BEEHIVES) && CanUse(RG_BOMBCHU_5)); + return HookshotOrBoomerang() || (ctx->GetTrickOption(RT_BOMBCHU_BEEHIVES) && CanUse(RG_BOMBCHU_5)) || + (ctx->GetOption(RSK_SLINGBOW_BREAK_BEEHIVES) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT))); } bool Logic::CanBreakLowerBeehives() { @@ -1366,80 +1380,11 @@ bool Logic::CanTriggerLACS() { (ctx->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get()); } -bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) { - return SmallKeys(dungeon, requiredAmount, requiredAmount); -} - -bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched) { +bool Logic::SmallKeys(s16 scene, uint8_t requiredAmount) { if (HasItem(RG_SKELETON_KEY)) { return true; } - switch (dungeon) { - case RR_FOREST_TEMPLE: - /*if (IsGlitched && (GetDifficultyValueFromString(GlitchHookshotJump_Boots) >= - static_cast(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHoverBoost) >= - static_cast(GlitchDifficulty::NOVICE) || (GetDifficultyValueFromString(GlitchHover) >= - static_cast(GlitchDifficulty::NOVICE) && GetDifficultyValueFromString(GlitchISG) >= - static_cast(GlitchDifficulty::INTERMEDIATE)))) { return ForestTempleKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_FOREST_TEMPLE) >= requiredAmountGlitchless; - - case RR_FIRE_TEMPLE: - /*if (IsGlitched && (GetDifficultyValueFromString(GlitchLedgeClip) >= - static_cast(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHover) >= - static_cast(GlitchDifficulty::INTERMEDIATE))) { return FireTempleKeys >= requiredAmountGlitched; - }*/ - // If the Fire Temple loop lock is removed, Small key Count is set to 1 before starting - return GetSmallKeyCount(SCENE_FIRE_TEMPLE) >= requiredAmountGlitchless; - - case RR_WATER_TEMPLE: - /*if (IsGlitched && (false)) { - return WaterTempleKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_WATER_TEMPLE) >= requiredAmountGlitchless; - - case RR_SPIRIT_TEMPLE: - /*if (IsGlitched && (false)) { - return SpiritTempleKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_SPIRIT_TEMPLE) >= requiredAmountGlitchless; - - case RR_SHADOW_TEMPLE: - /*if (IsGlitched && (GetDifficultyValueFromString(GlitchHookshotClip) >= - static_cast(GlitchDifficulty::NOVICE))) { return ShadowTempleKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_SHADOW_TEMPLE) >= requiredAmountGlitchless; - - case RR_BOTTOM_OF_THE_WELL: - /*if (IsGlitched && (false)) { - return BottomOfTheWellKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_BOTTOM_OF_THE_WELL) >= requiredAmountGlitchless; - - case RR_GERUDO_TRAINING_GROUND: - /*if (IsGlitched && (false)) { - return GerudoTrainingGroundsKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_GERUDO_TRAINING_GROUND) >= requiredAmountGlitchless; - - case RR_GANONS_CASTLE: - /*if (IsGlitched && (false)) { - return GanonsCastleKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_INSIDE_GANONS_CASTLE) >= requiredAmountGlitchless; - - case RR_MARKET_TREASURE_CHEST_GAME: - /*if (IsGlitched && (false)) { - return TreasureGameKeys >= requiredAmountGlitched; - }*/ - return GetSmallKeyCount(SCENE_TREASURE_BOX_SHOP) >= requiredAmountGlitchless; - - case RR_GF_OUTSKIRTS: - return GetSmallKeyCount(SCENE_THIEVES_HIDEOUT) >= requiredAmountGlitchless; - - default: - return false; - } + return GetSmallKeyCount(scene) >= requiredAmount; } std::map Logic::RandoGetToEquipFlag = { @@ -2228,7 +2173,7 @@ const std::vector& GetDungeonSmallKeyDoors(SceneID sceneId) { } } else if (transitionActor.id == ACTOR_DOOR_SHUTTER) { uint8_t doorType = (transitionActor.params >> 7) & 15; - if (doorType == SHUTTER_BACK_LOCKED || doorType == SHUTTER_BOSS || doorType == SHUTTER_KEY_LOCKED) { + if (doorType == SHUTTER_KEY_LOCKED) { dungeonSmallKeyDoors[key].emplace_back(transitionActor.params & 0x3F); } } @@ -2324,58 +2269,26 @@ void Logic::SetContext(std::shared_ptr _ctx) { ctx = _ctx; } -bool Logic::GetInLogic(LogicVal logicVal) { +bool Logic::Get(LogicVal logicVal) { return inLogic[logicVal]; } -void Logic::SetInLogic(LogicVal logicVal, bool value) { +void Logic::Set(LogicVal logicVal, bool value) { inLogic[logicVal] = value; } +bool Logic::IsFireLoopLocked() { + return ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || + ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) || + ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON); +} + void Logic::Reset(bool resetSaveContext /*= true*/) { if (resetSaveContext) { NewSaveContext(); } StartPerformanceTimer(PT_LOGIC_RESET); memset(inLogic, false, sizeof(inLogic)); - // Settings-dependent variables - IsFireLoopLocked = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || - ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) || - ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON); - - // AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting - - // Mask quest - CanBorrowMasks = false; - BorrowSkullMask = false; - BorrowSpookyMask = false; - BorrowBunnyHood = false; - BorrowRightMasks = false; - - // Adult logic - FreedEpona = false; - // BigPoe = false; - - // Trade Quest Events - WakeUpAdultTalon = false; - - // Dungeon Clears - DekuTreeClear = false; - DodongosCavernClear = false; - JabuJabusBellyClear = false; - ForestTempleClear = false; - FireTempleClear = false; - WaterTempleClear = false; - SpiritTempleClear = false; - ShadowTempleClear = false; - - // Trial Clears - ForestTrialClear = false; - FireTrialClear = false; - WaterTrialClear = false; - SpiritTrialClear = false; - ShadowTrialClear = false; - LightTrialClear = false; if (resetSaveContext) { // Ocarina C Buttons @@ -2407,130 +2320,28 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { // If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in // vanilla FiT - if (!IsFireLoopLocked && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { + if (!IsFireLoopLocked() && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1); } } - // Bottle Count Bottles = 0; NumBottles = 0; - CanEmptyBigPoes = false; - - // Drops and Bottle Contents Access - NutPot = false; - NutCrate = false; - DekuBabaNuts = false; - StickPot = false; - DekuBabaSticks = false; - BugShrub = false; - WanderingBugs = false; - BugRock = false; - BlueFireAccess = false; - FishGroup = false; - LoneFish = false; - GossipStoneFairy = false; - BeanPlantFairy = false; - ButterflyFairy = false; - FairyPot = false; - FreeFairies = false; - FairyPond = false; - PieceOfHeart = 0; HeartContainer = 0; - /* --- HELPERS, EVENTS, AND LOCATION ACCESS --- */ - /* These are used to simplify reading the logic, but need to be updated - / every time a base value is updated. */ - - ChildScarecrow = false; - AdultScarecrow = false; - - CouldPlayBowling = false; IsChild = false; IsAdult = false; - // CanPlantBean = false; - BigPoeKill = false; BigPoes = 0; BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() + 1; - // Bridge Requirements - BuiltRainbowBridge = false; - - // Other AtDay = false; AtNight = false; if (resetSaveContext) { GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get(); } - // Events - ShowedMidoSwordAndShield = false; - THCouldFree1TorchCarpenter = false; - THCouldFreeDoubleCellCarpenter = false; - TH_CouldFreeDeadEndCarpenter = false; - THCouldRescueSlopeCarpenter = false; - GF_GateOpen = false; - GtG_GateOpen = false; - DampesWindmillAccess = false; - DrainWell = false; - GoronCityChildFire = false; - GCWoodsWarpOpen = false; - GCDaruniasDoorOpenChild = false; - StopGCRollingGoronAsAdult = false; - CanWaterTempleLowFromHigh = false; - CanWaterTempleLowFromMid = false; - CanWaterTempleMiddle = false; - CanWaterTempleHigh = false; - KakarikoVillageGateOpen = false; - KingZoraThawed = false; - ForestTempleJoelle = false; - ForestTempleBeth = false; - ForestTempleAmy = false; - ForestTempleMeg = false; - FireLoopSwitch = false; - LinksCow = false; - DeliverLetter = false; - ClearMQDCUpperLobbyRocks = false; - LoweredWaterInsideBotw = false; - OpenedWestRoomMQBotw = false; - OpenedMiddleHoleMQBotw = false; - BrokeDeku1FWeb = false; - ClearedMQDekuSERoom = false; - MQDekuWaterRoomTorches = false; - PushedDekuBasementBlock = false; - OpenedLowestGoronCage = false; - OpenedUpperFireShortcut = false; - HitFireTemplePlatform = false; - OpenedFireMQFireMazeDoor = false; - MQForestBlockRoomTargets = false; - ForestCanTwistHallway = false; - ForestClearBelowBowChest = false; - ForestOpenBossCorridor = false; - ShadowTrialFirstChest = false; - MQGTGMazeSwitch = false; - MQGTGRightSideSwitch = false; - GTGPlatformSilverRupees = false; - MQJabuHolesRoomDoor = false; - JabuWestTentacle = false; - JabuEastTentacle = false; - JabuNorthTentacle = false; - LoweredJabuPath = false; - MQJabuLiftRoomCow = false; - MQShadowFloorSpikeRupees = false; - ShadowShortcutBlock = false; - MQWaterStalfosPit = false; - MQWaterDragonTorches = false; - MQWaterB1Switch = false; - // MQWaterPillarSoTBlock = false; - MQWaterOpenedPillarB1 = false; - MQSpiritCrawlBoulder = false; - MQSpiritMapRoomEnemies = false; - MQSpirit3SunsEnemies = false; - Spirit1FSilverRupees = false; - JabuRutoIn1F = false; - CalculatingAvailableChecks = false; StopPerformanceTimer(PT_LOGIC_RESET); diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 2bfea75e9..508db91ba 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -18,172 +18,19 @@ enum class GlitchType { EquipSwap, }; -enum class GlitchDifficulty { - NOVICE = 1, - INTERMEDIATE, - ADVANCED, - EXPERT, - HERO, -}; - class Logic { public: - bool noVariable = false; - - // Mask Quest - bool CanBorrowMasks = false; - bool BorrowSkullMask = false; - bool BorrowSpookyMask = false; - bool BorrowBunnyHood = false; - bool BorrowRightMasks = false; - - // Adult logic - bool FreedEpona = false; - - // Trade Quest Events - bool WakeUpAdultTalon = false; - - // Dungeon Clears - bool DekuTreeClear = false; - bool DodongosCavernClear = false; - bool JabuJabusBellyClear = false; - bool ForestTempleClear = false; - bool FireTempleClear = false; - bool WaterTempleClear = false; - bool SpiritTempleClear = false; - bool ShadowTempleClear = false; - - // Trial Clears - bool ForestTrialClear = false; - bool FireTrialClear = false; - bool WaterTrialClear = false; - bool SpiritTrialClear = false; - bool ShadowTrialClear = false; - bool LightTrialClear = false; - - // Logical keysanity - bool IsFireLoopLocked = false; - - // Bottle Count uint8_t Bottles = 0; uint8_t NumBottles = 0; - // this event covers if the player can currently empty big poes in logic - bool CanEmptyBigPoes = false; - - // Drops and Bottle Contents Access - bool NutPot = false; - bool NutCrate = false; - bool DekuBabaNuts = false; - bool StickPot = false; - bool DekuBabaSticks = false; - bool BugShrub = false; - bool WanderingBugs = false; - bool BugRock = false; - bool BlueFireAccess = false; - bool FishGroup = false; - bool LoneFish = false; - bool GossipStoneFairy = false; - bool BeanPlantFairy = false; - bool ButterflyFairy = false; - bool FairyPot = false; - bool FreeFairies = false; - bool FairyPond = false; - bool AmmoCanDrop = true; - uint8_t PieceOfHeart = 0; uint8_t HeartContainer = 0; - - bool ChildScarecrow = false; - bool AdultScarecrow = false; - - bool CarpetMerchant = false; - bool CouldPlayBowling = false; bool IsChild = false; bool IsAdult = false; - bool BigPoeKill = false; uint8_t BigPoes = 0; uint8_t BaseHearts = 0; - - // Bridge and LACS Requirements - bool BuiltRainbowBridge = false; - - // Other bool AtDay = false; bool AtNight = false; - // Events - bool ShowedMidoSwordAndShield = false; - bool THCouldFree1TorchCarpenter = false; - bool THCouldFreeDoubleCellCarpenter = false; - bool TH_CouldFreeDeadEndCarpenter = false; - bool THCouldRescueSlopeCarpenter = false; - bool THRescuedAllCarpenters = false; - bool GF_GateOpen = false; - bool GtG_GateOpen = false; - bool DampesWindmillAccess = false; - bool DrainWell = false; - bool GoronCityChildFire = false; - bool GCWoodsWarpOpen = false; - bool GCDaruniasDoorOpenChild = false; - bool StopGCRollingGoronAsAdult = false; - bool CanWaterTempleLowFromHigh = false; - bool CanWaterTempleMiddle = false; - bool CanWaterTempleHigh = false; - bool CanWaterTempleLowFromMid = false; - bool CouldWaterTempleLow = false; - bool CouldWaterTempleMiddle = false; - bool ReachedWaterHighEmblem = false; - bool KakarikoVillageGateOpen = false; - bool KingZoraThawed = false; - bool ForestTempleJoelle = false; - bool ForestTempleBeth = false; - bool ForestTempleAmy = false; - bool ForestTempleMeg = false; - bool FireLoopSwitch = false; - bool LinksCow = false; - bool DeliverLetter = false; - bool ClearMQDCUpperLobbyRocks = false; - bool LoweredWaterInsideBotw = false; - bool OpenedWestRoomMQBotw = false; - bool OpenedMiddleHoleMQBotw = false; - bool BrokeDeku1FWeb = false; - bool ClearedMQDekuSERoom = false; - bool MQDekuWaterRoomTorches = false; - bool PushedDekuBasementBlock = false; - bool OpenedLowestGoronCage = false; - bool OpenedUpperFireShortcut = false; - bool HitFireTemplePlatform = false; - bool OpenedFireMQFireMazeDoor = false; - bool MQForestBlockRoomTargets = false; - bool ForestCanTwistHallway = false; - bool ForestClearBelowBowChest = false; // a better name that covers both versions would be nice - bool ForestOpenBossCorridor = false; - bool ShadowTrialFirstChest = false; - bool MQGTGMazeSwitch = false; - bool MQGTGRightSideSwitch = false; - bool GTGPlatformSilverRupees = false; - bool MQJabuHolesRoomDoor = false; - bool JabuWestTentacle = false; - bool JabuEastTentacle = false; - bool JabuNorthTentacle = false; - bool LoweredJabuPath = false; - bool MQJabuLiftRoomCow = false; - bool MQShadowFloorSpikeRupees = false; - bool ShadowShortcutBlock = false; - bool MQWaterStalfosPit = false; - bool MQWaterDragonTorches = false; - bool MQWaterB1Switch = false; - // bool MQWaterPillarSoTBlock = false; should be irrelevant. SHOULD. - bool MQWaterOpenedPillarB1 = false; - bool MQSpiritCrawlBoulder = false; - bool MQSpiritMapRoomEnemies = false; - bool MQSpiritTimeTravelChest = false; - bool MQSpirit3SunsEnemies = false; - bool Spirit1FSilverRupees = false; - bool JabuRutoIn1F = false; - - /* --- END OF HELPERS AND LOCATION ACCESS --- */ - bool CalculatingAvailableChecks = false; bool ACProcessUndiscoveredExits = false; @@ -194,8 +41,8 @@ class Logic { bool HasItem(RandomizerGet itemName); bool HasBossSoul(RandomizerGet itemName); bool CanOpenOverworldDoor(RandomizerGet itemName); - bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount); - bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched); + bool SmallKeys(s16 scene, uint8_t requiredAmount); + bool CanGroundJump(bool hasBombflower = false); bool CanOpenUnderwaterChest(); bool CanDoGlitch(GlitchType glitch); bool CanEquipSwap(RandomizerGet itemName); @@ -249,6 +96,7 @@ class Logic { bool CanBreakPots(); bool CanBreakCrates(); bool CanBreakSmallCrates(); + bool CanBonkTrees(); bool HasFireSource(); bool HasFireSourceWithTorch(); bool TradeQuestStep(RandomizerGet rg); @@ -257,10 +105,11 @@ class Logic { bool CanUseProjectile(); bool CanBuildRainbowBridge(); bool CanTriggerLACS(); + bool IsFireLoopLocked(); void Reset(bool resetSaveContext = true); void SetContext(std::shared_ptr _ctx); - bool GetInLogic(LogicVal logicVal); - void SetInLogic(LogicVal logicVal, bool remove); + bool Get(LogicVal logicVal); + void Set(LogicVal logicVal, bool remove); void ApplyItemEffect(Item& item, bool state); uint8_t InventorySlot(uint32_t item); void SetUpgrade(uint32_t upgrade, uint8_t level); diff --git a/soh/soh/Enhancements/randomizer/option.cpp b/soh/soh/Enhancements/randomizer/option.cpp index f027fd066..bfdecd861 100644 --- a/soh/soh/Enhancements/randomizer/option.cpp +++ b/soh/soh/Enhancements/randomizer/option.cpp @@ -1,6 +1,6 @@ #include "option.h" #include "libultraship/bridge.h" -#include +#include #include #include "soh/SohGui/SohGui.hpp" #include "soh/SohGui/UIWidgets.hpp" diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 50d11d9b2..24e08bd28 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -290,6 +290,11 @@ void Settings::CreateOptionDescriptions() { "Overworld - Only shuffle crates that are outside of dungeons.\n" "\n" "All Crates - Shuffle all crates."; + mOptionDescriptions[RSK_SHUFFLE_TREES] = + "Trees will contain randomized items which are dropped the first time the player rolls into one.\n" + "Trees will have a special appearance when carrying randomized items.\n" + "\nSome trees are dependant on Link's age, such as some trees in Hyrule Field.\nTwo trees at Hyrule Castle are " + "only shuffle with No Logic."; mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n" "\n" "The fishing pole is required to play the fishing pond minigame."; @@ -476,7 +481,15 @@ void Settings::CreateOptionDescriptions() { "Overworld - Only freestanding rupees & hearts that are outside of dungeons.\n" "\n" "All Items - Shuffle all freestanding rupees & hearts."; - mOptionDescriptions[RSK_SHUFFLE_FAIRIES] = "Shuffle fairy locations."; + mOptionDescriptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES] = + "Shuffle fairies in fountain locations. " + "This includes the sets of fairies found in Ganon's Castle and the Desert Oasis."; + mOptionDescriptions[RSK_SHUFFLE_STONE_FAIRIES] = "Shuffle fairies from gossip stone locations."; + mOptionDescriptions[RSK_SHUFFLE_BEAN_FAIRIES] = "Shuffle fairies from magic bean locations."; + mOptionDescriptions[RSK_SHUFFLE_SONG_FAIRIES] = + "Shuffle fairy spots. These are spots where a big fairy is revealed by a song." + "\n" + "This excludes gossip stones and magic bean locations."; mOptionDescriptions[RSK_SHUFFLE_GRASS] = "Grass/Bushes will drop a randomized item the first time they're cut and collected. " "Grass/Bushes will have a different appearance when they hold a randomized item.\n" @@ -684,6 +697,7 @@ void Settings::CreateOptionDescriptions() { "tell you what's the reward for the Hyrule Loach."; mOptionDescriptions[RSK_SARIA_HINT] = "Talking to Saria either in person or through Saria's Song will tell you the " "location of a progressive magic meter."; + mOptionDescriptions[RSK_MIDO_HINT] = "Talking to Mido as child will tell you the location of the Kokiri Sword."; mOptionDescriptions[RSK_FISHING_POLE_HINT] = "Talking to the fishing pond owner without the fishing pole will tell you its location."; mOptionDescriptions[RSK_OOT_HINT] = @@ -742,15 +756,13 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SUNLIGHT_ARROWS] = "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Item placement logic will respect this option, so it might be required to use this to progress."; + mOptionDescriptions[RSK_SLINGBOW_BREAK_BEEHIVES] = + "Allows Slingshot and Bow to break beehives when Beehive Shuffle is turned on."; mOptionDescriptions[RSK_LOGIC_RULES] = "Glitchless - No glitches are required, but may require some minor tricks. Additional tricks may be enabled " "and disabled below.\n" "\n" - //"Glitched - Glitches may be required to beat the game. You can disable and enable glitches below.\n" - //"\n" - "No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT.\n" - "\n" - "Vanilla - Places all items and dungeon rewards in their vanilla locations."; + "No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT."; mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE] = "When this options is enabled, the randomizer will " "guarantee that every item is obtainable and every " "location is reachable. When disabled, only " diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 89ab1e217..d1ddb629d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -27,6 +27,7 @@ #include #include "draw.h" #include "soh/OTRGlobals.h" +#include #include "soh/SohGui/UIWidgets.hpp" #include "static_data.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" @@ -389,6 +390,29 @@ static const char* frenchRupeeNames[39] = { "Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies", }; +bool Rando_HandleSpoilerDrop(char* filePath) { + if (SohUtils::IsStringEmpty(filePath)) { + return false; + } + + try { + std::ifstream stream(filePath); + if (!stream) { + return false; + } + + nlohmann::json json; + stream >> json; + + if (json.contains("version") && json.contains("finalSeed")) { + CVarSetString(CVAR_GENERAL("RandomizerDroppedFile"), filePath); + CVarSetInteger(CVAR_GENERAL("RandomizerNewFileDropped"), 1); + return true; + } + } catch (std::exception& e) {} + return false; +} + Randomizer::Randomizer() { Rando::StaticData::InitItemTable(); Rando::StaticData::InitLocationTable(); @@ -405,6 +429,8 @@ Randomizer::Randomizer() { for (size_t c = 0; c < Rando::StaticData::hintTypeNames.size(); c++) { SpoilerfileHintTypeNameToEnum[Rando::StaticData::hintTypeNames[(HintType)c].GetEnglish(MF_CLEAN)] = (HintType)c; } + + Ship::Context::GetInstance()->GetFileDropMgr()->RegisterDropHandler(Rando_HandleSpoilerDrop); } Randomizer::~Randomizer() { @@ -2334,7 +2360,7 @@ std::map rcToRandomizerInf = { RAND_INF_GF_MID_NORTH_CENTER_CRATE, }, { - RR_GF_NORTHMOST_CENTER_CRATE, + RC_GF_NORTHMOST_CENTER_CRATE, RAND_INF_GF_NORTHMOST_CENTER_CRATE, }, { @@ -3308,6 +3334,69 @@ std::map rcToRandomizerInf = { RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, RAND_INF_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, }, + { RC_MARKET_TREE, RAND_INF_MARKET_TREE }, + { RC_HC_NEAR_GUARDS_TREE_1, RAND_INF_HC_NEAR_GUARDS_TREE_1 }, + { RC_HC_NEAR_GUARDS_TREE_2, RAND_INF_HC_NEAR_GUARDS_TREE_2 }, + { RC_HC_NEAR_GUARDS_TREE_3, RAND_INF_HC_NEAR_GUARDS_TREE_3 }, + { RC_HC_NEAR_GUARDS_TREE_4, RAND_INF_HC_NEAR_GUARDS_TREE_4 }, + { RC_HC_NEAR_GUARDS_TREE_5, RAND_INF_HC_NEAR_GUARDS_TREE_5 }, + { RC_HC_NEAR_GUARDS_TREE_6, RAND_INF_HC_NEAR_GUARDS_TREE_6 }, + { RC_HC_SKULLTULA_TREE, RAND_INF_HC_SKULLTULA_TREE }, + { RC_HC_GROTTO_TREE, RAND_INF_HC_GROTTO_TREE }, + { RC_HC_NL_TREE_1, RAND_INF_HC_NL_TREE_1 }, + { RC_HC_NL_TREE_2, RAND_INF_HC_NL_TREE_2 }, + { RC_HF_NEAR_KAK_TREE, RAND_INF_HF_NEAR_KAK_TREE }, + { RC_HF_NEAR_KAK_SMALL_TREE, RAND_INF_HF_NEAR_KAK_SMALL_TREE }, + { RC_HF_NEAR_MARKET_TREE_1, RAND_INF_HF_NEAR_MARKET_TREE_1 }, + { RC_HF_NEAR_MARKET_TREE_2, RAND_INF_HF_NEAR_MARKET_TREE_2 }, + { RC_HF_NEAR_MARKET_TREE_3, RAND_INF_HF_NEAR_MARKET_TREE_3 }, + { RC_HF_NEAR_LLR_TREE, RAND_INF_HF_NEAR_LLR_TREE }, + { RC_HF_NEAR_LH_TREE, RAND_INF_HF_NEAR_LH_TREE }, + { RC_HF_CHILD_NEAR_GV_TREE, RAND_INF_HF_CHILD_NEAR_GV_TREE }, + { RC_HF_ADULT_NEAR_GV_TREE, RAND_INF_HF_ADULT_NEAR_GV_TREE }, + { RC_HF_NEAR_ZR_TREE, RAND_INF_HF_NEAR_ZR_TREE }, + { RC_HF_NORTHWEST_TREE_1, RAND_INF_HF_NORTHWEST_TREE_1 }, + { RC_HF_NORTHWEST_TREE_2, RAND_INF_HF_NORTHWEST_TREE_2 }, + { RC_HF_NORTHWEST_TREE_3, RAND_INF_HF_NORTHWEST_TREE_3 }, + { RC_HF_NORTHWEST_TREE_4, RAND_INF_HF_NORTHWEST_TREE_4 }, + { RC_HF_NORTHWEST_TREE_5, RAND_INF_HF_NORTHWEST_TREE_5 }, + { RC_HF_NORTHWEST_TREE_6, RAND_INF_HF_NORTHWEST_TREE_6 }, + { RC_HF_EAST_TREE_1, RAND_INF_HF_EAST_TREE_1 }, + { RC_HF_EAST_TREE_2, RAND_INF_HF_EAST_TREE_2 }, + { RC_HF_EAST_TREE_3, RAND_INF_HF_EAST_TREE_3 }, + { RC_HF_EAST_TREE_4, RAND_INF_HF_EAST_TREE_4 }, + { RC_HF_EAST_TREE_5, RAND_INF_HF_EAST_TREE_5 }, + { RC_HF_EAST_TREE_6, RAND_INF_HF_EAST_TREE_6 }, + { RC_HF_SOUTHEAST_TREE_1, RAND_INF_HF_SOUTHEAST_TREE_1 }, + { RC_HF_SOUTHEAST_TREE_2, RAND_INF_HF_SOUTHEAST_TREE_2 }, + { RC_HF_SOUTHEAST_TREE_3, RAND_INF_HF_SOUTHEAST_TREE_3 }, + { RC_HF_SOUTHEAST_TREE_4, RAND_INF_HF_SOUTHEAST_TREE_4 }, + { RC_HF_SOUTHEAST_TREE_5, RAND_INF_HF_SOUTHEAST_TREE_5 }, + { RC_HF_SOUTHEAST_TREE_6, RAND_INF_HF_SOUTHEAST_TREE_6 }, + { RC_HF_SOUTHEAST_TREE_7, RAND_INF_HF_SOUTHEAST_TREE_7 }, + { RC_HF_SOUTHEAST_TREE_8, RAND_INF_HF_SOUTHEAST_TREE_8 }, + { RC_HF_SOUTHEAST_TREE_9, RAND_INF_HF_SOUTHEAST_TREE_9 }, + { RC_HF_SOUTHEAST_TREE_10, RAND_INF_HF_SOUTHEAST_TREE_10 }, + { RC_HF_SOUTHEAST_TREE_11, RAND_INF_HF_SOUTHEAST_TREE_11 }, + { RC_HF_SOUTHEAST_TREE_12, RAND_INF_HF_SOUTHEAST_TREE_12 }, + { RC_HF_SOUTHEAST_TREE_13, RAND_INF_HF_SOUTHEAST_TREE_13 }, + { RC_HF_SOUTHEAST_TREE_14, RAND_INF_HF_SOUTHEAST_TREE_14 }, + { RC_HF_SOUTHEAST_TREE_15, RAND_INF_HF_SOUTHEAST_TREE_15 }, + { RC_HF_SOUTHEAST_TREE_16, RAND_INF_HF_SOUTHEAST_TREE_16 }, + { RC_HF_SOUTHEAST_TREE_17, RAND_INF_HF_SOUTHEAST_TREE_17 }, + { RC_HF_SOUTHEAST_TREE_18, RAND_INF_HF_SOUTHEAST_TREE_18 }, + { RC_HF_SOUTHEAST_TREE_19, RAND_INF_HF_SOUTHEAST_TREE_19 }, + { RC_HF_CHILD_SOUTHEAST_TREE_1, RAND_INF_HF_CHILD_SOUTHEAST_TREE_1 }, + { RC_HF_CHILD_SOUTHEAST_TREE_2, RAND_INF_HF_CHILD_SOUTHEAST_TREE_2 }, + { RC_HF_CHILD_SOUTHEAST_TREE_3, RAND_INF_HF_CHILD_SOUTHEAST_TREE_3 }, + { RC_HF_CHILD_SOUTHEAST_TREE_4, RAND_INF_HF_CHILD_SOUTHEAST_TREE_4 }, + { RC_HF_CHILD_SOUTHEAST_TREE_5, RAND_INF_HF_CHILD_SOUTHEAST_TREE_5 }, + { RC_HF_CHILD_SOUTHEAST_TREE_6, RAND_INF_HF_CHILD_SOUTHEAST_TREE_6 }, + { RC_HF_TEKTITE_GROTTO_TREE, RAND_INF_HF_TEKTITE_GROTTO_TREE }, + { RC_ZF_TREE, RAND_INF_ZF_TREE }, + { RC_ZR_TREE, RAND_INF_ZR_TREE }, + { RC_KAK_TREE, RAND_INF_KAK_TREE }, + { RC_LLR_TREE, RAND_INF_LLR_TREE }, }; BeehiveIdentity Randomizer::IdentifyBeehive(s32 sceneNum, s16 xPosition, s32 respawnData) { @@ -3734,6 +3823,27 @@ SmallCrateIdentity Randomizer::IdentifySmallCrate(s32 sceneNum, s32 posX, s32 po return smallCrateIdentity; } +TreeIdentity Randomizer::IdentifyTree(s32 sceneNum, s32 posX, s32 posZ) { + struct TreeIdentity treeIdentity; + + if (sceneNum == SCENE_MARKET_NIGHT) { + sceneNum = SCENE_MARKET_DAY; + } + + s32 actorParams = TWO_ACTOR_PARAMS(posX, posZ); + Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_WOOD02, sceneNum, actorParams); + if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK && + (location->GetRCType() != RCTYPE_NLTREE || GetRandoSettingValue(RSK_LOGIC_RULES) == RO_LOGIC_NO_LOGIC)) { + treeIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()]; + treeIdentity.randomizerCheck = location->GetRandomizerCheck(); + return treeIdentity; + } + + treeIdentity.randomizerInf = RAND_INF_MAX; + treeIdentity.randomizerCheck = RC_UNKNOWN_CHECK; + return treeIdentity; +} + u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { return Rando::Context::GetInstance()->GetOption(randoSettingKey).Get(); } @@ -3807,6 +3917,8 @@ void GenerateRandomizerImgui(std::string seed = "") { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); generated = 1; + + GameInteractor::Instance->ExecuteHooks(); } bool GenerateRandomizer(std::string seed /*= ""*/) { @@ -3816,6 +3928,7 @@ bool GenerateRandomizer(std::string seed /*= ""*/) { } if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) == 0) { randoThread = std::thread(&GenerateRandomizerImgui, seed); + return true; } return false; @@ -3903,32 +4016,24 @@ void RandomizerSettingsWindow::DrawElement() { if (ImGui::BeginTabItem("Items")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); - ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == - RO_LOGIC_VANILLA); if (mSettings->GetOptionGroup(RSG_ITEMS_IMGUI_TABLE).RenderImGui()) { mNeedsUpdate = true; } - ImGui::EndDisabled(); ImGui::PopStyleVar(1); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Gameplay")) { - ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == - RO_LOGIC_VANILLA); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (mSettings->GetOptionGroup(RSG_GAMEPLAY_IMGUI_TABLE).RenderImGui()) { mNeedsUpdate = true; } - ImGui::EndDisabled(); ImGui::PopStyleVar(1); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Locations")) { - ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) || disableEditingRandoSettings || - CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == - RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) || disableEditingRandoSettings); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (!locationsTabOpen) { locationsTabOpen = true; @@ -4102,19 +4207,11 @@ void RandomizerSettingsWindow::DrawElement() { mNeedsUpdate = true; } } - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { - ImGui::SameLine(); - ImGui::TextColored( - ImVec4(1.0f, 0.0f, 0.0f, 1.0f), - "Heads up! This will disable all rando settings except for entrance shuffle and starter items"); - } ImGui::PopItemWidth(); ImGui::EndTable(); } - ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) || disableEditingRandoSettings || - CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == - RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) || disableEditingRandoSettings); // Tricks static std::unordered_map areaTreeDisabled{ @@ -5126,12 +5223,12 @@ CustomMessage Randomizer::GetIceTrapMessage() { "Das ist kein Item - das ist Karma.", "Und wieder hat Dich 'ne Kiste besiegt.", "Rauru lacht Dich aus.", - "Saria hat sich gerade entfreundet.", + "Salia hat sich gerade entfreundet.", "Prinzessin Ruto hat die Verlobung aufgelöst.", "Kein Seed, kein Ärger!", "Diese Truhe wurde Ihnen präsentiert von: ABSICHT!", "Nicht heute.", - "Nächster halt, #Frosthausen#!", + "Nächster Halt, #Frosthausen#!", "Genau so nützlich wie Navi im Bosskampf.", "Zelda? Die kennt Dich nicht.", "Zufall? Nein. Absicht!", @@ -5174,11 +5271,11 @@ CustomMessage Randomizer::GetIceTrapMessage() { "Der Spind von Davy Jones!", "Herzog Onkled lacht Dich aus.", "GEWINNER!", - "vERLIERER!", + "VERLIERER!", "Drücke B, Unten und Select um zu überleben.", "#Chill# mal jetzt.", "Hier halt mal eben.", - "Sony lacht Dich aus", + "Sony lacht Dich aus!", "Dieses Item ist nicht in deinem Land verfügbar.", "Es ist wichtig, die #Kühltruhe# mal für einen Tag auszuschalten.", "#Kacknoob#!", @@ -5823,6 +5920,53 @@ void RandomizerSettingsWindow::InitElement() { mSettings->UpdateOptionProperties(); } +static std::unordered_map randomizerGetToStatsTimeStamp = { + { RG_GOHMA_SOUL, TIMESTAMP_FOUND_GOHMA_SOUL }, + { RG_KING_DODONGO_SOUL, TIMESTAMP_FOUND_KING_DODONGO_SOUL }, + { RG_BARINADE_SOUL, TIMESTAMP_FOUND_BARINADE_SOUL }, + { RG_PHANTOM_GANON_SOUL, TIMESTAMP_FOUND_PHANTOM_GANON_SOUL }, + { RG_VOLVAGIA_SOUL, TIMESTAMP_FOUND_VOLVAGIA_SOUL }, + { RG_MORPHA_SOUL, TIMESTAMP_FOUND_MORPHA_SOUL }, + { RG_BONGO_BONGO_SOUL, TIMESTAMP_FOUND_BONGO_BONGO_SOUL }, + { RG_TWINROVA_SOUL, TIMESTAMP_FOUND_TWINROVA_SOUL }, + { RG_GANON_SOUL, TIMESTAMP_FOUND_GANON_SOUL }, + + { RG_BRONZE_SCALE, TIMESTAMP_FOUND_BRONZE_SCALE }, + + { RG_OCARINA_A_BUTTON, TIMESTAMP_FOUND_OCARINA_A_BUTTON }, + { RG_OCARINA_C_UP_BUTTON, TIMESTAMP_FOUND_OCARINA_C_UP_BUTTON }, + { RG_OCARINA_C_DOWN_BUTTON, TIMESTAMP_FOUND_OCARINA_C_DOWN_BUTTON }, + { RG_OCARINA_C_LEFT_BUTTON, TIMESTAMP_FOUND_OCARINA_C_LEFT_BUTTON }, + { RG_OCARINA_C_RIGHT_BUTTON, TIMESTAMP_FOUND_OCARINA_C_RIGHT_BUTTON }, + + { RG_FISHING_POLE, TIMESTAMP_FOUND_FISHING_POLE }, + + { RG_GUARD_HOUSE_KEY, TIMESTAMP_FOUND_GUARD_HOUSE_KEY }, + { RG_MARKET_BAZAAR_KEY, TIMESTAMP_FOUND_MARKET_BAZAAR_KEY }, + { RG_MARKET_POTION_SHOP_KEY, TIMESTAMP_FOUND_MARKET_POTION_SHOP_KEY }, + { RG_MASK_SHOP_KEY, TIMESTAMP_FOUND_MASK_SHOP_KEY }, + { RG_MARKET_SHOOTING_GALLERY_KEY, TIMESTAMP_FOUND_MARKET_SHOOTING_GALLERY_KEY }, + { RG_BOMBCHU_BOWLING_KEY, TIMESTAMP_FOUND_BOMBCHU_BOWLING_KEY }, + { RG_TREASURE_CHEST_GAME_BUILDING_KEY, TIMESTAMP_FOUND_TREASURE_CHEST_GAME_BUILDING_KEY }, + { RG_BOMBCHU_SHOP_KEY, TIMESTAMP_FOUND_BOMBCHU_SHOP_KEY }, + { RG_RICHARDS_HOUSE_KEY, TIMESTAMP_FOUND_RICHARDS_HOUSE_KEY }, + { RG_ALLEY_HOUSE_KEY, TIMESTAMP_FOUND_ALLEY_HOUSE_KEY }, + { RG_KAK_BAZAAR_KEY, TIMESTAMP_FOUND_KAK_BAZAAR_KEY }, + { RG_KAK_POTION_SHOP_KEY, TIMESTAMP_FOUND_KAK_POTION_SHOP_KEY }, + { RG_BOSS_HOUSE_KEY, TIMESTAMP_FOUND_BOSS_HOUSE_KEY }, + { RG_GRANNYS_POTION_SHOP_KEY, TIMESTAMP_FOUND_GRANNYS_POTION_SHOP_KEY }, + { RG_SKULLTULA_HOUSE_KEY, TIMESTAMP_FOUND_SKULLTULA_HOUSE_KEY }, + { RG_IMPAS_HOUSE_KEY, TIMESTAMP_FOUND_IMPAS_HOUSE_KEY }, + { RG_WINDMILL_KEY, TIMESTAMP_FOUND_WINDMILL_KEY }, + { RG_KAK_SHOOTING_GALLERY_KEY, TIMESTAMP_FOUND_KAK_SHOOTING_GALLERY_KEY }, + { RG_DAMPES_HUT_KEY, TIMESTAMP_FOUND_DAMPES_HUT_KEY }, + { RG_TALONS_HOUSE_KEY, TIMESTAMP_FOUND_TALONS_HOUSE_KEY }, + { RG_STABLES_KEY, TIMESTAMP_FOUND_STABLES_KEY }, + { RG_BACK_TOWER_KEY, TIMESTAMP_FOUND_BACK_TOWER_KEY }, + { RG_HYLIA_LAB_KEY, TIMESTAMP_FOUND_HYLIA_LAB_KEY }, + { RG_FISHING_HOLE_KEY, TIMESTAMP_FOUND_FISHING_HOLE_KEY }, +}; + // Gameplay stat tracking: Update time the item was acquired // (special cases for rando items) void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { @@ -5837,6 +5981,12 @@ void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { // Use ITEM_KEY_BOSS to timestamp Ganon's boss key if (item == RG_GANONS_CASTLE_BOSS_KEY) { gSaveContext.ship.stats.itemTimestamp[ITEM_KEY_BOSS] = time; + return; + } + + if (randomizerGetToStatsTimeStamp.contains((RandomizerGet)item)) { + gSaveContext.ship.stats.itemTimestamp[randomizerGetToStatsTimeStamp[(RandomizerGet)item]] = time; + return; } // Count any bottled item as a bottle @@ -5846,6 +5996,7 @@ void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { } return; } + // Count any bombchu pack as bombchus if ((item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_20) || item == RG_PROGRESSIVE_BOMBCHUS) { if (gSaveContext.ship.stats.itemTimestamp[ITEM_BOMBCHU] = 0) { @@ -5853,11 +6004,15 @@ void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { } return; } + if (item == RG_MAGIC_SINGLE) { gSaveContext.ship.stats.itemTimestamp[ITEM_SINGLE_MAGIC] = time; + return; } + if (item == RG_DOUBLE_DEFENSE) { gSaveContext.ship.stats.itemTimestamp[ITEM_DOUBLE_DEFENSE] = time; + return; } } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 56911ee7c..30cf85c66 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -58,6 +58,7 @@ class Randomizer { GrassIdentity IdentifyGrass(s32 sceneNum, s32 posX, s32 posZ, s32 respawnData, s32 linkAge); CrateIdentity IdentifyCrate(s32 sceneNum, s32 posX, s32 posZ); SmallCrateIdentity IdentifySmallCrate(s32 sceneNum, s32 posX, s32 posZ); + TreeIdentity IdentifyTree(s32 sceneNum, s32 posX, s32 posZ); GetItemEntry GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability = true); GetItemEntry GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index cc6cec294..53e6b5a6c 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -210,6 +210,123 @@ typedef enum { LOGIC_OCARINA_C_LEFT_BUTTON, LOGIC_OCARINA_C_RIGHT_BUTTON, LOGIC_TRIFORCE_PIECES, + LOGIC_CAN_BORROW_MASKS, + LOGIC_BORROW_SKULL_MASK, + LOGIC_BORROW_SPOOKY_MASK, + LOGIC_BORROW_BUNNY_HOOD, + LOGIC_BORROW_RIGHT_MASKS, + LOGIC_FREED_EPONA, + LOGIC_DEKU_TREE_CLEAR, + LOGIC_DODONGOS_CAVERN_CLEAR, + LOGIC_JABU_JABUS_BELLY_CLEAR, + LOGIC_FOREST_TEMPLE_CLEAR, + LOGIC_FIRE_TEMPLE_CLEAR, + LOGIC_WATER_TEMPLE_CLEAR, + LOGIC_SPIRIT_TEMPLE_CLEAR, + LOGIC_SHADOW_TEMPLE_CLEAR, + LOGIC_FOREST_TRIAL_CLEAR, + LOGIC_FIRE_TRIAL_CLEAR, + LOGIC_WATER_TRIAL_CLEAR, + LOGIC_SPIRIT_TRIAL_CLEAR, + LOGIC_SHADOW_TRIAL_CLEAR, + LOGIC_LIGHT_TRIAL_CLEAR, + LOGIC_CAN_EMPTY_BIG_POES, + LOGIC_NUT_POT, + LOGIC_NUT_CRATE, + LOGIC_DEKU_BABA_NUTS, + LOGIC_STICK_POT, + LOGIC_DEKU_BABA_STICKS, + LOGIC_BUG_SHRUB, + LOGIC_WANDERING_BUGS, + LOGIC_BUG_ROCK, + LOGIC_FISH_GROUP, + LOGIC_LONE_FISH, + LOGIC_GOSSIP_STONE_FAIRY, + LOGIC_BEAN_PLANT_FAIRY, + LOGIC_BUTTERFLY_FAIRY, + LOGIC_FAIRY_POT, + LOGIC_FREE_FAIRIES, + LOGIC_FAIRY_POND, + LOGIC_CHILD_SCARECROW, + LOGIC_ADULT_SCARECROW, + LOGIC_CARPET_MERCHANT, + LOGIC_COULD_PLAY_BOWLING, + LOGIC_BIG_POE_KILL, + LOGIC_BUILD_RAINBOW_BRIDGE, + LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, + LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER, + LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER, + LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER, + LOGIC_TH_COULD_FREE_SLOPE_CARPENTER, + LOGIC_TH_RESCUED_ALL_CARPENTERS, + LOGIC_GF_GATE_OPEN, + LOGIC_GTG_GATE_OPEN, + LOGIC_DAMPES_WINDMILL_ACCESS, + LOGIC_DRAIN_WELL, + LOGIC_GORON_CITY_CHILD_FIRE, + LOGIC_GORON_CITY_WOODS_WARP_OPEN, + LOGIC_GORON_CITY_DARUNIAS_DOOR_OPEN_CHILD, + LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT, + LOGIC_DEKU_TREE_1F_BROKE_WEB, + LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK, + LOGIC_DEKU_TREE_MQ_CLEARED_SE_ROOM, + LOGIC_DEKU_TREE_MQ_WATER_ROOM_TORCHES, + LOGIC_DC_EYES_LIT, + LOGIC_DC_STAIRS_ROOM_DOOR, + LOGIC_DC_LIFT_PLATFORM, + LOGIC_DC_KILLED_LOWER_LIZALFOS, + LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, + LOGIC_DC_MQ_BEHIND_FIRE_SWITCH, + LOGIC_JABU_RUTO_IN_1F, + LOGIC_JABU_WEST_TENTACLE, + LOGIC_JABU_EAST_TENTACLE, + LOGIC_JABU_NORTH_TENTACLE, + LOGIC_JABU_LOWERED_PATH, + LOGIC_JABU_MQ_HOLES_ROOM_DOOR, + LOGIC_JABU_MQ_LIFT_ROOM_COW, + LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, + LOGIC_FOREST_CAN_TWIST_HALLWAY, + LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, + LOGIC_FOREST_OPEN_BOSS_CORRIDOR, + LOGIC_FOREST_JOELLE, + LOGIC_FOREST_BETH, + LOGIC_FOREST_AMY, + LOGIC_FOREST_MEG, + LOGIC_FIRE_LOOP_SWITCH, + LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE, + LOGIC_FIRE_OPENED_UPPER_SHORTCUT, + LOGIC_FIRE_HIT_PLATFORM, + LOGIC_FIRE_MQ_OPENED_FIRE_MAZE_DOOR, + LOGIC_WATER_LOW_FROM_HIGH, + LOGIC_WATER_LOW_FROM_MID, + LOGIC_WATER_MIDDLE, + LOGIC_WATER_HIGH, + LOGIC_WATER_COULD_LOW, + LOGIC_WATER_COULD_MIDDLE, + LOGIC_WATER_REACHED_HIGH_EMBLEM, + LOGIC_WATER_MQ_STALFOS_PIT, + LOGIC_WATER_MQ_DRAGON_TORCHES, + LOGIC_WATER_MQ_B1_SWITCH, + LOGIC_WATER_MQ_B1_OPENED_PILLAR, + LOGIC_SPIRIT_1F_SILVER_RUPEES, + LOGIC_SPIRIT_MQ_CRAWL_BOULDER, + LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, + LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, + LOGIC_SPIRIT_MQ_3SUNS_ENEMIES, + LOGIC_SHADOW_SHORTCUT_BLOCK, + LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES, + LOGIC_WAKE_UP_ADULT_TALON, + LOGIC_KAKARIKO_GATE_OPEN, + LOGIC_DELIVER_RUTOS_LETTER, + LOGIC_KING_ZORA_THAWED, + LOGIC_LINKS_COW, + LOGIC_BOTW_LOWERED_WATER, + LOGIC_BOTW_MQ_OPENED_WEST_ROOM, + LOGIC_BOTW_MQ_OPENED_MIDDLE_HOLE, + LOGIC_GTG_MQ_MAZE_SWITCH, + LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH, + LOGIC_GTG_PLATFORM_SILVER_RUPEES, + LOGIC_SHADOW_TRIAL_FIRST_CHEST, LOGIC_MAX } LogicVal; @@ -299,12 +416,17 @@ typedef enum { RCTYPE_CRATE, // Crates RCTYPE_NLCRATE, // NL Crates RCTYPE_SMALL_CRATE, // Small crates + RCTYPE_TREE, // Trees + RCTYPE_NLTREE, // NL Trees RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps) RCTYPE_OCARINA, // Ocarina locations RCTYPE_BEEHIVE, // Beehives RCTYPE_FISH, // Fishes RCTYPE_FREESTANDING, // Freestanding rupees and hearts - RCTYPE_FAIRY, // Fairies + RCTYPE_FOUNTAIN_FAIRY, // Fairies in Fountains + RCTYPE_STONE_FAIRY, // Fairies from Gossip Stones + RCTYPE_BEAN_FAIRY, // Fairies from Beans + RCTYPE_SONG_FAIRY, // Fairies from Songs RCTYPE_GRASS, // Grass } RandomizerCheckType; @@ -697,6 +819,7 @@ typedef enum { RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, RR_FOREST_TEMPLE_MAP_ROOM, RR_FOREST_TEMPLE_SEWER, + RR_FOREST_TEMPLE_DRAINED_SEWER, RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, RR_FOREST_TEMPLE_FLOORMASTER_ROOM, RR_FOREST_TEMPLE_WEST_CORRIDOR, @@ -1077,21 +1200,6 @@ typedef enum { RR_GANONS_CASTLE_ESCAPE, RR_GANONS_CASTLE_GANON_ARENA, - RR_MARKER_AREAS_END, // Used for area key count - - // DUNGEONS - RR_DEKU_TREE, - RR_DODONGOS_CAVERN, - RR_JABU_JABUS_BELLY, - RR_FOREST_TEMPLE, - RR_FIRE_TEMPLE, - RR_WATER_TEMPLE, - RR_SPIRIT_TEMPLE, - RR_SHADOW_TEMPLE, - RR_BOTTOM_OF_THE_WELL, - RR_ICE_CAVERN, - RR_GERUDO_TRAINING_GROUND, - RR_GANONS_CASTLE, RR_MAX, } RandomizerRegion; @@ -2396,7 +2504,7 @@ typedef enum { RC_GF_SOUTHMOST_CENTER_CRATE, RC_GF_MID_SOUTH_CENTER_CRATE, RC_GF_MID_NORTH_CENTER_CRATE, - RR_GF_NORTHMOST_CENTER_CRATE, + RC_GF_NORTHMOST_CENTER_CRATE, RC_GF_OUTSKIRTS_NE_CRATE, RC_GF_OUTSKIRTS_NW_CRATE, RC_GF_HBA_RANGE_CRATE_1, @@ -2647,9 +2755,74 @@ typedef enum { RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, // End Crates + // Start Trees + RC_MARKET_TREE, + RC_HC_NEAR_GUARDS_TREE_1, + RC_HC_NEAR_GUARDS_TREE_2, + RC_HC_NEAR_GUARDS_TREE_3, + RC_HC_NEAR_GUARDS_TREE_4, + RC_HC_NEAR_GUARDS_TREE_5, + RC_HC_NEAR_GUARDS_TREE_6, + RC_HC_SKULLTULA_TREE, + RC_HC_GROTTO_TREE, + RC_HC_NL_TREE_1, + RC_HC_NL_TREE_2, + RC_HF_NEAR_LLR_TREE, + RC_HF_NEAR_LH_TREE, + RC_HF_CHILD_NEAR_GV_TREE, + RC_HF_ADULT_NEAR_GV_TREE, + RC_HF_NEAR_ZR_TREE, + RC_HF_NEAR_KAK_TREE, + RC_HF_NEAR_KAK_SMALL_TREE, + RC_HF_NEAR_MARKET_TREE_1, + RC_HF_NEAR_MARKET_TREE_2, + RC_HF_NEAR_MARKET_TREE_3, + RC_HF_NORTHWEST_TREE_1, + RC_HF_NORTHWEST_TREE_2, + RC_HF_NORTHWEST_TREE_3, + RC_HF_NORTHWEST_TREE_4, + RC_HF_NORTHWEST_TREE_5, + RC_HF_NORTHWEST_TREE_6, + RC_HF_EAST_TREE_1, + RC_HF_EAST_TREE_2, + RC_HF_EAST_TREE_3, + RC_HF_EAST_TREE_4, + RC_HF_EAST_TREE_5, + RC_HF_EAST_TREE_6, + RC_HF_SOUTHEAST_TREE_1, + RC_HF_SOUTHEAST_TREE_2, + RC_HF_SOUTHEAST_TREE_3, + RC_HF_SOUTHEAST_TREE_4, + RC_HF_SOUTHEAST_TREE_5, + RC_HF_SOUTHEAST_TREE_6, + RC_HF_SOUTHEAST_TREE_7, + RC_HF_SOUTHEAST_TREE_8, + RC_HF_SOUTHEAST_TREE_9, + RC_HF_SOUTHEAST_TREE_10, + RC_HF_SOUTHEAST_TREE_11, + RC_HF_SOUTHEAST_TREE_12, + RC_HF_SOUTHEAST_TREE_13, + RC_HF_SOUTHEAST_TREE_14, + RC_HF_SOUTHEAST_TREE_15, + RC_HF_SOUTHEAST_TREE_16, + RC_HF_SOUTHEAST_TREE_17, + RC_HF_SOUTHEAST_TREE_18, + RC_HF_SOUTHEAST_TREE_19, + RC_HF_CHILD_SOUTHEAST_TREE_1, + RC_HF_CHILD_SOUTHEAST_TREE_2, + RC_HF_CHILD_SOUTHEAST_TREE_3, + RC_HF_CHILD_SOUTHEAST_TREE_4, + RC_HF_CHILD_SOUTHEAST_TREE_5, + RC_HF_CHILD_SOUTHEAST_TREE_6, + RC_HF_TEKTITE_GROTTO_TREE, + RC_ZF_TREE, + RC_ZR_TREE, + RC_KAK_TREE, + RC_LLR_TREE, + // End Trees + RC_PIERRE, RC_DELIVER_RUTOS_LETTER, - RC_MASTER_SWORD_PEDESTAL, RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RC_KF_GOSSIP_STONE, @@ -3535,6 +3708,7 @@ typedef enum { RT_BOMBCHU_BEEHIVES, RT_BLUE_FIRE_MUD_WALLS, RT_OPEN_UNDERWATER_CHEST, + RT_HOOKSHOT_EXTENSION, RT_KF_ADULT_GS, // -- location tricks RT_LW_BRIDGE, RT_LW_MIDO_BACKFLIP, @@ -3551,7 +3725,6 @@ typedef enum { RT_GY_SHADOW_FIRE_ARROWS, RT_DMT_SOIL_GS, RT_DMT_BOMBABLE, - RT_DMT_HOOKSHOT_LOWER_GS, RT_DMT_HOVERS_LOWER_GS, RT_DMT_BEAN_LOWER_GS, RT_DMT_JS_LOWER_GS, @@ -3665,7 +3838,8 @@ typedef enum { RT_LENS_SHADOW, RT_LENS_SHADOW_PLATFORM, RT_LENS_BONGO, - RT_SHADOW_UMBRELLA, + RT_SHADOW_UMBRELLA_HOVER, + RT_SHADOW_UMBRELLA_CLIP, RT_SHADOW_UMBRELLA_GS, RT_SHADOW_FREESTANDING_KEY, RT_SHADOW_STATUE, @@ -3726,6 +3900,7 @@ typedef enum { RT_FW_VOID_WARP, RT_GROUND_CLIP, RT_GROUND_JUMP, + RT_GROUND_JUMP_HARD, RT_HESS, RT_HOOKSHOT_CLIP, RT_HOOKSHOT_JUMP, @@ -4131,6 +4306,7 @@ typedef enum { RH_ALTAR_CHILD, RH_ALTAR_ADULT, RH_SARIA_HINT, + RH_MIDO_HINT, RH_LOACH_HINT, RH_FISHING_POLE, RH_MINUET_WARP_LOC, @@ -4954,7 +5130,6 @@ typedef enum { RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RHT_GANONS_TOWER_BOSS_KEY_CHEST, RHT_DELIVER_RUTOS_LETTER, - RHT_MASTER_SWORD_PEDESTAL, // Beehives RHT_BEEHIVE_CHEST_GROTTO, RHT_BEEHIVE_COW_GROTTO, @@ -5399,6 +5574,7 @@ typedef enum { RHT_GREG_HINT, RHT_SARIA_TALK_HINT, RHT_SARIA_SONG_HINT, + RHT_MIDO_HINT, RHT_LOACH_HINT, RHT_FISHING_POLE_HINT, // Static Entrance Hints @@ -5489,6 +5665,14 @@ typedef enum { RHT_CRATE_SPIRIT_TEMPLE, RHT_CRATE_SHADOW_TEMPLE, RHT_CRATE_GERUDO_TRAINING_GROUND, + // Shuffle Trees + RHT_TREE_HYRULE_FIELD, + RHT_TREE_MARKET, + RHT_TREE_HYRULE_CASTLE, + RHT_TREE_ZORAS_FOUNTAIN, + RHT_TREE_ZORAS_RIVER, + RHT_TREE_LON_LON_RANCH, + RHT_TREE_KAKARIKO, // Ganon Line RHT_GANON_JOKE01, RHT_GANON_JOKE02, @@ -5828,6 +6012,7 @@ typedef enum { RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, RSK_SHUFFLE_POTS, RSK_SHUFFLE_CRATES, + RSK_SHUFFLE_TREES, RSK_SHUFFLE_FROG_SONG_RUPEES, RSK_ITEM_POOL, RSK_ICE_TRAPS, @@ -5839,6 +6024,7 @@ typedef enum { RSK_GREG_HINT, RSK_LOACH_HINT, RSK_SARIA_HINT, + RSK_MIDO_HINT, RSK_FROGS_HINT, RSK_OOT_HINT, RSK_KAK_10_SKULLS_HINT, @@ -5889,6 +6075,7 @@ typedef enum { RSK_MERCHANT_PRICES_AFFORDABLE, RSK_BLUE_FIRE_ARROWS, RSK_SUNLIGHT_ARROWS, + RSK_SLINGBOW_BREAK_BEEHIVES, RSK_ENABLE_BOMBCHU_DROPS, RSK_BOMBCHU_BAG, RSK_LINKS_POCKET, @@ -5958,7 +6145,10 @@ typedef enum { RSK_SHUFFLE_DEKU_STICK_BAG, RSK_SHUFFLE_DEKU_NUT_BAG, RSK_SHUFFLE_FREESTANDING, - RSK_SHUFFLE_FAIRIES, + RSK_SHUFFLE_FOUNTAIN_FAIRIES, + RSK_SHUFFLE_STONE_FAIRIES, + RSK_SHUFFLE_BEAN_FAIRIES, + RSK_SHUFFLE_SONG_FAIRIES, RSK_LOCK_OVERWORLD_DOORS, RSK_SHUFFLE_GRASS, RSK_MAX @@ -6342,7 +6532,6 @@ typedef enum { typedef enum { RO_LOGIC_GLITCHLESS, RO_LOGIC_NO_LOGIC, - RO_LOGIC_VANILLA, } RandoOptionLogic; // Damage Multiplier @@ -6445,6 +6634,11 @@ typedef struct SmallCrateIdentity { RandomizerCheck randomizerCheck; } SmallCrateIdentity; +typedef struct TreeIdentity { + RandomizerInf randomizerInf; + RandomizerCheck randomizerCheck; +} TreeIdentity; + typedef enum { TRACKER_WINDOW_FLOATING, TRACKER_WINDOW_WINDOW, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index da05ee508..fa1e7158b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -189,6 +189,10 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCrates"), RO_GENERIC_NO)) && (location.GetRCType() != RCTYPE_SMALL_CRATE || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCrates"), RO_GENERIC_NO)) && + (location.GetRCType() != RCTYPE_TREE || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleTrees"), RO_GENERIC_NO)) && + (location.GetRCType() != RCTYPE_NLTREE || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleTrees"), RO_GENERIC_NO)) && (location.GetRCType() != RCTYPE_FISH || ctx->GetFishsanity()->GetFishLocationIncluded(&location, FSO_SOURCE_CVARS)) && (location.GetRCType() != RCTYPE_ADULT_TRADE || @@ -203,8 +207,14 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), RO_GENERIC_NO)) && (location.GetRCType() != RCTYPE_FROG_SONG || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), RO_GENERIC_NO)) && - (location.GetRCType() != RCTYPE_FAIRY || - CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFairies"), RO_GENERIC_NO)) && + (location.GetRCType() != RCTYPE_FOUNTAIN_FAIRY || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFountainFairies"), RO_GENERIC_NO)) && + (location.GetRCType() != RCTYPE_STONE_FAIRY || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleStoneFairies"), RO_GENERIC_NO)) && + (location.GetRCType() != RCTYPE_BEAN_FAIRY || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeanFairies"), RO_GENERIC_NO)) && + (location.GetRCType() != RCTYPE_SONG_FAIRY || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFairySpots"), RO_GENERIC_NO)) && ((location.GetRCType() != RCTYPE_MAP && location.GetRCType() != RCTYPE_COMPASS) || CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index d6334b6a0..022303aa3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -8,6 +8,7 @@ #include "soh/ResourceManagerHelpers.h" #include "soh/SohGui/UIWidgets.hpp" #include "soh/SohGui/SohGui.hpp" +#include "soh/SohGui/SohMenu.h" #include "dungeon.h" #include "entrance.h" #include "location_access.h" @@ -19,6 +20,7 @@ #include #include #include +#include #include "location.h" #include "item_location.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" @@ -39,9 +41,21 @@ extern std::vector dungeonRewardMedallions; extern std::vector songItems; extern std::vector equipmentItems; +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + using json = nlohmann::json; +using namespace UIWidgets; namespace CheckTracker { +static WidgetInfo backgroundColorWidget; +static WidgetInfo windowTypeWidget; +static WidgetInfo dungeonSpoilerWidget; +static WidgetInfo hideUnshuffledShopWidget; +static WidgetInfo showGSWidget; +static WidgetInfo showLogicWidget; +static WidgetInfo checkAvailabilityWidget; // settings bool showShops; @@ -68,8 +82,12 @@ bool showOverworldGrass; bool showDungeonGrass; bool showOverworldCrates; bool showDungeonCrates; +bool showTrees; bool showFrogSongRupees; -bool showFairies; +bool showFountainFairies; +bool showStoneFairies; +bool showBeanFairies; +bool showSongFairies; bool showStartingMapsCompasses; bool showKeysanity; bool showGerudoFortressKeys; @@ -1085,7 +1103,7 @@ void CheckTrackerWindow::DrawElement() { totalChecksSS << totalChecksAvailable << " Available / "; } totalChecksSS << totalChecksGotten << " Checked / " << totalChecks << " Total"; - ImGui::Text(totalChecksSS.str().c_str()); + ImGui::Text("%s", totalChecksSS.str().c_str()); UIWidgets::PaddedSeparator(); @@ -1194,7 +1212,7 @@ void CheckTrackerWindow::DrawElement() { } } - ImGui::Text(areaTotalsSS.str().c_str()); + ImGui::Text("%s", areaTotalsSS.str().c_str()); UIWidgets::Tooltip(areaTotalsTooltipSS.str().c_str()); } else { ImGui::Text("???"); @@ -1351,9 +1369,19 @@ void LoadSettings() { IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_FROG_SONG_RUPEES) == RO_GENERIC_YES : false; - showFairies = IS_RANDO - ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_FAIRIES) == RO_GENERIC_YES - : false; + showFountainFairies = + IS_RANDO + ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_FOUNTAIN_FAIRIES) == RO_GENERIC_YES + : false; + showStoneFairies = + IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_STONE_FAIRIES) == RO_GENERIC_YES + : false; + showBeanFairies = + IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BEAN_FAIRIES) == RO_GENERIC_YES + : false; + showSongFairies = + IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SONG_FAIRIES) == RO_GENERIC_YES + : false; showStartingMapsCompasses = IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue( RSK_SHUFFLE_MAPANDCOMPASS) != RO_DUNGEON_ITEM_LOC_VANILLA : false; @@ -1456,6 +1484,7 @@ void LoadSettings() { showDungeonCrates = false; break; } + showTrees = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TREES); } else { // Vanilla showOverworldTokens = true; showDungeonTokens = true; @@ -1465,6 +1494,7 @@ void LoadSettings() { showDungeonGrass = false; showOverworldCrates = false; showDungeonCrates = false; + showTrees = false; } fortressFast = false; @@ -1537,13 +1567,13 @@ bool IsCheckShuffled(RandomizerCheck rc) { if (loc->GetRCType() == RCTYPE_SHOP) { auto identity = OTRGlobals::Instance->gRandomizer->IdentifyShopItem(loc->GetScene(), loc->GetActorParams() + 1); } - if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) != RO_LOGIC_VANILLA) { + if (IS_RANDO) { return (loc->GetArea() != RCAREA_INVALID) && // don't show Invalid locations (loc->GetRCType() != RCTYPE_GOSSIP_STONE) && // TODO: Don't show hints until tracker supports them (loc->GetRCType() != RCTYPE_STATIC_HINT) && // TODO: Don't show hints until tracker supports them - (loc->GetRCType() != - RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we support shuffling them - (rc != RC_HC_ZELDAS_LETTER) && // don't show zeldas letter until we support shuffling it + (loc->GetRCType() != RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we + // support shuffling them + (rc != RC_HC_ZELDAS_LETTER) && // don't show zeldas letter until we support shuffling it (rc != RC_LINKS_POCKET || showLinksPocket) && OTRGlobals::Instance->gRandoContext->IsQuestOfLocationActive(rc) && (loc->GetRCType() != RCTYPE_SHOP || @@ -1577,6 +1607,10 @@ bool IsCheckShuffled(RandomizerCheck rc) { (loc->GetRCType() != RCTYPE_SMALL_CRATE || (showOverworldCrates && RandomizerCheckObjects::AreaIsOverworld(loc->GetArea())) || (showDungeonCrates && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))) && + (loc->GetRCType() != RCTYPE_TREE || showTrees) && + (loc->GetRCType() != RCTYPE_NLTREE || + (showTrees && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) == RO_LOGIC_NO_LOGIC)) && (loc->GetRCType() != RCTYPE_COW || showCows) && (loc->GetRCType() != RCTYPE_FISH || OTRGlobals::Instance->gRandoContext->GetFishsanity()->GetFishLocationIncluded(loc)) && @@ -1592,7 +1626,10 @@ bool IsCheckShuffled(RandomizerCheck rc) { (rc != RC_HC_MALON_EGG || showWeirdEgg) && (loc->GetRCType() != RCTYPE_FROG_SONG || showFrogSongRupees) && ((loc->GetRCType() != RCTYPE_MAP && loc->GetRCType() != RCTYPE_COMPASS) || showStartingMapsCompasses) && - (loc->GetRCType() != RCTYPE_FAIRY || showFairies) && + (loc->GetRCType() != RCTYPE_FOUNTAIN_FAIRY || showFountainFairies) && + (loc->GetRCType() != RCTYPE_STONE_FAIRY || showStoneFairies) && + (loc->GetRCType() != RCTYPE_BEAN_FAIRY || showBeanFairies) && + (loc->GetRCType() != RCTYPE_SONG_FAIRY || showSongFairies) && (loc->GetRCType() != RCTYPE_SMALL_KEY || showKeysanity) && (loc->GetRCType() != RCTYPE_BOSS_KEY || showBossKeysanity) && (loc->GetRCType() != RCTYPE_GANON_BOSS_KEY || showGanonBossKey) && @@ -2017,6 +2054,7 @@ void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) StartPerformanceTimer(PT_RECALCULATE_AVAILABLE_CHECKS); const auto& ctx = Rando::Context::GetInstance(); + logic = ctx->GetLogic(); std::vector targetLocations; targetLocations.reserve(RC_MAX); @@ -2088,22 +2126,14 @@ void CheckTrackerSettingsWindow::DrawElement() { ImGui::TableHeadersRow(); ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - UIWidgets::CVarColorPicker("BG Color", CVAR_TRACKER_CHECK("BgColor"), Color_Bg_Default, true, - UIWidgets::ColorPickerResetButton | UIWidgets::ColorPickerRandomButton, THEME_COLOR); - ImGui::PopItemWidth(); + SohGui::mSohMenu->MenuDrawItem(backgroundColorWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); - UIWidgets::CVarCombobox("Window Type", CVAR_TRACKER_CHECK("WindowType"), windowType, - UIWidgets::ComboboxOptions() - .LabelPosition(UIWidgets::LabelPositions::Far) - .ComponentAlignment(UIWidgets::ComponentAlignments::Right) - .Color(THEME_COLOR) - .DefaultIndex(TRACKER_WINDOW_WINDOW)); + SohGui::mSohMenu->MenuDrawItem(windowTypeWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { UIWidgets::CVarCheckbox("Enable Dragging", CVAR_TRACKER_CHECK("Draggable"), UIWidgets::CheckboxOptions().Color(THEME_COLOR)); - UIWidgets::CVarCheckbox("Only enable while paused", CVAR_TRACKER_CHECK("ShowOnlyPaused"), + UIWidgets::CVarCheckbox("Only Enable While Paused", CVAR_TRACKER_CHECK("ShowOnlyPaused"), UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CVarCombobox("Display Mode", CVAR_TRACKER_CHECK("DisplayType"), displayType, UIWidgets::ComboboxOptions() @@ -2128,41 +2158,17 @@ void CheckTrackerSettingsWindow::DrawElement() { } } ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - UIWidgets::CVarCheckbox("Vanilla/MQ Dungeon Spoilers", CVAR_TRACKER_CHECK("MQSpoilers"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. " - "Otherwise, Vanilla/MQ dungeon locations must be unlocked.") - .Color(THEME_COLOR)); + SohGui::mSohMenu->MenuDrawItem(dungeonSpoilerWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); ImGui::EndDisabled(); - if (UIWidgets::CVarCheckbox( - "Hide unshuffled shop item checks", CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will prevent the tracker from displaying slots with non-shop-item shuffles.") - .Color(THEME_COLOR))) { - hideShopUnshuffledChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), 0); - UpdateFilters(); - } - if (UIWidgets::CVarCheckbox( - "Always show gold skulltulas", CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings.") - .Color(THEME_COLOR))) { - alwaysShowGS = !alwaysShowGS; - UpdateFilters(); - } - UIWidgets::CVarCheckbox("Show Logic", CVAR_TRACKER_CHECK("ShowLogic"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will show a check's logic when hovering over it.") - .Color(THEME_COLOR)); + + SohGui::mSohMenu->MenuDrawItem(hideUnshuffledShopWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); + + SohGui::mSohMenu->MenuDrawItem(showGSWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); + + SohGui::mSohMenu->MenuDrawItem(showLogicWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - if (UIWidgets::CVarCheckbox("Enable Available Checks", CVAR_TRACKER_CHECK("EnableAvailableChecks"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will show the checks that are available to be collected " - "with your current progress.") - .Color(THEME_COLOR))) { - enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); - RecalculateAvailableChecks(); - } + SohGui::mSohMenu->MenuDrawItem(checkAvailabilityWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); ImGui::EndDisabled(); // Filtering settings @@ -2220,8 +2226,8 @@ void CheckTrackerSettingsWindow::DrawElement() { "Checks that you saved the game while having collected.", THEME_COLOR); ImGui::PopStyleVar(1); + ImGui::EndTable(); } - ImGui::EndTable(); } void CheckTrackerWindow::InitElement() { @@ -2239,4 +2245,74 @@ void CheckTrackerWindow::InitElement() { void CheckTrackerWindow::UpdateElement() { } + +void RegisterCheckTrackerWidgets() { + backgroundColorWidget = { .name = "Background Color##CheckTrackerBgColor", + .type = WidgetType::WIDGET_CVAR_COLOR_PICKER }; + backgroundColorWidget.CVar(CVAR_TRACKER_CHECK("BgColor")) + .Options( + ColorPickerOptions().Color(THEME_COLOR).DefaultValue(Color_Bg_Default).UseAlpha().ShowReset().ShowRandom()); + SohGui::mSohMenu->AddSearchWidget({ backgroundColorWidget, "Randomizer", "Check Tracker", "General Settings" }); + + windowTypeWidget = { .name = "Window Type", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + windowTypeWidget.CVar(CVAR_TRACKER_CHECK("WindowType")) + .Options(ComboboxOptions() + .DefaultIndex(TRACKER_WINDOW_WINDOW) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(windowType)); + SohGui::mSohMenu->AddSearchWidget({ windowTypeWidget, "Randomizer", "Check Tracker", "General Settings" }); + + dungeonSpoilerWidget = { .name = "Vanilla/MQ Dungeon Spoilers", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dungeonSpoilerWidget.CVar(CVAR_TRACKER_CHECK("MQSpoilers")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. " + "Otherwise, Vanilla/MQ dungeon locations must be unlocked.")); + SohGui::mSohMenu->AddSearchWidget({ dungeonSpoilerWidget, "Randomizer", "Check Tracker", "General Settings" }); + + hideUnshuffledShopWidget = { .name = "Hide Unshuffled Shop Item Checks", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + hideUnshuffledShopWidget.CVar(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks")) + .Options( + CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will prevent the tracker from displaying slots with non-shop-item shuffles.")) + .Callback([&](WidgetInfo& info) { + hideShopUnshuffledChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), 0); + UpdateFilters(); + }); + SohGui::mSohMenu->AddSearchWidget({ hideUnshuffledShopWidget, "Randomizer", "Check Tracker", "General Settings" }); + + showGSWidget = { .name = "Always Show Gold Skulltulas", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + showGSWidget.CVar(CVAR_TRACKER_CHECK("AlwaysShowGSLocs")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings.")) + .Callback([&](WidgetInfo& info) { + alwaysShowGS = !alwaysShowGS; + UpdateFilters(); + }); + SohGui::mSohMenu->AddSearchWidget({ showGSWidget, "Randomizer", "Check Tracker", "General Settings" }); + + showLogicWidget = { .name = "Show Logic", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + showLogicWidget.CVar(CVAR_TRACKER_CHECK("ShowLogic")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will show a check's logic when hovering over it.")); + SohGui::mSohMenu->AddSearchWidget({ showLogicWidget, "Randomizer", "Check Tracker", "General Settings" }); + + checkAvailabilityWidget = { .name = "Enable Available Checks", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + checkAvailabilityWidget.CVar(CVAR_TRACKER_CHECK("EnableAvailableChecks")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will show the checks that are available to be collected " + "with your current progress.")) + .Callback([&](WidgetInfo& info) { + enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); + RecalculateAvailableChecks(); + }); +} + +static RegisterMenuInitFunc menuInitFunc(RegisterCheckTrackerWidgets); } // namespace CheckTracker diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp index 1a635f58e..b5dd3e4fa 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp @@ -120,10 +120,10 @@ const EntranceData entranceData[] = { { ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Underwater Shortcut", "Zora's River Underwater Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "lw"}, { ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, ENTR_LOST_WOODS_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods North Exit", "Sacred Forest Meadow South Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_OVERWORLD, "lw"}, { ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Tunnel Grotto Entry", "LW Tunnel Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest", 1}, - { ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Grotto Entry", "LW Scrubs Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw", 1}, + { ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Grotto Entry", "LW Deku Scrub Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,scrubs", 1}, { ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Meadow Grotto Entry", "Deku Theater", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage", 1}, { ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "LW Tunnel Grotto", "LW Tunnel Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest"}, - { ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), {{ SCENE_GROTTOS, 0x07 }}, "LW Scrubs Grotto", "LW North Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw"}, + { ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), {{ SCENE_GROTTOS, 0x07 }}, "LW Deku Scrub Grotto", "LW North Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,scrubs"}, { ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), {{ SCENE_GROTTOS, 0x0C }}, "Deku Theater", "LW Meadow Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage"}, // Sacred Forest Meadow @@ -210,11 +210,11 @@ const EntranceData entranceData[] = { { ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Upper Exit", "Death Mountain Trail Top Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD}, { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Great Fairy Entry", "DMC Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR, "", 1}, { ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Upper Grotto Entry", "DMC Upper Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest", 1}, - { ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Hammer Grotto Entry", "DMC Scrubs Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs", 1}, + { ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Hammer Grotto Entry", "DMC Deku Scrub Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs", 1}, { ENTR_FIRE_TEMPLE_ENTRANCE, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Outside Temple", "Fire Temple Entrance", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x01 }}, "DMC Great Fairy Fountain", "DMC Great Fairy Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR}, { ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMC Upper Grotto", "DMC Upper Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest"}, - { ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "DMC Scrubs Grotto", "DMC Hammer Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs"}, + { ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "DMC Deku Scrub Grotto", "DMC Hammer Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs"}, { ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, ENTR_FIRE_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Entrance", "Death Mountain Crater Outside Temple", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON}, { ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, ENTR_FIRE_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Boss Door", "Volvagia", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_FIRE_TEMPLE_BOSS_DOOR, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1}, @@ -225,15 +225,15 @@ const EntranceData entranceData[] = { { ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Darunia's Room Backdoor", "Death Mountain Crater Bridge Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD, "gc"}, { ENTR_LOST_WOODS_TUNNEL_SHORTCUT, ENTR_GORON_CITY_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Tunnel Shortcut", "Lost Woods Tunnel Shortcut", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "gc,lw"}, { ENTR_GORON_SHOP_0, ENTR_GORON_CITY_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Shop Entry", "Goron Shop", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc", 1}, - { ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Lava Grotto Entry", "GC Scrubs Grotto", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs", 1}, + { ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Lava Grotto Entry", "GC Deku Scrub Grotto", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs", 1}, { ENTR_GORON_CITY_OUTSIDE_SHOP, ENTR_GORON_SHOP_0, SINGLE_SCENE_INFO(SCENE_GORON_SHOP), "Goron Shop", "GC Shop Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc"}, - { ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "GC Scrubs Grotto", "GC Lava Grotto Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs"}, + { ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "GC Deku Scrub Grotto", "GC Lava Grotto Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs"}, // Zora's River { ENTR_HYRULE_FIELD_RIVER_EXIT, ENTR_ZORAS_RIVER_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Lower Exit", "Hyrule Field River Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"}, { ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Underwater Shortcut", "Lost Woods Underwater Shortcut", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"}, { ENTR_ZORAS_DOMAIN_ENTRANCE, ENTR_ZORAS_RIVER_WATERFALL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Waterfall Exit", "Zora's Domain Entrance", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD}, - { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Rock Circle Grotto Entry", "ZR Deku SCrub Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs", 1}, + { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Rock Circle Grotto Entry", "ZR Deku Scrub Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs", 1}, { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Boulder Grotto Entry", "ZR Fairy Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "", 1}, { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Open Grotto Entry", "ZR Open Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest", 1}, { ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "ZR Deku Scrub Grotto", "ZR Rock Circle Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs"}, @@ -275,7 +275,7 @@ const EntranceData entranceData[] = { { ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Northwest Boulder Grotto Entry", "HF Fairy Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "", 1}, { ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF West Rock Circle Grotto Entry", "HF Cow Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed", 1}, { ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF South Open Grotto Entry", "HF Open Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1}, - { ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Fenced Grotto Entry", "HF Fenced Scrub Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "scrubs", 1}, + { ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Fenced Grotto Entry", "HF Fenced Deku Scrub Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "scrubs", 1}, { ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Southeast Boulder Grotto Entry", "HF Southeast Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1}, { ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Near Market Boulder Grotto", "HF Near Market Boulder Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO}, { ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET), {{ SCENE_GROTTOS, 0x01 }}, "HF Stone Bridge Tree Grotto", "HF Stone Bridge Tree Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "spider"}, @@ -283,7 +283,7 @@ const EntranceData entranceData[] = { { ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "HF Fairy Grotto", "HF Northwest Boulder Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO}, { ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET), {{ SCENE_GROTTOS, 0x05 }}, "HF Cow Grotto", "HF West Rock Circle Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed"}, { ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Open Grotto", "HF South Open Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"}, - { ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), {{ SCENE_GROTTOS, 0x02 }}, "HF Fenced Scrub Grotto", "HF Fenced Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "srubs"}, + { ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), {{ SCENE_GROTTOS, 0x02 }}, "HF Fenced Deku Scrub Grotto", "HF Fenced Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "scrubs"}, { ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Southeast Grotto", "HF Southeast Boulder Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"}, // Lon Lon Ranch @@ -739,7 +739,7 @@ void EntranceTrackerSettingsWindow::DrawElement() { ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); UIWidgets::CVarCheckbox( "Show Source", CVAR_TRACKER_ENTRANCE("ShowFrom"), - UIWidgets::CheckboxOptions().Tooltip("Reveal the sourcefor undiscovered entrances").Color(THEME_COLOR)); + UIWidgets::CheckboxOptions().Tooltip("Reveal the source for undiscovered entrances").Color(THEME_COLOR)); UIWidgets::CVarCheckbox("Show Destination", CVAR_TRACKER_ENTRANCE("ShowTo"), UIWidgets::CheckboxOptions() .Tooltip("Reveal the destination for undiscovered entrances") @@ -836,7 +836,7 @@ void EntranceTrackerWindow::DrawElement() { ImGui::BeginChild("ChildEntranceTrackerLocations", ImVec2(0, -8)); bool showTo = CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowTo"), 0); bool showFrom = CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowFrom"), 0); - bool collapsUndiscovered = CVarGetInteger(CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"), 0); + bool collapseUndiscovered = CVarGetInteger(CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"), 0); bool highlightPrevious = CVarGetInteger(CVAR_TRACKER_ENTRANCE("HighlightPrevious"), 0); bool highlightAvailable = CVarGetInteger(CVAR_TRACKER_ENTRANCE("HighlightAvailable"), 0); bool hideReverse = CVarGetInteger(CVAR_TRACKER_ENTRANCE("HideReverseEntrances"), 1); @@ -892,7 +892,7 @@ void EntranceTrackerWindow::DrawElement() { const char* rplcDstName = showOverride ? override->destination.c_str() : ""; // Filter for entrances by group name, type, source/destination names, and meta tags - if ((!locationSearch.IsActive() && (showOriginal || showOverride || !collapsUndiscovered)) || + if ((!locationSearch.IsActive() && (showOriginal || showOverride || !collapseUndiscovered)) || ((showOriginal && (locationSearch.PassFilter(origSrcName) || locationSearch.PassFilter(origSrcAreaName) || locationSearch.PassFilter(origTypeName) || locationSearch.PassFilter(original->metaTag.c_str()))) || diff --git a/soh/soh/Enhancements/randomizer/randomizer_grotto.c b/soh/soh/Enhancements/randomizer/randomizer_grotto.c index 042efadf4..96105728a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_grotto.c +++ b/soh/soh/Enhancements/randomizer/randomizer_grotto.c @@ -184,7 +184,7 @@ s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex) { } // Translates and overrides the passed in entrance index if it corresponds to a -// special grotto entrance (grotto load or returnpoint) and updates player respawn data correctly. +// special grotto entrance (grotto load or return point) and updates player respawn data correctly. s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) { // Don't change anything unless grotto shuffle has been enabled diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index d42e14cb1..8742805a6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -997,6 +997,69 @@ DEFINE_RAND_INF(RAND_INF_SHADOW_TEMPLE_MQ_TRUTH_SPINNER_SMALL_CRATE_3) DEFINE_RAND_INF(RAND_INF_SHADOW_TEMPLE_MQ_TRUTH_SPINNER_SMALL_CRATE_4) DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_STATUE_SMALL_CRATE) DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE) +DEFINE_RAND_INF(RAND_INF_MARKET_TREE) +DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_1) +DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_2) +DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_3) +DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_4) +DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_5) +DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_6) +DEFINE_RAND_INF(RAND_INF_HC_SKULLTULA_TREE) +DEFINE_RAND_INF(RAND_INF_HC_GROTTO_TREE) +DEFINE_RAND_INF(RAND_INF_HC_NL_TREE_1) +DEFINE_RAND_INF(RAND_INF_HC_NL_TREE_2) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_LLR_TREE) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_LH_TREE) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NEAR_GV_TREE) +DEFINE_RAND_INF(RAND_INF_HF_ADULT_NEAR_GV_TREE) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_ZR_TREE) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_KAK_TREE) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_KAK_SMALL_TREE) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_MARKET_TREE_1) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_MARKET_TREE_2) +DEFINE_RAND_INF(RAND_INF_HF_NEAR_MARKET_TREE_3) +DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_1) +DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_2) +DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_3) +DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_4) +DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_5) +DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_6) +DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_1) +DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_2) +DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_3) +DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_4) +DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_5) +DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_6) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_1) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_2) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_3) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_4) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_5) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_6) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_7) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_8) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_9) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_10) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_11) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_12) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_13) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_14) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_15) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_16) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_17) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_18) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_19) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_1) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_2) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_3) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_4) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_5) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_6) +DEFINE_RAND_INF(RAND_INF_HF_TEKTITE_GROTTO_TREE) +DEFINE_RAND_INF(RAND_INF_ZF_TREE) +DEFINE_RAND_INF(RAND_INF_ZR_TREE) +DEFINE_RAND_INF(RAND_INF_KAK_TREE) +DEFINE_RAND_INF(RAND_INF_LLR_TREE) DEFINE_RAND_INF(RAND_INF_CAUGHT_LOACH) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index fcace1017..0288539d1 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -1,20 +1,23 @@ -#include "randomizer_item_tracker.h" -#include "soh/util.h" -#include "soh/OTRGlobals.h" -#include "soh/cvar_prefixes.h" -#include "soh/SaveManager.h" -#include "soh/ResourceManagerHelpers.h" -#include "soh/SohGui/UIWidgets.hpp" -#include "soh/SohGui/SohGui.hpp" -#include "randomizerTypes.h" - +#include #include #include #include + #include -#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include + #include "randomizer_check_tracker.h" -#include +#include "randomizer_item_tracker.h" +#include "randomizerTypes.h" +#include "soh/cvar_prefixes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" +#include "soh/ResourceManagerHelpers.h" +#include "soh/SaveManager.h" +#include "soh/SohGui/SohGui.hpp" +#include "soh/SohGui/SohMenu.h" +#include "soh/SohGui/UIWidgets.hpp" +#include "soh/util.h" extern "C" { #include @@ -42,6 +45,27 @@ bool shouldUpdateVectors = true; std::vector mainWindowItems = {}; +static WidgetInfo backgroundColor; +static WidgetInfo windowTypeWidget; +static WidgetInfo enableDraggingWidget; +static WidgetInfo onlyPausedWidget; +static WidgetInfo ammoTracking; +static WidgetInfo keyTracking; +static WidgetInfo triforcePieceCount; +static WidgetInfo dungeonItemTracking; +static WidgetInfo gregTracking; +static WidgetInfo triforcePieceTracking; +static WidgetInfo bossSoulsTracking; +static WidgetInfo ocarinaButtonTracking; +static WidgetInfo overworldKeysTracking; +static WidgetInfo fishingPoleTracking; +static WidgetInfo personalNotesWiget; +static WidgetInfo hookshotIdentWidget; + +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + std::vector inventoryItems = { ITEM_TRACKER_ITEM(ITEM_STICK, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_NUT, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_BOMB, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_BOW, 0, DrawItem), @@ -449,7 +473,8 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { result.currentCapacity = IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET) ? 0 : CUR_CAPACITY(UPG_WALLET); result.maxCapacity = - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INCLUDE_TYCOON_WALLET) ? 999 : 500; + IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INCLUDE_TYCOON_WALLET) ? 999 + : 500; result.currentAmmo = gSaveContext.rupees; break; case ITEM_BOMBCHU: @@ -502,7 +527,28 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { result.maxCapacity = GERUDO_TRAINING_GROUND_SMALL_KEY_MAX; break; case SCENE_THIEVES_HIDEOUT: - result.maxCapacity = GERUDO_FORTRESS_SMALL_KEY_MAX; + if (IS_RANDO) { + switch (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GERUDO_FORTRESS)) { + case RO_GF_CARPENTERS_NORMAL: + result.maxCapacity = GERUDO_FORTRESS_SMALL_KEY_MAX; + break; + case RO_GF_CARPENTERS_FAST: + result.maxCapacity = 1; + break; + case RO_GF_CARPENTERS_FREE: + result.maxCapacity = 0; + break; + default: + result.maxCapacity = 0; + SPDLOG_ERROR( + "Invalid value for RSK_GERUDO_FORTRESS: " + + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GERUDO_FORTRESS)); + assert(false); + break; + } + } else { + result.maxCapacity = GERUDO_FORTRESS_SMALL_KEY_MAX; + } break; case SCENE_INSIDE_GANONS_CASTLE: result.maxCapacity = GANONS_CASTLE_SMALL_KEY_MAX; @@ -1735,260 +1781,162 @@ static std::unordered_map minimalDisplayTypes = { void ItemTrackerSettingsWindow::DrawElement() { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f }); - ImGui::BeginTable("itemTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV); - ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Section settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableHeadersRow(); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - CVarColorPicker("Background Color##gItemTrackerBgColor", CVAR_TRACKER_ITEM("BgColor"), { 0, 0, 0, 0 }, true, - ColorPickerRandomButton | ColorPickerResetButton, THEME_COLOR); + if (ImGui::BeginTable("itemTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { + ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Section settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableHeadersRow(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + SohGui::mSohMenu->MenuDrawItem(backgroundColor, 250, THEME_COLOR); + ImGui::PopItemWidth(); + SohGui::mSohMenu->MenuDrawItem(windowTypeWidget, 250, THEME_COLOR); - ImGui::PopItemWidth(); - if (CVarCombobox("Window Type", CVAR_TRACKER_ITEM("WindowType"), windowTypes, - ComboboxOptions() - .DefaultIndex(TRACKER_WINDOW_FLOATING) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } + if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { + if (CVarCheckbox("Enable Dragging", CVAR_TRACKER_ITEM("Draggable"), CheckboxOptions().Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + if (CVarCheckbox("Only Enable While Paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"), + CheckboxOptions().Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + if (CVarCombobox("Display Mode", CVAR_TRACKER_ITEM("DisplayType.Main"), displayModes, + ComboboxOptions() + .DefaultIndex(TRACKER_DISPLAY_ALWAYS) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == + TRACKER_DISPLAY_COMBO_BUTTON) { + if (CVarCombobox("Combo Button 1", CVAR_TRACKER_ITEM("ComboButton1"), buttons, + ComboboxOptions() + .DefaultIndex(TRACKER_COMBO_BUTTON_L) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + if (CVarCombobox("Combo Button 2", CVAR_TRACKER_ITEM("ComboButton2"), buttons, + ComboboxOptions() + .DefaultIndex(TRACKER_COMBO_BUTTON_R) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + } + } + ImGui::Separator(); + CVarSliderInt("Icon size : %dpx", CVAR_TRACKER_ITEM("IconSize"), + IntSliderOptions().Min(25).Max(128).DefaultValue(36).Color(THEME_COLOR)); + CVarSliderInt("Icon margins : %dpx", CVAR_TRACKER_ITEM("IconSpacing"), + IntSliderOptions().Min(-5).Max(50).DefaultValue(12).Color(THEME_COLOR)); + CVarSliderInt("Text size : %dpx", CVAR_TRACKER_ITEM("TextSize"), + IntSliderOptions().Min(1).Max(30).DefaultValue(13).Color(THEME_COLOR)); - if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { - if (CVarCheckbox("Enable Dragging", CVAR_TRACKER_ITEM("Draggable"), CheckboxOptions().Color(THEME_COLOR))) { - shouldUpdateVectors = true; + ImGui::NewLine(); + SohGui::mSohMenu->MenuDrawItem(ammoTracking, 250, THEME_COLOR); + if (CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == + ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || + CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == + ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) { + if (CVarCheckbox("Align count to left side", CVAR_TRACKER_ITEM("ItemCountAlignLeft"), + CheckboxOptions().Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } } - if (CVarCheckbox("Only enable while paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"), - CheckboxOptions().Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarCombobox("Display Mode", CVAR_TRACKER_ITEM("DisplayType.Main"), displayModes, + + SohGui::mSohMenu->MenuDrawItem(keyTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(triforcePieceCount, 250, THEME_COLOR); + + ImGui::TableNextColumn(); + + if (CVarCombobox("Inventory", CVAR_TRACKER_ITEM("DisplayType.Inventory"), displayTypes, ComboboxOptions() - .DefaultIndex(TRACKER_DISPLAY_ALWAYS) + .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { shouldUpdateVectors = true; } - if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == - TRACKER_DISPLAY_COMBO_BUTTON) { - if (CVarCombobox("Combo Button 1", CVAR_TRACKER_ITEM("ComboButton1"), buttons, - ComboboxOptions() - .DefaultIndex(TRACKER_COMBO_BUTTON_L) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarCombobox("Combo Button 2", CVAR_TRACKER_ITEM("ComboButton2"), buttons, - ComboboxOptions() - .DefaultIndex(TRACKER_COMBO_BUTTON_R) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - } - } - ImGui::Separator(); - CVarSliderInt("Icon size : %dpx", CVAR_TRACKER_ITEM("IconSize"), - IntSliderOptions().Min(25).Max(128).DefaultValue(36).Color(THEME_COLOR)); - CVarSliderInt("Icon margins : %dpx", CVAR_TRACKER_ITEM("IconSpacing"), - IntSliderOptions().Min(-5).Max(50).DefaultValue(12).Color(THEME_COLOR)); - CVarSliderInt("Text size : %dpx", CVAR_TRACKER_ITEM("TextSize"), - IntSliderOptions().Min(1).Max(30).DefaultValue(13).Color(THEME_COLOR)); - - ImGui::NewLine(); - CVarCombobox("Ammo/Capacity Tracking", CVAR_TRACKER_ITEM("ItemCountType"), itemTrackerCapacityTrackOptions, - ComboboxOptions() - .DefaultIndex(ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) - .ComponentAlignment(ComponentAlignments::Left) - .LabelPosition(LabelPositions::Above) - .Color(THEME_COLOR) - .Tooltip("Customize what the numbers under each item are tracking." - "\n\nNote: items without capacity upgrades will track ammo even in capacity mode")); - if (CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == - ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || - CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == - ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) { - if (CVarCheckbox("Align count to left side", CVAR_TRACKER_ITEM("ItemCountAlignLeft"), - CheckboxOptions().Color(THEME_COLOR))) { + if (CVarCombobox("Equipment", CVAR_TRACKER_ITEM("DisplayType.Equipment"), displayTypes, + ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR))) { shouldUpdateVectors = true; } - } - - CVarCombobox("Key Count Tracking", CVAR_TRACKER_ITEM("KeyCounts"), itemTrackerKeyTrackOptions, - ComboboxOptions() - .DefaultIndex(KEYS_COLLECTED_MAX) - .ComponentAlignment(ComponentAlignments::Left) - .LabelPosition(LabelPositions::Above) - .Color(THEME_COLOR) - .Tooltip("Customize what numbers are shown for key tracking.")); - - CVarCombobox("Triforce Piece Count Tracking", CVAR_TRACKER_ITEM("TriforcePieceCounts"), - itemTrackerTriforcePieceTrackOptions, - ComboboxOptions() - .DefaultIndex(TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX) - .ComponentAlignment(ComponentAlignments::Left) - .LabelPosition(LabelPositions::Above) - .Color(THEME_COLOR) - .Tooltip("Customize what numbers are shown for triforce piece tracking.")); - - ImGui::TableNextColumn(); - - if (CVarCombobox("Inventory", CVAR_TRACKER_ITEM("DisplayType.Inventory"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarCombobox("Equipment", CVAR_TRACKER_ITEM("DisplayType.Equipment"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarCombobox("Misc", CVAR_TRACKER_ITEM("DisplayType.Misc"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarCombobox("Dungeon Rewards", CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == - SECTION_DISPLAY_SEPARATE) { - if (CVarCheckbox("Circle display", CVAR_TRACKER_ITEM("DungeonRewardsLayout"), - CheckboxOptions().DefaultValue(false).Color(THEME_COLOR))) { + if (CVarCombobox("Misc", CVAR_TRACKER_ITEM("DisplayType.Misc"), displayTypes, + ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR))) { shouldUpdateVectors = true; } - } - if (CVarCombobox("Songs", CVAR_TRACKER_ITEM("DisplayType.Songs"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarCombobox("Dungeon Items", CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != - SECTION_DISPLAY_HIDDEN) { - if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == + if (CVarCombobox("Dungeon Rewards", CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), displayTypes, + ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { - if (CVarCheckbox("Horizontal display", CVAR_TRACKER_ITEM("DungeonItems.Layout"), + if (CVarCheckbox("Circle display", CVAR_TRACKER_ITEM("DungeonRewardsLayout"), + CheckboxOptions().DefaultValue(false).Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + } + if (CVarCombobox("Songs", CVAR_TRACKER_ITEM("DisplayType.Songs"), displayTypes, + ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + SohGui::mSohMenu->MenuDrawItem(dungeonItemTracking, 250, THEME_COLOR); + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != + SECTION_DISPLAY_HIDDEN) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == + SECTION_DISPLAY_SEPARATE) { + if (CVarCheckbox("Horizontal display", CVAR_TRACKER_ITEM("DungeonItems.Layout"), + CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) { + shouldUpdateVectors = true; + } + } + if (CVarCheckbox("Maps and compasses", CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) { shouldUpdateVectors = true; } } - if (CVarCheckbox("Maps and compasses", CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), - CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - } - if (CVarCombobox("Greg", CVAR_TRACKER_ITEM("DisplayType.Greg"), extendedDisplayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } + SohGui::mSohMenu->MenuDrawItem(gregTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(triforcePieceTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(bossSoulsTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(ocarinaButtonTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(overworldKeysTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(fishingPoleTracking, 250, THEME_COLOR); - if (CVarCombobox("Triforce Pieces", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Boss Souls", CVAR_TRACKER_ITEM("DisplayType.BossSouls"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Overworld Keys", CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Fishing Pole", CVAR_TRACKER_ITEM("DisplayType.FishingPole"), extendedDisplayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Total Checks", "gTrackers.ItemTracker.TotalChecks.DisplayType", minimalDisplayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_MINIMAL_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || - (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING && - CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) != - TRACKER_DISPLAY_COMBO_BUTTON)) { - if (CVarCombobox("Personal notes", CVAR_TRACKER_ITEM("DisplayType.Notes"), displayTypes, + if (CVarCombobox("Total Checks", CVAR_TRACKER_ITEM("TotalChecks.DisplayType"), minimalDisplayTypes, ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .DefaultIndex(SECTION_DISPLAY_MINIMAL_HIDDEN) .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { shouldUpdateVectors = true; } - } - CVarCheckbox("Show Hookshot Identifiers", CVAR_TRACKER_ITEM("HookshotIdentifier"), - CheckboxOptions() - .Tooltip("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot.") - .Color(THEME_COLOR)); - ImGui::PopStyleVar(1); - ImGui::EndTable(); + SohGui::mSohMenu->MenuDrawItem(personalNotesWiget, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(hookshotIdentWidget, 250, THEME_COLOR); + + ImGui::PopStyleVar(1); + ImGui::EndTable(); + } } void ItemTrackerWindow::InitElement() { @@ -2003,3 +1951,178 @@ void ItemTrackerWindow::InitElement() { GameInteractor::Instance->RegisterGameHook(ItemTrackerOnFrame); } + +void RegisterItemTrackerWidgets() { + backgroundColor = { .name = "Background Color##gItemTrackerBgColor", .type = WidgetType::WIDGET_CVAR_COLOR_PICKER }; + backgroundColor.CVar(CVAR_TRACKER_ITEM("BgColor")) + .Options( + ColorPickerOptions().Color(THEME_COLOR).DefaultValue({ 0, 0, 0, 0 }).UseAlpha().ShowReset().ShowRandom()); + SohGui::mSohMenu->AddSearchWidget({ backgroundColor, "Randomizer", "Item Tracker", "General Settings" }); + + windowTypeWidget = { .name = "Window Type", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + windowTypeWidget.CVar(CVAR_TRACKER_ITEM("WindowType")) + .Options(ComboboxOptions() + .DefaultIndex(TRACKER_WINDOW_FLOATING) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(windowTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + SohGui::mSohMenu->AddSearchWidget({ windowTypeWidget, "Randomizer", "Item Tracker", "General Settings" }); + enableDraggingWidget; + onlyPausedWidget; + + ammoTracking = { .name = "Ammo/Capacity Tracking", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + ammoTracking.CVar(CVAR_TRACKER_ITEM("ItemCountType")) + .Options(ComboboxOptions() + .DefaultIndex(ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(itemTrackerCapacityTrackOptions) + .Tooltip("Customize what the numbers under each item are tracking." + "\n\nNote: items without capacity upgrades will track ammo even in capacity mode")); + SohGui::mSohMenu->AddSearchWidget({ ammoTracking, "Randomizer", "Item Tracker", "General Settings" }); + + keyTracking = { .name = "Key Count Tracking", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + keyTracking.CVar(CVAR_TRACKER_ITEM("KeyCounts")) + .Options(ComboboxOptions() + .DefaultIndex(KEYS_COLLECTED_MAX) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(itemTrackerKeyTrackOptions) + .Tooltip("Customize what numbers are shown for key tracking.")); + SohGui::mSohMenu->AddSearchWidget({ keyTracking, "Randomizer", "Item Tracker", "General Settings" }); + + triforcePieceTracking = { .name = "Triforce Pieces", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + triforcePieceTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.TriforcePieces")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + SohGui::mSohMenu->AddSearchWidget({ triforcePieceTracking, "Randomizer", "Item Tracker", "General Settings" }); + + dungeonItemTracking = { .name = "Dungeon Items", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + dungeonItemTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.DungeonItems")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { dungeonItemTracking, "Randomizer", "Item Tracker", "General Settings", "keys maps compasses icon" }); + + gregTracking = { .name = "Greg", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + gregTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.Greg")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(extendedDisplayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget({ gregTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + bossSoulsTracking = { .name = "Boss Souls", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + bossSoulsTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.BossSouls")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget({ bossSoulsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + triforcePieceCount = { .name = "Triforce Piece Count Tracking", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + triforcePieceCount.CVar(CVAR_TRACKER_ITEM("TriforcePieceCounts")) + .Options(ComboboxOptions() + .DefaultIndex(TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(itemTrackerTriforcePieceTrackOptions) + .Tooltip("Customize what numbers are shown for triforce piece tracking.")); + SohGui::mSohMenu->AddSearchWidget({ triforcePieceCount, "Randomizer", "Item Tracker", "General Settings" }); + + ocarinaButtonTracking = { .name = "Ocarina Buttons", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + ocarinaButtonTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { ocarinaButtonTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + overworldKeysTracking = { .name = "Overworld Keys", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + overworldKeysTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.OverworldKeys")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { overworldKeysTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + fishingPoleTracking = { .name = "Fishing Pole", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + fishingPoleTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.FishingPole")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(extendedDisplayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { fishingPoleTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + personalNotesWiget = { .name = "Personal notes", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + static const char* notesDisabledTooltip = + "Disabled because tracker is set to floating and display combo is enabled."; + personalNotesWiget.CVar(CVAR_TRACKER_ITEM("DisplayType.Notes")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .PreFunc([&](WidgetInfo& info) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || + (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING && + CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) != + TRACKER_DISPLAY_COMBO_BUTTON)) { + info.options.get()->disabled = true; + info.options.get()->disabledTooltip = notesDisabledTooltip; + } + }) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget({ personalNotesWiget, "Randomizer", "Item Tracker", "General Settings" }); + + hookshotIdentWidget = { .name = "Show Hookshot Identifiers", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + hookshotIdentWidget.CVar(CVAR_SETTING("FreeLook.Enabled")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot.")); + SohGui::mSohMenu->AddSearchWidget( + { hookshotIdentWidget, "Settings", "Controls", "Camera Controls", "longshot icon" }); +} + +static RegisterMenuInitFunc menuInitFunc(RegisterItemTrackerWidgets); diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 51101f6fa..ade5dd163 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -243,6 +243,11 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE); + if (Randomizer_GetSettingValue(RSK_FOREST) == RO_CLOSED_FOREST_OFF) { + Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH); + } + // Go away Ruto (Water Temple first cutscene). gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10); diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index b9392c64a..4f28cd021 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -6,7 +6,7 @@ #include -#include "consolevariablebridge.h" +#include #include "soh/Network/Archipelago/ArchipelagoConsoleWindow.h" @@ -217,6 +217,7 @@ void Settings::CreateOptions() { OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF); OPT_U8(RSK_SHUFFLE_GRASS, "Shuffle Grass", {"Off", "Dungeons", "Overworld", "All Grass/Bushes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGrass"), mOptionDescriptions[RSK_SHUFFLE_GRASS], WidgetType::Combobox, RO_SHUFFLE_GRASS_OFF); OPT_U8(RSK_SHUFFLE_CRATES, "Shuffle Crates", {"Off", "Dungeons", "Overworld", "All Crates"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleCrates"), mOptionDescriptions[RSK_SHUFFLE_CRATES], WidgetType::Combobox, RO_SHUFFLE_CRATES_OFF); + OPT_BOOL(RSK_SHUFFLE_TREES, "Shuffle Trees", CVAR_RANDOMIZER_SETTING("ShuffleTrees"), mOptionDescriptions[RSK_SHUFFLE_TREES]); OPT_BOOL(RSK_SHUFFLE_FISHING_POLE, "Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]); OPT_U8(RSK_SHUFFLE_MERCHANTS, "Shuffle Merchants", {"Off", "Bean Merchant Only", "All But Beans", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF, IMFLAG_NONE); OPT_U8(RSK_MERCHANT_PRICES, "Merchant Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPrices"), mOptionDescriptions[RSK_MERCHANT_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE); @@ -240,7 +241,10 @@ void Settings::CreateOptions() { OPT_U8(RSK_FISHSANITY, "Fishsanity", {"Off", "Shuffle only Hyrule Loach", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF); OPT_U8(RSK_FISHSANITY_POND_COUNT, "Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE); OPT_BOOL(RSK_FISHSANITY_AGE_SPLIT, "Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]); - OPT_BOOL(RSK_SHUFFLE_FAIRIES, "Shuffle Fairies", CVAR_RANDOMIZER_SETTING("ShuffleFairies"), mOptionDescriptions[RSK_SHUFFLE_FAIRIES]); + OPT_BOOL(RSK_SHUFFLE_FOUNTAIN_FAIRIES, "Shuffle Fairies in Fountains", CVAR_RANDOMIZER_SETTING("ShuffleFountainFairies"), mOptionDescriptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES]); + OPT_BOOL(RSK_SHUFFLE_STONE_FAIRIES, "Shuffle Gossip Stone Fairies", CVAR_RANDOMIZER_SETTING("ShuffleStoneFairies"), mOptionDescriptions[RSK_SHUFFLE_STONE_FAIRIES]); + OPT_BOOL(RSK_SHUFFLE_BEAN_FAIRIES, "Shuffle Bean Fairies", CVAR_RANDOMIZER_SETTING("ShuffleBeanFairies"), mOptionDescriptions[RSK_SHUFFLE_BEAN_FAIRIES]); + OPT_BOOL(RSK_SHUFFLE_SONG_FAIRIES, "Shuffle Fairy Spots", CVAR_RANDOMIZER_SETTING("ShuffleFairySpots"), mOptionDescriptions[RSK_SHUFFLE_SONG_FAIRIES]); OPT_U8(RSK_SHUFFLE_MAPANDCOMPASS, "Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); OPT_U8(RSK_KEYSANITY, "Small Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Keysanity"), mOptionDescriptions[RSK_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); OPT_U8(RSK_GERUDO_KEYS, "Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoKeys"), mOptionDescriptions[RSK_GERUDO_KEYS], WidgetType::Combobox, RO_GERUDO_KEYS_VANILLA); @@ -281,6 +285,7 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_GREG_HINT, "Greg the Green Rupee Hint", CVAR_RANDOMIZER_SETTING("GregHint"), mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE); OPT_BOOL(RSK_LOACH_HINT, "Hyrule Loach Hint", CVAR_RANDOMIZER_SETTING("LoachHint"), mOptionDescriptions[RSK_LOACH_HINT], IMFLAG_NONE); OPT_BOOL(RSK_SARIA_HINT, "Saria's Hint", CVAR_RANDOMIZER_SETTING("SariaHint"), mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE); + OPT_BOOL(RSK_MIDO_HINT, "Mido's Hint", CVAR_RANDOMIZER_SETTING("MidoHint"), mOptionDescriptions[RSK_MIDO_HINT], IMFLAG_NONE); OPT_BOOL(RSK_FISHING_POLE_HINT, "Fishing Pole Hint", CVAR_RANDOMIZER_SETTING("FishingPoleHint"), mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE); OPT_BOOL(RSK_FROGS_HINT, "Frog Ocarina Game Hint", CVAR_RANDOMIZER_SETTING("FrogsHint"), mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE); OPT_BOOL(RSK_OOT_HINT, "Ocarina of Time Hint", CVAR_RANDOMIZER_SETTING("OoTHint"), mOptionDescriptions[RSK_OOT_HINT], IMFLAG_NONE); @@ -304,6 +309,7 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_SUNLIGHT_ARROWS, "Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); OPT_U8(RSK_INFINITE_UPGRADES, "Infinite Upgrades", {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades"), mOptionDescriptions[RSK_INFINITE_UPGRADES]); OPT_BOOL(RSK_SKELETON_KEY, "Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]); + OPT_BOOL(RSK_SLINGBOW_BREAK_BEEHIVES, "Slingshot/Bow Can Break Beehives", CVAR_RANDOMIZER_SETTING("SlingBowBeehives"), mOptionDescriptions[RSK_SLINGBOW_BREAK_BEEHIVES]); OPT_U8(RSK_ITEM_POOL, "Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED); OPT_U8(RSK_ICE_TRAPS, "Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL); // TODO: Remove Double Defense, Progressive Goron Sword @@ -329,7 +335,7 @@ void Settings::CreateOptions() { OPT_U8(RSK_STARTING_SKULLTULA_TOKEN, "Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), "", WidgetType::Slider); OPT_U8(RSK_STARTING_HEARTS, "Starting Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingHearts"), "", WidgetType::Slider, 2); // TODO: Remainder of Starting Items - OPT_U8(RSK_LOGIC_RULES, "Logic", {"Glitchless", "No Logic", "Vanilla"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LogicRules"), mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS); + OPT_U8(RSK_LOGIC_RULES, "Logic", {"Glitchless", "No Logic"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LogicRules"), mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS); OPT_BOOL(RSK_ALL_LOCATIONS_REACHABLE, "All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WidgetType::Checkbox, RO_GENERIC_ON); OPT_BOOL(RSK_SKULLS_SUNS_SONG, "Night Skulltula's Expect Sun's Song", CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), mOptionDescriptions[RSK_SKULLS_SUNS_SONG]); OPT_U8(RSK_DAMAGE_MULTIPLIER, "Damage Multiplier", {"x1/2", "x1", "x2", "x4", "x8", "x16", "OHKO"}, OptionCategory::Setting, "", "", WidgetType::Slider, RO_DAMAGE_MULTIPLIER_DEFAULT); @@ -358,9 +364,7 @@ void Settings::CreateOptions() { // OPT_TRICK(RT_FLAME_STORAGE, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, // Tricks::Tag::GLITCH}, "Flame Storage", "Enables locations requiring flame storage."); OPT_TRICK(RT_GROUND_CLIP, // RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Ground Clip", - // "Enables locations requiring ground clips."); OPT_TRICK(RT_GROUND_JUMP, RCQUEST_BOTH, RA_NONE, - // {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Ground Jump", "Enables locations - // requiring ground jumps."); OPT_TRICK(RT_HESS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, + // "Enables locations requiring ground clips."); OPT_TRICK(RT_HESS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, // Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "HESS", "Enables locations requiring a Hyper Extended Super // Slide."); OPT_TRICK(RT_HOOKSHOT_CLIP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, // Tricks::Tag::GLITCH}, "Hookshot Clip", "Enables locations requiring Hookshot clips."); @@ -407,6 +411,20 @@ void Settings::CreateOptions() { OPT_TRICK(RT_OPEN_UNDERWATER_CHEST, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "Open Underwater Chests", "Underwater chests can be opened by wearing iron boots and hookshotting the chest."); + OPT_TRICK(RT_HOOKSHOT_EXTENSION, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE }, + "Hookshot/Projectile Extension", + "Slightly extends range. Also allows clipping projectile past collision. Used for:\n" + "- Crossing Gerudo Valley with Hookshot\n" + "- Retrieving DMT Gold Skulltula beside bomb flower\n" + "- Hitting switch through wall in Spirit Temple's big mirror room with Bow, Slingshot, or Hookshot\n" + "- Hitting switch through wall in Spirit Trial with Bow or Slingshot"); + OPT_TRICK(RT_GROUND_JUMP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "Ground Jump", + "Enables requiring ground jumps."); + OPT_TRICK(RT_GROUND_JUMP_HARD, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE, Tricks::Tag::GLITCH }, + "Hard Ground Jumps", + "Enables ground jumps which require some precision outside of setting up jump:\n- While using Hover " + "Boots in Forest Temple Courtyard to reach upper ledge\n- While using Hover Boots in Shadow Temple " + "invisible spike room to reach door\n- Jumping past second step in Ice Cavern"); OPT_TRICK(RT_KF_ADULT_GS, RCQUEST_BOTH, RA_KOKIRI_FOREST, { Tricks::Tag::NOVICE }, "Adult Kokiri Forest GS with Hover Boots", "Can be obtained without Hookshot by using the Hover Boots off of one of the roots."); @@ -472,10 +490,6 @@ void Settings::CreateOptions() { "Death Mountain Trail Chest with Strength", "Child Link can blow up the wall using a nearby bomb flower. You must backwalk with the flower and then " "quickly throw it toward the wall."); - OPT_TRICK(RT_DMT_HOOKSHOT_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::INTERMEDIATE }, - "Death Mountain Trail Lower Red Rock GS with Hookshot", - "After killing the Skulltula, the token can be fished out of the rock without needing to destroy it, by " - "using the Hookshot in the correct way."); OPT_TRICK(RT_DMT_HOVERS_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::ADVANCED }, "Death Mountain Trail Lower Red Rock GS with Hover Boots", "After killing the Skulltula, the token can be collected without needing to destroy the rock by " @@ -968,17 +982,20 @@ void Settings::CreateOptions() { "Shadow Temple Bongo Bongo without Lens of Truth", "Bongo Bongo can be defeated without the use of Lens of Truth, as the hands give a pretty good idea of " "where the eye is."); - OPT_TRICK(RT_SHADOW_UMBRELLA, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::EXPERT }, + OPT_TRICK(RT_SHADOW_UMBRELLA_HOVER, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::EXPERT }, "Shadow Temple Stone Umbrella Skip", "A very precise Hover Boots movement from off of the lower chest can get you on top of the crushing " "spikes without needing to pull the block. Applies to both Vanilla and Master Quest."); + OPT_TRICK(RT_SHADOW_UMBRELLA_CLIP, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, + "Shadow Temple Stone Umbrella Clip", + "Backflipping as the falling spikes fall clips above without needing any other requirements. " + "Applies to both Vanilla and Master Quest."); OPT_TRICK(RT_SHADOW_UMBRELLA_GS, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::EXPERT }, "Shadow Temple Falling Spikes GS with Hover Boots", "After killing the Skulltula, a very precise Hover Boots movement from off of the lower chest can get " "you on top of the crushing spikes without needing to pull the block. From there, another very precise " "Hover Boots movement can be used to obtain the token without needing the Hookshot. Applies to both " - "Vanilla and Master Quest. For obtaining the chests in this room with just Hover Boots, be sure to " - "enable \"Shadow Temple Stone Umbrella Skip\"."); + "Vanilla and Master Quest."); OPT_TRICK(RT_SHADOW_FREESTANDING_KEY, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "Shadow Temple Freestanding Key with Bombchu", "Release the Bombchu with good timing so that it explodes near the bottom of the pot."); @@ -1282,6 +1299,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_COWS], &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_CRATES], + &mOptions[RSK_SHUFFLE_TREES], &mOptions[RSK_SHUFFLE_MERCHANTS], &mOptions[RSK_MERCHANT_PRICES], &mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE], @@ -1297,7 +1315,10 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_ADULT_TRADE], &mOptions[RSK_SHUFFLE_100_GS_REWARD], &mOptions[RSK_SHUFFLE_BOSS_SOULS], - &mOptions[RSK_SHUFFLE_FAIRIES], + &mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES], + &mOptions[RSK_SHUFFLE_STONE_FAIRIES], + &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], + &mOptions[RSK_SHUFFLE_SONG_FAIRIES], &mOptions[RSK_SHUFFLE_GRASS], }, WidgetContainerType::COLUMN); @@ -1352,14 +1373,31 @@ void Settings::CreateOptions() { WidgetContainerType::SECTION); mOptionGroups[RSG_EXTRA_HINTS_IMGUI] = OptionGroup::SubGroup( "Extra Hints", - { &mOptions[RSK_TOT_ALTAR_HINT], &mOptions[RSK_GANONDORF_HINT], &mOptions[RSK_SHEIK_LA_HINT], - &mOptions[RSK_DAMPES_DIARY_HINT], &mOptions[RSK_GREG_HINT], &mOptions[RSK_LOACH_HINT], - &mOptions[RSK_SARIA_HINT], &mOptions[RSK_FROGS_HINT], &mOptions[RSK_OOT_HINT], - &mOptions[RSK_BIGGORON_HINT], &mOptions[RSK_BIG_POES_HINT], &mOptions[RSK_CHICKENS_HINT], - &mOptions[RSK_MALON_HINT], &mOptions[RSK_HBA_HINT], &mOptions[RSK_FISHING_POLE_HINT], - &mOptions[RSK_WARP_SONG_HINTS], &mOptions[RSK_SCRUB_TEXT_HINT], &mOptions[RSK_MERCHANT_TEXT_HINT], - &mOptions[RSK_KAK_10_SKULLS_HINT], &mOptions[RSK_KAK_20_SKULLS_HINT], &mOptions[RSK_KAK_30_SKULLS_HINT], - &mOptions[RSK_KAK_40_SKULLS_HINT], &mOptions[RSK_KAK_50_SKULLS_HINT], &mOptions[RSK_KAK_100_SKULLS_HINT], + { &mOptions[RSK_TOT_ALTAR_HINT], + &mOptions[RSK_GANONDORF_HINT], + &mOptions[RSK_SHEIK_LA_HINT], + &mOptions[RSK_DAMPES_DIARY_HINT], + &mOptions[RSK_GREG_HINT], + &mOptions[RSK_LOACH_HINT], + &mOptions[RSK_SARIA_HINT], + &mOptions[RSK_MIDO_HINT], + &mOptions[RSK_FROGS_HINT], + &mOptions[RSK_OOT_HINT], + &mOptions[RSK_BIGGORON_HINT], + &mOptions[RSK_BIG_POES_HINT], + &mOptions[RSK_CHICKENS_HINT], + &mOptions[RSK_MALON_HINT], + &mOptions[RSK_HBA_HINT], + &mOptions[RSK_FISHING_POLE_HINT], + &mOptions[RSK_WARP_SONG_HINTS], + &mOptions[RSK_SCRUB_TEXT_HINT], + &mOptions[RSK_MERCHANT_TEXT_HINT], + &mOptions[RSK_KAK_10_SKULLS_HINT], + &mOptions[RSK_KAK_20_SKULLS_HINT], + &mOptions[RSK_KAK_30_SKULLS_HINT], + &mOptions[RSK_KAK_40_SKULLS_HINT], + &mOptions[RSK_KAK_50_SKULLS_HINT], + &mOptions[RSK_KAK_100_SKULLS_HINT], &mOptions[RSK_MASK_SHOP_HINT] }, WidgetContainerType::SECTION, "This setting adds some hints at locations other than Gossip Stones."); mOptionGroups[RSG_ITEM_POOL_HINTS_IMGUI_COLUMN] = @@ -1378,6 +1416,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SUNLIGHT_ARROWS], &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], + &mOptions[RSK_SLINGBOW_BREAK_BEEHIVES], }, WidgetContainerType::COLUMN); mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE] = @@ -1515,6 +1554,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_COWS], &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_CRATES], + &mOptions[RSK_SHUFFLE_TREES], &mOptions[RSK_SHUFFLE_KOKIRI_SWORD], &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], @@ -1540,7 +1580,10 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_DEKU_STICK_BAG], &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], &mOptions[RSK_SHUFFLE_FREESTANDING], - &mOptions[RSK_SHUFFLE_FAIRIES], + &mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES], + &mOptions[RSK_SHUFFLE_STONE_FAIRIES], + &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], + &mOptions[RSK_SHUFFLE_SONG_FAIRIES], }); mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS] = OptionGroup("Shuffle Dungeon Items", { @@ -1619,6 +1662,7 @@ void Settings::CreateOptions() { &mOptions[RSK_GREG_HINT], &mOptions[RSK_LOACH_HINT], &mOptions[RSK_SARIA_HINT], + &mOptions[RSK_MIDO_HINT], &mOptions[RSK_FROGS_HINT], &mOptions[RSK_OOT_HINT], &mOptions[RSK_WARP_SONG_HINTS], @@ -1643,6 +1687,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SUNLIGHT_ARROWS], &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], + &mOptions[RSK_SLINGBOW_BREAK_BEEHIVES], }); mOptionGroups[RSG_ITEM_POOL] = OptionGroup( "Item Pool Settings", std::initializer_list({ &mOptions[RSK_ITEM_POOL], &mOptions[RSK_ICE_TRAPS] })); @@ -1809,158 +1854,134 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Hide(); mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Hide(); mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Hide(); - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { - mOptionGroups[RSG_AREA_ACCESS_IMGUI].Disable(); - mOptions[RSK_STARTING_AGE].Disable(""); - mOptions[RSK_GERUDO_FORTRESS].Disable(""); - mOptions[RSK_RAINBOW_BRIDGE].Disable(""); - mOptions[RSK_BRIDGE_OPTIONS].Disable(""); - mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Disable(""); - mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Disable(""); - mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Disable(""); - mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Disable(""); - mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Disable(""); - mOptions[RSK_GANONS_TRIALS].Disable(""); - mOptions[RSK_TRIAL_COUNT].Disable(""); - mOptions[RSK_TRIFORCE_HUNT].Disable(""); - mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Disable(""); - mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Disable(""); - mOptionGroups[RSG_ITEMS_IMGUI_TABLE].Disable(); - mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE].Disable(); - mOptions[RSK_LINKS_POCKET].Disable(""); - mOptions[RSK_STARTING_OCARINA].Disable(""); + mOptionGroups[RSG_AREA_ACCESS_IMGUI].Enable(); + // Starting Age - Disabled when Forest is set to Closed or under very specific conditions + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == + RO_GENERIC_OFF) /* closed door of time with ocarina shuffle off */ { + mOptions[RSK_STARTING_AGE].Disable("This option is disabled due to other options making the game unbeatable."); } else { - mOptionGroups[RSG_AREA_ACCESS_IMGUI].Enable(); - // Starting Age - Disabled when Forest is set to Closed or under very specific conditions - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED && - CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == - RO_GENERIC_OFF) /* closed door of time with ocarina shuffle off */ { - mOptions[RSK_STARTING_AGE].Disable( - "This option is disabled due to other options making the game unbeatable."); - } else { - mOptions[RSK_STARTING_AGE].Enable(); - } - mOptions[RSK_GERUDO_FORTRESS].Enable(); - mOptions[RSK_RAINBOW_BRIDGE].Enable(); - mOptions[RSK_BRIDGE_OPTIONS].Enable(); - mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Enable(); - mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Enable(); - mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Enable(); - mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Enable(); - mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Enable(); - const uint8_t bridgeOpt = - CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_VANILLA)) { - case RO_BRIDGE_STONES: - // Show Bridge Options and Stone Count slider - mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); - mOptions[RSK_BRIDGE_OPTIONS].Unhide(); - mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Unhide(); - if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { - if (mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].GetOptionCount() == 4) { - mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].ChangeOptions(NumOpts(0, 4)); - } - } else { - if (mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].GetOptionCount() == 5) { - mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].ChangeOptions(NumOpts(0, 3)); - } - } - break; - case RO_BRIDGE_MEDALLIONS: - // Show Bridge Options and Medallion Count Slider - mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); - mOptions[RSK_BRIDGE_OPTIONS].Unhide(); - mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Unhide(); - if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { - if (mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].GetOptionCount() == 7) { - mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 7)); - } - } else { - if (mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].GetOptionCount() == 8) { - mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 6)); - } - } - break; - case RO_BRIDGE_DUNGEON_REWARDS: - // Show Bridge Options and Dungeon Reward Count Slider - mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); - mOptions[RSK_BRIDGE_OPTIONS].Unhide(); - mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Unhide(); - if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { - if (mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].GetOptionCount() == 10) { - mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].ChangeOptions(NumOpts(0, 10)); - } - } else { - if (mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].GetOptionCount() == 11) { - mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].ChangeOptions(NumOpts(0, 9)); - } - } - break; - case RO_BRIDGE_DUNGEONS: - // Show Bridge Options and Dungeon Count Slider - mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); - mOptions[RSK_BRIDGE_OPTIONS].Unhide(); - mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Unhide(); - if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { - if (mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].GetOptionCount() == 9) { - mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 9)); - } - } else { - if (mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].GetOptionCount() == 10) { - mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 8)); - } - } - break; - case RO_BRIDGE_TOKENS: - // Show token count slider (not bridge options) - mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); - mOptions[RSK_BRIDGE_OPTIONS].Hide(); - mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Unhide(); - break; - default: - break; - } - mOptions[RSK_GANONS_TRIALS].Enable(); - mOptions[RSK_TRIAL_COUNT].Enable(); - // Only show the trial count slider if Trials is set to Set Number - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER) == - RO_GANONS_TRIALS_SET_NUMBER) { - mOptions[RSK_GANONS_TRIALS].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); - mOptions[RSK_TRIAL_COUNT].Unhide(); - } else { - mOptions[RSK_GANONS_TRIALS].AddFlag(IMFLAG_SEPARATOR_BOTTOM); - mOptions[RSK_TRIAL_COUNT].Hide(); - } - mOptions[RSK_TRIFORCE_HUNT].Enable(); - mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Enable(); - mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Enable(); - // Remove the pieces required/total sliders and add a separator after Tirforce Hunt if Triforce Hunt is off - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), RO_GENERIC_OFF) == RO_GENERIC_OFF) { - mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Hide(); - mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Hide(); - mOptions[RSK_TRIFORCE_HUNT].AddFlag(IMFLAG_SEPARATOR_BOTTOM); - } else { - mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Unhide(); - mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Unhide(); - mOptions[RSK_TRIFORCE_HUNT].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); - } - // Update triforce pieces required to be capped at the current value for pieces total. - const uint8_t triforceTotal = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), 30); - if (mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].GetOptionCount() != triforceTotal + 1) { - mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].ChangeOptions(NumOpts(1, triforceTotal + 1)); - } - mOptionGroups[RSG_ITEMS_IMGUI_TABLE].Enable(); - mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE].Enable(); - // Link's Pocket - Disabled when Dungeon Rewards are shuffled to End of Dungeon - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) == - RO_DUNGEON_REWARDS_END_OF_DUNGEON) { - mOptions[RSK_LINKS_POCKET].Disable( - "This option is disabled because \"Dungeon Rewards\" are shuffled to \"End of Dungeons\"."); - } else { - mOptions[RSK_LINKS_POCKET].Enable(); - } - mOptions[RSK_STARTING_OCARINA].Enable(); + mOptions[RSK_STARTING_AGE].Enable(); } + mOptions[RSK_GERUDO_FORTRESS].Enable(); + mOptions[RSK_RAINBOW_BRIDGE].Enable(); + mOptions[RSK_BRIDGE_OPTIONS].Enable(); + mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Enable(); + mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Enable(); + mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Enable(); + mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Enable(); + mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Enable(); + const uint8_t bridgeOpt = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_VANILLA)) { + case RO_BRIDGE_STONES: + // Show Bridge Options and Stone Count slider + mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_BRIDGE_OPTIONS].Unhide(); + mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Unhide(); + if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { + if (mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].GetOptionCount() == 4) { + mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].ChangeOptions(NumOpts(0, 4)); + } + } else { + if (mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].GetOptionCount() == 5) { + mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].ChangeOptions(NumOpts(0, 3)); + } + } + break; + case RO_BRIDGE_MEDALLIONS: + // Show Bridge Options and Medallion Count Slider + mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_BRIDGE_OPTIONS].Unhide(); + mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Unhide(); + if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { + if (mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].GetOptionCount() == 7) { + mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 7)); + } + } else { + if (mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].GetOptionCount() == 8) { + mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 6)); + } + } + break; + case RO_BRIDGE_DUNGEON_REWARDS: + // Show Bridge Options and Dungeon Reward Count Slider + mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_BRIDGE_OPTIONS].Unhide(); + mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Unhide(); + if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { + if (mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].GetOptionCount() == 10) { + mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].ChangeOptions(NumOpts(0, 10)); + } + } else { + if (mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].GetOptionCount() == 11) { + mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].ChangeOptions(NumOpts(0, 9)); + } + } + break; + case RO_BRIDGE_DUNGEONS: + // Show Bridge Options and Dungeon Count Slider + mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_BRIDGE_OPTIONS].Unhide(); + mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Unhide(); + if (bridgeOpt == RO_BRIDGE_GREG_REWARD) { + if (mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].GetOptionCount() == 9) { + mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 9)); + } + } else { + if (mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].GetOptionCount() == 10) { + mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 8)); + } + } + break; + case RO_BRIDGE_TOKENS: + // Show token count slider (not bridge options) + mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_BRIDGE_OPTIONS].Hide(); + mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Unhide(); + break; + default: + break; + } + mOptions[RSK_GANONS_TRIALS].Enable(); + mOptions[RSK_TRIAL_COUNT].Enable(); + // Only show the trial count slider if Trials is set to Set Number + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER) == + RO_GANONS_TRIALS_SET_NUMBER) { + mOptions[RSK_GANONS_TRIALS].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_TRIAL_COUNT].Unhide(); + } else { + mOptions[RSK_GANONS_TRIALS].AddFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_TRIAL_COUNT].Hide(); + } + mOptions[RSK_TRIFORCE_HUNT].Enable(); + mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Enable(); + mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Enable(); + // Remove the pieces required/total sliders and add a separator after Tirforce Hunt if Triforce Hunt is off + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), RO_GENERIC_OFF) == RO_GENERIC_OFF) { + mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Hide(); + mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Hide(); + mOptions[RSK_TRIFORCE_HUNT].AddFlag(IMFLAG_SEPARATOR_BOTTOM); + } else { + mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Unhide(); + mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Unhide(); + mOptions[RSK_TRIFORCE_HUNT].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + } + // Update triforce pieces required to be capped at the current value for pieces total. + const uint8_t triforceTotal = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), 30); + if (mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].GetOptionCount() != triforceTotal + 1) { + mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].ChangeOptions(NumOpts(1, triforceTotal + 1)); + } + mOptionGroups[RSG_ITEMS_IMGUI_TABLE].Enable(); + mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE].Enable(); + // Link's Pocket - Disabled when Dungeon Rewards are shuffled to End of Dungeon + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) == + RO_DUNGEON_REWARDS_END_OF_DUNGEON) { + mOptions[RSK_LINKS_POCKET].Disable( + "This option is disabled because \"Dungeon Rewards\" are shuffled to \"End of Dungeons\"."); + } else { + mOptions[RSK_LINKS_POCKET].Enable(); + } + mOptions[RSK_STARTING_OCARINA].Enable(); // Don't show any MQ options if both quests aren't available if (!(OTRGlobals::Instance->HasMasterQuest() && OTRGlobals::Instance->HasOriginal())) { @@ -2515,10 +2536,16 @@ void Settings::UpdateOptionProperties() { "setting where you present the loach to the fishing pond owner."); } - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 7) == 0) { - mOptions[RSK_CHICKENS_HINT].Disable("Anju will just give you the item instead with 0 chickens."); + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 10) == 0) { + mOptions[RSK_BIG_POES_HINT].Disable("Poe Collector will just give you the item instead with 0 big poes."); } else { - mOptions[RSK_CHICKENS_HINT].Enable(); + mOptions[RSK_BIG_POES_HINT].Enable(); + } + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), RO_GENERIC_OFF)) { + mOptions[RSK_SLINGBOW_BREAK_BEEHIVES].Enable(); + } else { + mOptions[RSK_SLINGBOW_BREAK_BEEHIVES].Disable( + "This option is disabled because Shuffle Beehives is not enabled."); } } @@ -2593,7 +2620,7 @@ void Context::FinalizeSettings(const std::set& excludedLocation } if (!mOptions[RSK_SHUFFLE_MASTER_SWORD]) { if (mOptions[RSK_STARTING_MASTER_SWORD]) { - this->GetItemLocation(RC_MASTER_SWORD_PEDESTAL)->SetExcludedOption(1); + this->GetItemLocation(RC_TOT_MASTER_SWORD)->SetExcludedOption(1); } } if (!mOptions[RSK_SHUFFLE_OCARINA]) { @@ -2871,15 +2898,6 @@ void Context::FinalizeSettings(const std::set& excludedLocation mLACSCondition = RO_LACS_VANILLA; } - if (mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) { - for (OptionValue* setting : VanillaLogicDefaults) { - // setting->SetDelayedOption(); - setting->Set(0); - } - // mOptions[RSK_KEYSANITY].SetDelayedOption(); - mOptions[RSK_KEYSANITY].Set(3); - } - if (!mOptions[RSK_SHUFFLE_WARP_SONGS]) { mOptions[RSK_WARP_SONG_HINTS].Set(RO_GENERIC_OFF); } diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index 75b855658..94d4016b8 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -71,6 +71,7 @@ std::unordered_map StaticData::hintNames = { { RH_ALTAR_CHILD, CustomMessage("ToT Altar as Child") }, { RH_ALTAR_ADULT, CustomMessage("ToT Altar as Adult") }, { RH_SARIA_HINT, CustomMessage("Saria's Magic Hint") }, + { RH_MIDO_HINT, CustomMessage("Mido's Kokiri Sword Hint") }, { RH_LOACH_HINT, CustomMessage("Loach Hint") }, { RH_FISHING_POLE, CustomMessage("Fishing Pole Hint") }, { RH_MINUET_WARP_LOC, CustomMessage("Minuet of Forest Destination") }, @@ -194,6 +195,7 @@ std::unordered_map StaticData::staticHintInfoMap {RH_DAMPES_DIARY, StaticHintInfo(HINT_TYPE_AREA, {RHT_DAMPE_DIARY}, RSK_DAMPES_DIARY_HINT, true, {}, {RG_PROGRESSIVE_HOOKSHOT}, {RC_DAMPE_HINT})}, {RH_GREG_RUPEE, StaticHintInfo(HINT_TYPE_AREA, {RHT_GREG_HINT}, RSK_GREG_HINT, true, {}, {RG_GREG_RUPEE}, {RC_GREG_HINT})}, {RH_SARIA_HINT, StaticHintInfo(HINT_TYPE_AREA, {RHT_SARIA_TALK_HINT, RHT_SARIA_SONG_HINT}, RSK_SARIA_HINT, true, {}, {RG_PROGRESSIVE_MAGIC_METER}, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, true)}, + {RH_MIDO_HINT, StaticHintInfo(HINT_TYPE_AREA, {RHT_MIDO_HINT}, RSK_MIDO_HINT, true, {}, {RG_KOKIRI_SWORD}, {}, true)}, {RH_LOACH_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_LOACH_HINT}, RSK_LOACH_HINT, true, {RC_LH_HYRULE_LOACH})}, {RH_FISHING_POLE, StaticHintInfo(HINT_TYPE_AREA, {RHT_FISHING_POLE_HINT}, RSK_FISHING_POLE_HINT, true, {}, {RG_FISHING_POLE}, {RC_FISHING_POLE_HINT}, true)}, {RH_HBA_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_HBA_HINT_SIGN, RHT_HBA_HINT_NOT_ON_HORSE, RHT_HBA_HINT_INITIAL, RHT_HBA_HINT_HAVE_1000}, RSK_HBA_HINT, true, {RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS})}, diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h index 7bdec17c1..cd24667a0 100644 --- a/soh/soh/Enhancements/randomizer/static_data.h +++ b/soh/soh/Enhancements/randomizer/static_data.h @@ -48,7 +48,10 @@ class StaticData { static std::vector GetStaticHintLocations(); static std::vector GetPondFishLocations(); static std::vector GetOverworldFishLocations(); - static std::vector GetOverworldFairyLocations(); + static std::vector GetFountainFairyLocations(); + static std::vector GetStoneFairyLocations(); + static std::vector GetBeanFairyLocations(); + static std::vector GetSongFairyLocations(); static void RegisterSongLocations(); static void RegisterBeehiveLocations(); static void RegisterCowLocations(); @@ -58,6 +61,7 @@ class StaticData { static void RegisterFreestandingLocations(); static void RegisterGrassLocations(); static void RegisterCrateLocations(); + static void RegisterTreeLocations(); static void InitHashMaps(); static std::array, 17> randomizerFishingPondFish; static std::unordered_map randomizerGrottoFishMap; diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 49657c3c2..8bcd19903 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -1,6 +1,5 @@ #include #include "soh/OTRGlobals.h" -#include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/enhancementTypes.h" @@ -166,7 +165,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li *should = false; } - u8 meetsBurningKakRequirements = LINK_IS_ADULT && + u8 meetsBurningKakRequirements = LINK_IS_ADULT && gSaveContext.cutsceneIndex < 0xFFF0 && gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && @@ -302,9 +301,10 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li } switch (actor->id) { case ACTOR_OBJ_SWITCH: { - if ((actor->params == 8224 && gPlayState->sceneNum == SCENE_DODONGOS_CAVERN) || - (actor->params == 6979 && gPlayState->sceneNum == SCENE_WATER_TEMPLE) && - CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { + if (((actor->params == 8224 && gPlayState->sceneNum == SCENE_DODONGOS_CAVERN) || + (actor->params == 6979 && gPlayState->sceneNum == SCENE_WATER_TEMPLE) || + (actor->params == 8961 && gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE)) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { break; } ObjSwitch* switchActor = (ObjSwitch*)actor; @@ -342,6 +342,16 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li *should = false; break; } + case ACTOR_EN_BOX: { + if (actor->params == -30457 && gPlayState->sceneNum == SCENE_JABU_JABU && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { + break; + } + EnBox* boxActor = (EnBox*)actor; + *should = false; + RateLimitedSuccessChime(); + break; + } case ACTOR_BG_HIDAN_FWBIG: case ACTOR_EN_EX_ITEM: case ACTOR_EN_DNT_NOMAL: @@ -354,7 +364,6 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li case ACTOR_DOOR_SHUTTER: case ACTOR_BG_ICE_SHUTTER: case ACTOR_OBJ_LIGHTSWITCH: - case ACTOR_EN_BOX: case ACTOR_OBJ_SYOKUDAI: case ACTOR_OBJ_TIMEBLOCK: case ACTOR_EN_PO_SISTERS: @@ -706,14 +715,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li } break; case VB_BE_VALID_GRAVEDIGGING_SPOT: - if (CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), IS_RANDO)) { EnTk* enTk = va_arg(args, EnTk*); enTk->validDigHere = true; *should = true; } break; case VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE: - if (CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), IS_RANDO)) { EnTk* enTk = va_arg(args, EnTk*); enTk->currentReward = 3; *should = true; @@ -1200,6 +1209,10 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE; +void TimeSaverQueueItem(RandomizerGet randoGet) { + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(randoGet).GetGIEntry_Copy(); +} + void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { // Do nothing when in a boss rush if (IS_BOSS_RUSH) { @@ -1458,5 +1471,5 @@ void RegisterSkipTimerDelay() { }); } -static RegisterShipInitFunc skipTimerDelay(RegisterSkipTimerDelay, - { CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" }); +static RegisterShipInitFunc initFunc(RegisterSkipTimerDelay, + { CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" }); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.h b/soh/soh/Enhancements/timesaver_hook_handlers.h index 41bccd8d9..373c9eaf8 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.h +++ b/soh/soh/Enhancements/timesaver_hook_handlers.h @@ -1,6 +1,9 @@ #ifndef TIMESAVER_HOOK_HANDLERS_H #define TIMESAVER_HOOK_HANDLERS_H +#include "soh/Enhancements/randomizer/randomizerTypes.h" + void TimeSaverRegisterHooks(); +void TimeSaverQueueItem(RandomizerGet randoGet); #endif // TIMESAVER_HOOK_HANDLERS_H \ No newline at end of file diff --git a/soh/soh/Enhancements/timesplits/TimeSplits.cpp b/soh/soh/Enhancements/timesplits/TimeSplits.cpp index 4d4eac171..60ae14159 100644 --- a/soh/soh/Enhancements/timesplits/TimeSplits.cpp +++ b/soh/soh/Enhancements/timesplits/TimeSplits.cpp @@ -2,7 +2,7 @@ #include #include -#include "Context.h" +#include #include "TimeSplits.h" #include "soh/Enhancements/gameplaystats.h" #include "soh/SaveManager.h" diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 6337f6d41..dd3a3826a 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -2,8 +2,8 @@ #include "soh/Enhancements/speechsynthesizer/SpeechSynthesizer.h" #include -#include -#include +#include +#include #include #include #include diff --git a/soh/soh/Extractor/Extract.cpp b/soh/soh/Extractor/Extract.cpp index a12be6264..558a3f74d 100644 --- a/soh/soh/Extractor/Extract.cpp +++ b/soh/soh/Extractor/Extract.cpp @@ -6,7 +6,7 @@ #endif #include "Extract.h" #include "portable-file-dialogs.h" -#include +#include #include "variables.h" #ifdef unix @@ -453,6 +453,34 @@ bool Extractor::ManuallySearchForRomMatchingType(RomSearchMode searchMode) { return true; } +bool Extractor::RunFileStandalone(std::string rom) { + if (std::filesystem::is_directory(rom)) { + return false; + } + auto file = std::filesystem::path(rom); + if ((file.extension() != ".n64") && (file.extension() != ".z64") && (file.extension() != ".v64")) { + return false; + } + SetRomInfo(rom); + + if (!ValidateRomSize()) { + return false; + } + std::ifstream inFile; + + inFile.open(rom, std::ios::in | std::ios::binary); + inFile.read((char*)mRomData.get(), mCurRomSize); + inFile.clear(); + inFile.close(); + BitConverter::RomToBigEndian(mRomData.get(), mCurRomSize); + + if (!ValidateRom(true)) { + return false; + } + + return true; +} + bool Extractor::Run(std::string searchPath, RomSearchMode searchMode) { std::vector roms; std::ifstream inFile; diff --git a/soh/soh/Extractor/Extract.h b/soh/soh/Extractor/Extract.h index ae4fa740a..691233aba 100644 --- a/soh/soh/Extractor/Extract.h +++ b/soh/soh/Extractor/Extract.h @@ -59,6 +59,7 @@ class Extractor { static void ShowErrorBox(const char* title, const char* text); bool IsMasterQuest() const; + bool RunFileStandalone(std::string file); bool Run(std::string searchPath, RomSearchMode searchMode = RomSearchMode::Both); bool CallZapd(std::string installPath, std::string exportdir); const char* GetZapdStr(); diff --git a/soh/soh/GbiWrap.cpp b/soh/soh/GbiWrap.cpp index 0a26e9b18..1773c69c5 100644 --- a/soh/soh/GbiWrap.cpp +++ b/soh/soh/GbiWrap.cpp @@ -3,7 +3,7 @@ // OTRTODO - this is awful extern "C" { -void InitOTR(); +void InitOTR(int argc, char* argv[]); void Graph_ProcessFrame(void (*run_one_game_iter)(void)); void Graph_StartFrame(); void Graph_ProcessGfxCommands(Gfx* commands); diff --git a/soh/soh/Notification/Notification.cpp b/soh/soh/Notification/Notification.cpp index ed9907fd2..c6c66bdd8 100644 --- a/soh/soh/Notification/Notification.cpp +++ b/soh/soh/Notification/Notification.cpp @@ -147,8 +147,10 @@ void Emit(Options notification) { notification.remainingTime = CVarGetFloat(CVAR_SETTING("Notifications.Duration"), 10.0f); } notifications.push_back(notification); - Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + if (!notification.mute) { + Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } } } // namespace Notification diff --git a/soh/soh/Notification/Notification.h b/soh/soh/Notification/Notification.h index 7eb4bb2d7..bf1d4ec04 100644 --- a/soh/soh/Notification/Notification.h +++ b/soh/soh/Notification/Notification.h @@ -17,6 +17,7 @@ struct Options { std::string suffix = ""; ImVec4 suffixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f); float remainingTime = 0.0f; // Seconds + bool mute = false; // whether notification should make a noise }; class Window final : public Ship::GuiWindow { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 76e9afeee..f826320c7 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -7,10 +7,10 @@ #include #include "ResourceManagerHelpers.h" -#include "graphic/Fast3D/Fast3dWindow.h" -#include -#include -#include +#include +#include +#include +#include #include #include "Enhancements/gameconsole.h" @@ -19,13 +19,15 @@ #else #include #endif -#include +#include #include "Enhancements/speechsynthesizer/SpeechSynthesizer.h" #include "Enhancements/controls/SohInputEditorWindow.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/audio/AudioCollection.h" #include "Enhancements/enhancementTypes.h" #include "Enhancements/debugconsole.h" +#include "Enhancements/randomizer/entrance.h" +#include "Enhancements/randomizer/location_access.h" #include "Enhancements/randomizer/randomizer.h" #include "Enhancements/randomizer/randomizer_entrance_tracker.h" #include "Enhancements/randomizer/randomizer_item_tracker.h" @@ -38,10 +40,10 @@ #include "variables.h" #include "z64.h" #include "macros.h" -#include "Fonts.h" -#include "window/FileDropMgr.h" -#include "window/gui/resource/Font.h" -#include +#include +#include +#include +#include #include "Enhancements/custom-message/CustomMessageManager.h" #include "Enhancements/Presets/Presets.h" #include "util.h" @@ -51,7 +53,7 @@ #include "Extractor/Extract.h" #endif -#include +#include #ifdef __APPLE__ #include @@ -85,14 +87,16 @@ Sail* Sail::Instance; #include "Enhancements/game-interactor/GameInteractor.h" #include "Enhancements/randomizer/draw.h" #include +#include +#include // Resource Types/Factories -#include "resource/type/Array.h" -#include "resource/type/Blob.h" -#include "resource/type/DisplayList.h" -#include "resource/type/Matrix.h" -#include "resource/type/Texture.h" -#include "resource/type/Vertex.h" +#include "soh/resource/type/Array.h" +#include +#include +#include +#include +#include #include "soh/resource/type/SohResourceType.h" #include "soh/resource/type/Animation.h" #include "soh/resource/type/AudioSample.h" @@ -106,11 +110,11 @@ Sail* Sail::Instance; #include "soh/resource/type/Skeleton.h" #include "soh/resource/type/SkeletonLimb.h" #include "soh/resource/type/Text.h" -#include "resource/factory/BlobFactory.h" -#include "resource/factory/DisplayListFactory.h" -#include "resource/factory/MatrixFactory.h" -#include "resource/factory/TextureFactory.h" -#include "resource/factory/VertexFactory.h" +#include +#include +#include +#include +#include #include "soh/resource/importer/ArrayFactory.h" #include "soh/resource/importer/AnimationFactory.h" #include "soh/resource/importer/AudioSampleFactory.h" @@ -133,7 +137,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" } -void SoH_ProcessDroppedFiles(std::string filePath); +bool SoH_HandleConfigDrop(char* filePath); OTRGlobals* OTRGlobals::Instance; SaveManager* SaveManager::Instance; @@ -281,26 +285,7 @@ void OTRGlobals::Initialize() { if (std::filesystem::exists(sohOtrPath)) { OTRFiles.push_back(sohOtrPath); } - std::string patchesPath = Ship::Context::LocateFileAcrossAppDirs("mods", appShortName); - std::vector patchOTRs = {}; - if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) { - if (std::filesystem::is_directory(patchesPath)) { - for (const auto& p : std::filesystem::recursive_directory_iterator( - patchesPath, std::filesystem::directory_options::follow_directory_symlink)) { - if (StringHelper::IEquals(p.path().extension().string(), ".otr") || - StringHelper::IEquals(p.path().extension().string(), ".mpq") || - StringHelper::IEquals(p.path().extension().string(), ".o2r") || - StringHelper::IEquals(p.path().extension().string(), ".zip")) { - patchOTRs.push_back(p.path().generic_string()); - } - } - } - } - std::sort(patchOTRs.begin(), patchOTRs.end(), [](const std::string& a, const std::string& b) { - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), - [](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); }); - }); - OTRFiles.insert(OTRFiles.end(), patchOTRs.begin(), patchOTRs.end()); + std::unordered_set ValidHashes = { OOT_PAL_MQ, OOT_NTSC_JP_MQ, OOT_NTSC_US_MQ, OOT_PAL_GC_MQ_DBG, OOT_NTSC_US_10, OOT_NTSC_US_11, OOT_NTSC_US_12, OOT_PAL_10, OOT_PAL_11, OOT_NTSC_JP_GC_CE, @@ -345,6 +330,10 @@ void OTRGlobals::Initialize() { std::make_shared(std::vector>({ sohInputEditorWindow })); context->InitWindow(sohFast3dWindow); + context->GetWindow()->SetAutoCaptureMouse(CVarGetInteger(CVAR_SETTING("EnableMouse"), 0) && + CVarGetInteger(CVAR_SETTING("AutoCaptureMouse"), 1)); + context->GetWindow()->SetForceCursorVisibility(CVarGetInteger(CVAR_SETTING("CursorVisibility"), 0)); + auto overlay = context->GetInstance()->GetWindow()->GetGui()->GetGameOverlay(); overlay->LoadFont("Press Start 2P", 12.0f, "fonts/PressStart2P-Regular.ttf"); overlay->LoadFont("Fipps", 32.0f, "fonts/Fipps-Regular.otf"); @@ -985,7 +974,6 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { version.minor = reader->ReadUInt16(); version.patch = reader->ReadUInt16(); } - archive->Close(); } return version; @@ -1134,7 +1122,32 @@ void CheckAndCreateModFolder() { } } -extern "C" void InitOTR() { +extern "C" void InitOTR(int argc, char* argv[]) { +#if !defined(__SWITCH__) && !defined(__WIIU__) + if (argc > 1) { + for (int i = 1; i < argc; i++) { + std::string installPath = Ship::Context::GetAppBundlePath(); + Extractor extract; + if (extract.RunFileStandalone(argv[i])) { + bool doExtract = true; + std::string archive = (extract.IsMasterQuest() ? "oot-mq.o2r" : "oot.o2r"); + if (std::filesystem::exists(Ship::Context::GetAppBundlePath() + "/" + archive)) { + std::string msg = "Archive for current ROM, " + archive + ", already exists. Extract again?"; + doExtract = extract.ShowYesNoBox("Confirm Re-extract", msg.c_str()) == IDYES; + } + if (doExtract) { + extract.CallZapd(installPath, Ship::Context::GetAppDirectoryPath(appShortName)); + } + } else { + std::string msg = "File " + std::string(argv[i]) + " is not a ROM or does not match supported ROMs."; + extract.ShowErrorBox("Incompatible File", msg.c_str()); + } + } + if (Extractor::ShowYesNoBox("Run Ship of Harkinian", "All files have been processed. Run SoH?") != IDYES) { + exit(0); + } + } +#endif OTRGlobals::Instance = new OTRGlobals(); #ifdef __SWITCH__ Ship::Switch::Init(Ship::PreInitPhase); @@ -1252,6 +1265,7 @@ extern "C" void InitOTR() { conf->RegisterVersionUpdater(std::make_shared()); conf->RegisterVersionUpdater(std::make_shared()); conf->RegisterVersionUpdater(std::make_shared()); + conf->RegisterVersionUpdater(std::make_shared()); conf->RunVersionUpdates(); SohGui::SetupGuiElements(); @@ -1289,7 +1303,8 @@ extern "C" void InitOTR() { CVarClear(CVAR_GENERAL("RandomizerNewFileDropped")); CVarClear(CVAR_GENERAL("RandomizerDroppedFile")); // #endregion - GameInteractor::Instance->RegisterGameHook(SoH_ProcessDroppedFiles); + + Ship::Context::GetInstance()->GetFileDropMgr()->RegisterDropHandler(SoH_HandleConfigDrop); RegisterImGuiItemIcons(); @@ -1467,20 +1482,13 @@ extern "C" void Graph_StartFrame() { } #endif case KbScancode::LUS_KB_TAB: { - CVarSetInteger(CVAR_SETTING("AltAssets"), !CVarGetInteger(CVAR_SETTING("AltAssets"), 0)); + if (CVarGetInteger(CVAR_SETTING("Mods.AlternateAssetsHotkey"), 1)) { + CVarSetInteger(CVAR_SETTING("AltAssets"), !CVarGetInteger(CVAR_SETTING("AltAssets"), 0)); + } break; } } #endif - - auto dropMgr = Ship::Context::GetInstance()->GetFileDropMgr(); - if (dropMgr->FileDropped()) { - std::string filePath = dropMgr->GetDroppedFile(); - if (!filePath.empty()) { - GameInteractor::Instance->ExecuteHooks(filePath); - } - dropMgr->ClearDroppedFile(); - } } void RunCommands(Gfx* Commands, const std::vector>& mtx_replacements) { @@ -1680,7 +1688,9 @@ ImFont* OTRGlobals::CreateFontWithSize(float size, std::string fontPath) { initData->Path = fontPath; std::shared_ptr fontData = std::static_pointer_cast( Ship::Context::GetInstance()->GetResourceManager()->LoadResource(fontPath, false, initData)); - font = mImGuiIo->Fonts->AddFontFromMemoryTTF(fontData->Data, fontData->DataSize, size); + ImFontConfig fontConf; + fontConf.FontDataOwnedByAtlas = false; + font = mImGuiIo->Fonts->AddFontFromMemoryTTF(fontData->Data, fontData->DataSize, size, &fontConf); } // FontAwesome fonts need to have their sizes reduced by 2.0f/3.0f in order to align correctly float iconFontSize = size * 2.0f / 3.0f; @@ -2259,6 +2269,149 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); + if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { + s16 entrance = -1; + switch (textId) { + case TEXT_WATERFALL: + entrance = ENTR_ZORAS_DOMAIN_ENTRANCE; + break; + case TEXT_OUTSIDE_FISHING_POND: + entrance = ENTR_FISHING_POND_0; + break; + case TEXT_HF_SIGN: + if (gPlayState->sceneNum == SCENE_KAKARIKO_VILLAGE) { + entrance = ENTR_HYRULE_FIELD_STAIRS_EXIT; + } else if (gPlayState->sceneNum == SCENE_GERUDO_VALLEY) { + entrance = ENTR_HYRULE_FIELD_ROCKY_PATH; + } else if (gPlayState->sceneNum == SCENE_LAKE_HYLIA) { + entrance = ENTR_HYRULE_FIELD_FENCE_EXIT; + } + break; + case TEXT_HC_GREAT_FAIRY_SIGN: + entrance = ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC; + break; + case TEXT_DMT_KAK_SIGN: + if (gPlayState->sceneNum == SCENE_HYRULE_FIELD) { + entrance = ENTR_KAKARIKO_VILLAGE_FRONT_GATE; + } else { + entrance = ENTR_KAKARIKO_VILLAGE_GUARD_GATE; + } + break; + case TEXT_KAK_TO_GY_SIGN: + entrance = ENTR_GRAVEYARD_ENTRANCE; + break; + case TEXT_KAK_WELL_SIGN: + entrance = ENTR_BOTTOM_OF_THE_WELL_ENTRANCE; + break; + case TEXT_KAK_DMT_SIGN: + entrance = ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT; + break; + case TEXT_DMT_SIGN: + entrance = ENTR_GROTTOS_13; + break; + case TEXT_DMT_DC_SIGN: + entrance = ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN; + break; + case TEXT_DMT_GC_SIGN: + entrance = ENTR_GORON_CITY_UPPER_EXIT; + break; + case TEXT_GC_SIGN: + if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL) { + entrance = ENTR_GORON_CITY_UPPER_EXIT; + } else { + entrance = ENTR_GORON_CITY_DARUNIA_ROOM_EXIT; + } + break; + case TEXT_DMT_DMC_SIGN: + entrance = ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT; + break; + case TEXT_DMT_SUMMIT_SIGN: + entrance = ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT; + break; + case TEXT_HF_ZR_SIGN: + entrance = ENTR_ZORAS_RIVER_WEST_EXIT; + break; + case TEXT_KF_SHOP_SIGN: + entrance = ENTR_KOKIRI_SHOP_0; + break; + case TEXT_LINKS_HOUSE_SIGN: + entrance = ENTR_LINKS_HOUSE_1; + break; + case TEXT_KOKIRI_EXIT_SIGN: + entrance = ENTR_LOST_WOODS_BRIDGE_EAST_EXIT; + break; + case TEXT_ZD_SIGN: + if (gPlayState->sceneNum == SCENE_ZORAS_DOMAIN) { + entrance = ENTR_ZORAS_RIVER_WATERFALL_EXIT; + } else { + entrance = ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT; + } + break; + case TEXT_ZF_JABU_SIGN: + entrance = ENTR_JABU_JABU_ENTRANCE; + break; + case TEXT_KF_LW_SIGN: + entrance = ENTR_LOST_WOODS_SOUTH_EXIT; + break; + case TEXT_HF_LON_LON_SIGN: + entrance = ENTR_LON_LON_RANCH_ENTRANCE; + break; + case TEXT_LA_SIGN: + entrance = ENTR_LAKE_HYLIA_NORTH_EXIT; + break; + case TEXT_LA_LAB_SIGN: + entrance = ENTR_LAKESIDE_LABORATORY_0; + break; + case TEXT_GV_SIGN: + if (gPlayState->sceneNum == SCENE_HYRULE_FIELD) { + entrance = ENTR_GERUDO_VALLEY_EAST_EXIT; + } else { + entrance = ENTR_GERUDO_VALLEY_WEST_EXIT; + } + break; + case TEXT_ZD_SHOP_SIGN: + entrance = ENTR_ZORA_SHOP_0; + break; + case TEXT_OUTSIDE_KOKIRI_SIGN: + entrance = ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT; + break; + case TEXT_OUTSIDE_MARKET_SIGN: + entrance = ENTR_LON_LON_RANCH_ENTRANCE; + break; + case TEXT_MIDO_HOUSE_SIGN: + entrance = ENTR_MIDOS_HOUSE_0; + break; + case TEXT_KNOW_IT_ALL_HOUSE_SIGN: + entrance = ENTR_KNOW_IT_ALL_BROS_HOUSE_0; + break; + case TEXT_TWINS_HOUSE_SIGN: + entrance = ENTR_TWINS_HOUSE_0; + break; + case TEXT_SARIAS_HOUSE_SIGN: + entrance = ENTR_SARIAS_HOUSE_0; + break; + case TEXT_NO_DIVING_SIGN: + entrance = ENTR_LAKE_HYLIA_RIVER_EXIT; + break; + } + if (entrance != -1) { + auto entranceCtx = ctx->GetEntranceShuffler(); + for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) { + if (Entrance_EntranceIsNull(&entranceCtx->entranceOverrides[i])) { + break; + } + if (entranceCtx->entranceOverrides[i].index == entrance) { + s16 overrideIndex = entranceCtx->entranceOverrides[i].override; + Entrance_SetEntranceDiscovered(entrance, false); + auto data = GetEntranceData(overrideIndex); + font->charTexBuf[0] = (TEXTBOX_TYPE_WOODEN << 4) | TEXTBOX_POS_BOTTOM; + return msgCtx->msgLength = font->msgLength = SohUtils::CopyStringToCharBuffer( + buffer, data->source + CustomMessage::MESSAGE_END(), maxBufferSize); + } + } + } + } + bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); Player* player = GET_PLAYER(play); @@ -2339,7 +2492,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else { messageEntry = ctx->GetHint(stoneHint)->GetHintMessage(MF_AUTO_FORMAT); } - } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { + } else if (textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT) { // rando hints at altar messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage(MF_AUTO_FORMAT) : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); @@ -2482,6 +2635,10 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if ((textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER) && ctx->GetOption(RSK_SARIA_HINT)) { messageEntry = ctx->GetHint(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } else if ((textId == TEXT_MIDO_SPEAK_TO_MIDO_FIRST_TIME || textId == TEXT_MIDO_SPEAK_TO_MIDO_AGAIN || + textId == TEXT_MIDO_HOME_AFTER_ZELDAS_LETTER || textId == TEXT_MIDO_HOME_BEFORE_ZELDAS_LETTER) && + ctx->GetOption(RSK_MIDO_HINT)) { + messageEntry = ctx->GetHint(RH_MIDO_HINT)->GetHintMessage(MF_AUTO_FORMAT); } else if (ctx->GetOption(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS || textId == TEXT_BIGGORON_I_MAAAADE_THISSSS)) { @@ -2519,7 +2676,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (textId == TEXT_BIG_POE_COLLECTED_RANDO) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); - } else if (textId == TEXT_GERUDO_GUARD_FRIENDLY && player->talkActor->id == ACTOR_EN_GE2) { + } else if (textId == TEXT_GERUDO_GUARD_FRIENDLY && player->talkActor->id == ACTOR_EN_GE2 && + gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS) { // TODO_TRANSLATE Translate into french and german messageEntry = CustomMessage("Want me to throw you in jail?&\x1B#Yes please&No thanks#", { QM_GREEN }); messageEntry.AutoFormat(); @@ -2589,15 +2747,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { return false; } -extern "C" void Overlay_DisplayText(float duration, const char* text) { - Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); -} - -extern "C" void Overlay_DisplayText_Seconds(int seconds, const char* text) { - float duration = seconds * OTRGlobals::Instance->GetInterpolationFPS() * 0.05; - Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); -} - extern "C" void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex) { SetCurrentGrottoIDForTracker(entranceIndex); } @@ -2646,26 +2795,21 @@ extern "C" void Gfx_TextureCacheDelete(const uint8_t* texAddr) { } } -void SoH_ProcessDroppedFiles(std::string filePath) { +bool SoH_HandleConfigDrop(char* filePath) { + if (SohUtils::IsStringEmpty(filePath)) { + return false; + } try { std::ifstream configStream(filePath); if (!configStream) { - return; + return false; } nlohmann::json configJson; configStream >> configJson; - // #region SOH [Randomizer] TODO: Refactor spoiler file handling for randomizer - if (configJson.contains("version") && configJson.contains("finalSeed")) { - CVarSetString(CVAR_GENERAL("RandomizerDroppedFile"), filePath.c_str()); - CVarSetInteger(CVAR_GENERAL("RandomizerNewFileDropped"), 1); - return; - } - // #endregion - if (!configJson.contains("CVars")) { - return; + return false; } CVarClearBlock(CVAR_PREFIX_ENHANCEMENT); @@ -2711,17 +2855,19 @@ void SoH_ProcessDroppedFiles(std::string filePath) { uint32_t finalHash = SohUtils::Hash(configJson.dump()); gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Configuration Loaded. Hash: %d", finalHash); + return true; } catch (std::exception& e) { SPDLOG_ERROR("Failed to load config file: {}", e.what()); auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file"); - return; + return false; } catch (...) { SPDLOG_ERROR("Failed to load config file"); auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file"); - return; + return false; } + return false; } extern "C" void ParseArchipelago() { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 74029ce59..9b9714017 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -21,7 +21,7 @@ #define M_SQRT1_2f 0.70710678118654752440f /* 1/sqrt(2) */ #ifdef __cplusplus -#include +#include #include "Enhancements/savestates.h" #include "Enhancements/randomizer/randomizer.h" #include @@ -87,7 +87,7 @@ class OTRGlobals { #endif #ifndef __cplusplus -void InitOTR(void); +void InitOTR(int argc, char* argv[]); void DeinitOTR(void); void VanillaItemTable_Init(); void OTRAudio_Init(); @@ -157,8 +157,6 @@ uint8_t Randomizer_GenerateRandomizer(); void Randomizer_ShowRandomizerMenu(); void Archipelago_ShowArchipelagoMenu(); int CustomMessage_RetrieveIfExists(PlayState* play); -void Overlay_DisplayText(float duration, const char* text); -void Overlay_DisplayText_Seconds(int seconds, const char* text); GetItemEntry ItemTable_Retrieve(int16_t getItemID); GetItemEntry ItemTable_RetrieveEntry(s16 modIndex, s16 getItemID); void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex); diff --git a/soh/soh/ObjectExtension/ActorMaximumHealth.cpp b/soh/soh/ObjectExtension/ActorMaximumHealth.cpp index 9c710822f..a712b02d5 100644 --- a/soh/soh/ObjectExtension/ActorMaximumHealth.cpp +++ b/soh/soh/ObjectExtension/ActorMaximumHealth.cpp @@ -26,4 +26,4 @@ static void ActorMaximumHealth_Register() { }); } -RegisterShipInitFunc actorMaximumHealthInit(ActorMaximumHealth_Register); \ No newline at end of file +static RegisterShipInitFunc initFunc(ActorMaximumHealth_Register); diff --git a/soh/soh/ResourceManagerHelpers.cpp b/soh/soh/ResourceManagerHelpers.cpp index a9ec6fc25..127378da7 100644 --- a/soh/soh/ResourceManagerHelpers.cpp +++ b/soh/soh/ResourceManagerHelpers.cpp @@ -11,8 +11,9 @@ #include "resource/type/Array.h" #include "resource/type/Skeleton.h" #include "resource/type/PlayerAnimation.h" -#include -#include +#include +#include +#include extern "C" PlayState* gPlayState; diff --git a/soh/soh/ResourceManagerHelpers.h b/soh/soh/ResourceManagerHelpers.h index b760feae3..8562a3e0e 100644 --- a/soh/soh/ResourceManagerHelpers.h +++ b/soh/soh/ResourceManagerHelpers.h @@ -10,7 +10,7 @@ #ifdef __cplusplus #include -#include +#include std::shared_ptr ResourceMgr_GetResourceByNameHandlingMQ(const char* path); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 968ce531c..4257e9cb4 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1060,28 +1060,26 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int se #if defined(__SWITCH__) || defined(__WIIU__) FILE* w = fopen(tempFile.c_str(), "w"); - std::string json_string = saveBlock.dump(4); + std::string json_string = saveBlock.dump(1); fwrite(json_string.c_str(), sizeof(char), json_string.length(), w); fclose(w); #else std::ofstream output(tempFile); - output << std::setw(4) << saveBlock << std::endl; + output << std::setw(1) << saveBlock << std::endl; output.close(); #endif +#if defined(__SWITCH__) || defined(__WIIU__) if (std::filesystem::exists(fileName)) { std::filesystem::remove(fileName); } - -#if defined(__SWITCH__) || defined(__WIIU__) copy_file(tempFile.c_str(), fileName.c_str()); -#else - std::filesystem::copy_file(tempFile, fileName); -#endif - if (std::filesystem::exists(tempFile)) { std::filesystem::remove(tempFile); } +#else + std::filesystem::rename(tempFile, fileName); +#endif delete saveContext; InitMeta(fileNum); @@ -1126,7 +1124,7 @@ void SaveManager::SaveGlobal() { const std::filesystem::path sGlobalPath = sSavePath / std::string("global.sav"); std::ofstream output(sGlobalPath); - output << std::setw(4) << globalBlock << std::endl; + output << std::setw(1) << globalBlock << std::endl; } void SaveManager::LoadFile(int fileNum) { @@ -1178,15 +1176,12 @@ void SaveManager::LoadFile(int fileNum) { std::string newFileName = Ship::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak"); - std::filesystem::path newFile(newFileName); - #if defined(__SWITCH__) || defined(__WIIU__) - copy_file(fileName.c_str(), newFile.c_str()); -#else - std::filesystem::copy_file(fileName, newFile); -#endif - + copy_file(fileName.c_str(), newFileName.c_str()); std::filesystem::remove(fileName); +#else + std::filesystem::rename(fileName, newFileName); +#endif SohGui::RegisterPopup( "Outdated Randomizer Save", "The SoH version in the file in slot " + std::to_string(fileNum + 1) + @@ -1243,16 +1238,15 @@ void SaveManager::LoadFile(int fileNum) { GameInteractor::Instance->ExecuteHooks(fileNum); } catch (const std::exception& e) { input.close(); - std::filesystem::path newFile( + std::string newFileName = Ship::Context::GetPathRelativeToAppDirectory("Save") + - ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak")); + ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak"); #if defined(__SWITCH__) || defined(__WIIU__) - copy_file(fileName.c_str(), newFile.c_str()); -#else - std::filesystem::copy_file(fileName, newFile); -#endif - + copy_file(fileName.c_str(), newFileName.c_str()); std::filesystem::remove(fileName); +#else + std::filesystem::rename(fileName, newFileName); +#endif SohGui::RegisterPopup("Error loading save file", "A problem occurred loading the save in slot " + std::to_string(fileNum + 1) + ".\nSave file corruption is suspected.\n" + diff --git a/soh/soh/SohGui/ImGuiUtils.cpp b/soh/soh/SohGui/ImGuiUtils.cpp index ab3d8f59c..c80293a53 100644 --- a/soh/soh/SohGui/ImGuiUtils.cpp +++ b/soh/soh/SohGui/ImGuiUtils.cpp @@ -1,6 +1,6 @@ #include "ImGuiUtils.h" -#include -#include +#include +#include #include "assets/soh_assets.h" #include "soh/Enhancements/randomizer/rando_hash.h" diff --git a/soh/soh/SohGui/Menu.cpp b/soh/soh/SohGui/Menu.cpp index 5a609a935..592c0c5e6 100644 --- a/soh/soh/SohGui/Menu.cpp +++ b/soh/soh/SohGui/Menu.cpp @@ -2,8 +2,8 @@ #include "UIWidgets.hpp" #include "soh/OTRGlobals.h" #include "soh/Enhancements/controls/SohInputEditorWindow.h" -#include "window/gui/GuiMenuBar.h" -#include "window/gui/GuiElement.h" +#include +#include #include "SohModals.h" #include #include @@ -23,12 +23,19 @@ extern void Warp(); namespace SohGui { extern std::shared_ptr mModalWindow; } +std::vector extraSearchWidgets = {}; namespace Ship { std::string disabledTempTooltip; const char* disabledTooltip; bool disabledValue = false; +bool navigateToWidget = false; +const char* navigateMainEntry = ""; +const char* navigateSidebar = ""; +std::string navigateWidgetName = ""; +bool highlightWidget = false; + bool operator==(Color_RGB8 const& l, Color_RGB8 const& r) noexcept { return l.r == r.r && l.g == r.g && l.b == r.b; } @@ -128,6 +135,7 @@ void Menu::InitElement() { poppedSize.y = CVarGetInteger(CVAR_SETTING("Menu.PoppedHeight"), 800); poppedPos.x = CVarGetInteger(CVAR_SETTING("Menu.PoppedPos.x"), 0); poppedPos.y = CVarGetInteger(CVAR_SETTING("Menu.PoppedPos.y"), 0); + menuThemeIndex = static_cast(CVarGetInteger(CVAR_SETTING("Menu.Theme"), defaultThemeIndex)); UpdateWindowBackendObjects(); } @@ -186,7 +194,12 @@ bool ModernMenuHeaderEntry(std::string label) { uint32_t Menu::DrawSearchResults(std::string& menuSearchText) { int searchCount = 0; - if (ImGui::BeginChild("Search Results")) { + std::transform(menuSearchText.begin(), menuSearchText.end(), menuSearchText.begin(), ::tolower); + menuSearchText.erase(std::remove(menuSearchText.begin(), menuSearchText.end(), ' '), menuSearchText.end()); + ImGui::SetNextWindowSizeConstraints({ ImGui::GetContentRegionAvail().x / 2, 0 }, + { ImGui::GetContentRegionAvail().x / 2, ImGui::GetContentRegionAvail().y }); + if (ImGui::BeginChild("Search Results Col 1", { ImGui::GetContentRegionAvail().x / 2, 0 }, + ImGuiChildFlags_AutoResizeY, ImGuiWindowFlags_NoTitleBar)) { for (auto& menuLabel : menuOrder) { auto& menuEntry = menuEntries.at(menuLabel); for (auto& sidebarLabel : menuEntry.sidebarOrder) { @@ -195,29 +208,63 @@ uint32_t Menu::DrawSearchResults(std::string& menuSearchText) { auto& column = sidebar.columnWidgets.at(i); for (auto& info : column) { if (info.type == WIDGET_SEARCH || info.type == WIDGET_SEPARATOR || - info.type == WIDGET_SEPARATOR_TEXT || info.isHidden) { + info.type == WIDGET_SEPARATOR_TEXT || info.isHidden || info.hideInSearch) { continue; } const char* tooltip = info.options->tooltip; std::string widgetStr = std::string(info.name) + std::string(tooltip != NULL ? tooltip : ""); - std::transform(menuSearchText.begin(), menuSearchText.end(), menuSearchText.begin(), ::tolower); - menuSearchText.erase(std::remove(menuSearchText.begin(), menuSearchText.end(), ' '), - menuSearchText.end()); std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower); widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end()); if (widgetStr.find(menuSearchText) != std::string::npos) { - MenuDrawItem(info, 90 / sidebar.columnCount, menuThemeIndex); + UIWidgets::ComponentAlignments backupAlignment; + UIWidgets::LabelPositions backupLabelPos; + if (info.type == WIDGET_COMBOBOX || info.type == WIDGET_CVAR_COMBOBOX) { + backupAlignment = + std::static_pointer_cast(info.options)->alignment; + backupLabelPos = + std::static_pointer_cast(info.options)->labelPosition; + std::static_pointer_cast(info.options)->alignment = + UIWidgets::ComponentAlignments::Left; + std::static_pointer_cast(info.options)->labelPosition = + UIWidgets::LabelPositions::Above; + } + MenuDrawItem(info, 400, menuThemeIndex); ImGui::PushStyleColor(ImGuiCol_Text, UIWidgets::ColorValues.at(UIWidgets::Colors::Gray)); std::string origin = fmt::format(" ({} -> {}, Col {})", menuEntry.label, sidebarLabel, i + 1); ImGui::Text("%s", origin.c_str()); ImGui::PopStyleColor(); searchCount++; + if (info.type == WIDGET_COMBOBOX || info.type == WIDGET_CVAR_COMBOBOX) { + std::static_pointer_cast(info.options)->alignment = + backupAlignment; + std::static_pointer_cast(info.options)->labelPosition = + backupLabelPos; + } } } } } } + for (auto& entry : extraSearchWidgets) { + if (entry.info.type == WIDGET_SEARCH || entry.info.type == WIDGET_SEPARATOR || + entry.info.type == WIDGET_SEPARATOR_TEXT || entry.info.isHidden || entry.info.hideInSearch) { + continue; + } + std::string widgetStr = + entry.info.name + entry.info.options->tooltip + entry.extraTerms + entry.sidebarName; + std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower); + widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end()); + if (widgetStr.find(menuSearchText) != std::string::npos) { + MenuDrawItem(entry.info, 400, menuThemeIndex); + ImGui::PushStyleColor(ImGuiCol_Text, UIWidgets::ColorValues.at(UIWidgets::Colors::Gray)); + std::string origin = fmt::format(" ({} -> {}, {})", entry.menuName, entry.sidebarName, entry.location); + ImGui::Text("%s", origin.c_str()); + ImGui::PopStyleColor(); + searchCount++; + } + } + ImGui::EndChild(); } return searchCount; } @@ -227,6 +274,10 @@ void Menu::AddMenuEntry(std::string entryName, const char* entryCvar) { menuOrder.push_back(entryName); } +void Menu::AddSearchWidget(SearchWidget widget) { + extraSearchWidgets.push_back(widget); +} + std::unordered_map& Menu::GetDisabledMap() { return disabledMap; } @@ -449,6 +500,20 @@ void Menu::MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors me window->DrawElement(); } } break; + case WIDGET_CVAR_COLOR_PICKER: { + auto options = std::static_pointer_cast(widget.options); + uint32_t modifiers = 0; + if (options->showLock) + modifiers |= UIWidgets::ColorPickerLockCheck; + if (options->showRandom) + modifiers |= UIWidgets::ColorPickerRandomButton; + if (options->showReset) + modifiers |= UIWidgets::ColorPickerResetButton; + if (options->showRainbow) + modifiers |= UIWidgets::ColorPickerRainbowCheck; + UIWidgets::CVarColorPicker(widget.name.c_str(), widget.cVar, options->defaultValue, options->useAlpha, + modifiers, options->color); + } break; case WIDGET_SEARCH: { UIWidgets::PushStyleButton(menuThemeIndex); if (ImGui::Button("Clear")) { @@ -473,7 +538,6 @@ void Menu::MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors me return; } DrawSearchResults(menuSearchText); - ImGui::EndChild(); } break; default: break; @@ -496,10 +560,24 @@ void Menu::Draw() { SyncVisibilityConsoleVariable(); } +static bool freshOpen = true; void Menu::DrawElement() { for (auto& [reason, info] : disabledMap) { info.active = info.evaluation(info); } + const char* headerCvar = CVAR_SETTING("Menu.ActiveHeader"); + + if (navigateToWidget) { + if (menuEntries.contains(navigateMainEntry) && + menuEntries.at(navigateMainEntry).sidebars.contains(navigateSidebar)) { + menuSearch.Clear(); + CVarSetString(headerCvar, navigateMainEntry); + const char* sidebarCvar = menuEntries.at(navigateMainEntry).sidebarCvar; + CVarSetString(sidebarCvar, navigateSidebar); + highlightWidget = true; + } + navigateToWidget = false; + } raceDisableActive = CVarGetInteger(CVAR_SETTING("DisableChanges"), 0); @@ -538,6 +616,7 @@ void Menu::DrawElement() { if (!popout) { ImGui::PopStyleVar(); } + freshOpen = true; ImGui::PopStyleColor(); ImGui::End(); return; @@ -567,7 +646,6 @@ void Menu::DrawElement() { ImGui::PushFont(OTRGlobals::Instance->fontStandardLargest); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10.0f, 8.0f)); - const char* headerCvar = CVAR_SETTING("Menu.ActiveHeader"); std::string headerIndex = CVarGetString(headerCvar, "Settings"); ImVec2 pos = window->DC.CursorPos; float centerX = pos.x + windowWidth / 2 - (style.ItemSpacing.x * (menuEntries.size() + 1)); @@ -654,13 +732,13 @@ void Menu::DrawElement() { std::string menuSearchText = ""; if (headerSearch) { ImGui::SameLine(); - if (autoFocus && ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && !ImGui::IsAnyItemActive() && - !ImGui::IsMouseClicked(0)) { - ImGui::SetKeyboardFocusHere(0); + if (autoFocus && freshOpen) { + ImGui::SetKeyboardFocusHere(); } auto color = UIWidgets::ColorValues.at(menuThemeIndex); - color.w = 0.2f; + color.w = 0.6f; ImGui::PushStyleColor(ImGuiCol_FrameBg, color); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); menuSearch.Draw("##search", 200.0f); menuSearchText = menuSearch.InputBuf; menuSearchText.erase(std::remove(menuSearchText.begin(), menuSearchText.end(), ' '), menuSearchText.end()); @@ -668,6 +746,7 @@ void Menu::DrawElement() { ImGui::SameLine(headerWidth - 200.0f + style.ItemSpacing.x); ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.4f), "Search..."); } + ImGui::PopStyleVar(); ImGui::PopStyleColor(); } ImGui::EndChild(); @@ -797,21 +876,26 @@ void Menu::DrawElement() { ImGuiWindowFlags_NoTitleBar); } if (headerSearch && menuSearchText.length() > 0) { + ImGui::AlignTextToFramePadding(); + ImGui::PushFont(OTRGlobals::Instance->fontMonoLargest); + ImGui::Text("Search Results"); + ImGui::PopFont(); + ImGui::SameLine(); + UIWidgets::ButtonOptions clearBtnOpts = {}; + clearBtnOpts.size = UIWidgets::Sizes::Inline; + if (UIWidgets::Button("Clear Search", clearBtnOpts)) { + menuSearch.Clear(); + } + ImGui::BeginChild("searchSeparator", ImVec2(ImGui::GetContentRegionAvail().x / 2, 20), + ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY); + UIWidgets::Separator(true, true, 0, 10); + ImGui::EndChild(); uint32_t searchCount = DrawSearchResults(menuSearchText); if (searchCount == 0) { ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("No results found").x) / 2); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.4f), "No results found"); } - ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("Clear Search").x) / 2 - 10.0f); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); - UIWidgets::ButtonOptions clearBtnOpts = {}; - clearBtnOpts.size = UIWidgets::Sizes::Inline; - if (UIWidgets::Button("Clear Search", clearBtnOpts)) { - menuSearch.Clear(); - } - - ImGui::EndChild(); } else { std::string menuLabel = menuEntries.at(headerIndex).label; if (MenuInit::GetUpdateFuncs().contains(menuLabel)) { @@ -853,6 +937,9 @@ void Menu::DrawElement() { poppedSize = ImGui::GetWindowSize(); poppedPos = ImGui::GetWindowPos(); } + if (freshOpen) { + freshOpen = false; + } ImGui::End(); } } // namespace Ship diff --git a/soh/soh/SohGui/Menu.h b/soh/soh/SohGui/Menu.h index a7facffd1..a39d48510 100644 --- a/soh/soh/SohGui/Menu.h +++ b/soh/soh/SohGui/Menu.h @@ -2,7 +2,7 @@ #define MENU_H #include -#include "graphic/Fast3D/backends/gfx_rendering_api.h" +#include #include "MenuTypes.h" namespace Ship { @@ -26,6 +26,7 @@ class Menu : public GuiWindow { void MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors menuThemeIndex); void AddMenuEntry(std::string entryName, const char* entryCvar); + void AddSearchWidget(SearchWidget widget); std::unordered_map& GetDisabledMap(); protected: diff --git a/soh/soh/SohGui/MenuTypes.h b/soh/soh/SohGui/MenuTypes.h index e96d015ef..6dd9aca2c 100644 --- a/soh/soh/SohGui/MenuTypes.h +++ b/soh/soh/SohGui/MenuTypes.h @@ -24,10 +24,10 @@ typedef enum { struct WidgetInfo; struct disabledInfo; -using VoidFunc = void (*)(); -using DisableInfoFunc = bool (*)(disabledInfo&); +using VoidFunc = std::function; +using DisableInfoFunc = std::function; using DisableVec = std::vector; -using WidgetFunc = void (*)(WidgetInfo&); +using WidgetFunc = std::function; typedef enum { WIDGET_CHECKBOX, @@ -41,8 +41,8 @@ typedef enum { WIDGET_BUTTON, WIDGET_INPUT, WIDGET_CVAR_INPUT, - WIDGET_COLOR_24, // color picker without alpha - WIDGET_COLOR_32, // color picker with alpha + WIDGET_CVAR_COLOR_PICKER, + WIDGET_COLOR_PICKER, WIDGET_SEARCH, WIDGET_SEPARATOR, WIDGET_SEPARATOR_TEXT, @@ -72,9 +72,10 @@ typedef enum { // holds the widget values for a widget, contains all CVar types available from LUS. int32_t is used for boolean // evaluation using CVarVariant = std::variant; -using OptionsVariant = std::variant; +using OptionsVariant = + std::variant; // All the info needed for display and search of all widgets in the menu. // `name` is the label displayed, @@ -111,11 +112,13 @@ struct WidgetInfo { bool isHidden = false; bool sameLine = false; bool raceDisable = true; + bool hideInSearch = false; WidgetInfo& CVar(const char* cVar_) { cVar = cVar_; return *this; } + WidgetInfo& Options(OptionsVariant options_) { switch (type) { case WIDGET_AUDIO_BACKEND: @@ -138,6 +141,11 @@ struct WidgetInfo { options = std::make_shared(std::get(options_)); break; + case WIDGET_COLOR_PICKER: + case WIDGET_CVAR_COLOR_PICKER: + options = + std::make_shared(std::get(options_)); + break; case WIDGET_BUTTON: options = std::make_shared(std::get(options_)); break; @@ -155,48 +163,63 @@ struct WidgetInfo { } return *this; } + + WidgetInfo& Options(std::shared_ptr options_) { + options = options_; + return *this; + } + + WidgetInfo& Callback(WidgetFunc callback_) { + callback = callback_; + return *this; + } + + WidgetInfo& PreFunc(WidgetFunc preFunc_) { + preFunc = preFunc_; + return *this; + } + + WidgetInfo& PostFunc(WidgetFunc postFunc_) { + postFunc = postFunc_; + return *this; + } + + WidgetInfo& WindowName(const char* windowName_) { + windowName = windowName_; + return *this; + } + + WidgetInfo& ValuePointer(std::variant valuePointer_) { + valuePointer = valuePointer_; + return *this; + } + + WidgetInfo& SameLine(bool sameLine_) { + sameLine = sameLine_; + return *this; + } + + WidgetInfo& CustomFunction(WidgetFunc customFunction_) { + customFunction = customFunction_; + return *this; + } + + WidgetInfo& RaceDisable(bool disable) { + raceDisable = disable; + return *this; + } + + WidgetInfo& HideInSearch(bool hide) { + hideInSearch = hide; + return *this; + } + void ResetDisables() { isHidden = false; options->disabled = false; options->disabledTooltip = ""; activeDisables.clear(); } - WidgetInfo& Options(std::shared_ptr options_) { - options = options_; - return *this; - } - WidgetInfo& Callback(WidgetFunc callback_) { - callback = callback_; - return *this; - } - WidgetInfo& PreFunc(WidgetFunc preFunc_) { - preFunc = preFunc_; - return *this; - } - WidgetInfo& PostFunc(WidgetFunc postFunc_) { - postFunc = postFunc_; - return *this; - } - WidgetInfo& WindowName(const char* windowName_) { - windowName = windowName_; - return *this; - } - WidgetInfo& ValuePointer(std::variant valuePointer_) { - valuePointer = valuePointer_; - return *this; - } - WidgetInfo& SameLine(bool sameLine_) { - sameLine = sameLine_; - return *this; - } - WidgetInfo& CustomFunction(WidgetFunc customFunction_) { - customFunction = customFunction_; - return *this; - } - WidgetInfo& RaceDisable(bool disable) { - raceDisable = disable; - return *this; - } }; struct WidgetPath { @@ -240,6 +263,7 @@ struct MainMenuEntry { static const std::unordered_map audioBackendsMap = { { Ship::AudioBackend::WASAPI, "Windows Audio Session API" }, { Ship::AudioBackend::SDL, "SDL" }, + { Ship::AudioBackend::NUL, "Null" }, }; static const std::unordered_map windowBackendsMap = { @@ -269,6 +293,24 @@ struct MenuInit { } }; +struct SearchEntry { + // First four required + std::string widgetName; + std::string menuName; + std::string sidebarName; + std::string location; + std::string extraTerms = ""; +}; + +struct SearchWidget { + // First four required + WidgetInfo& info; + std::string menuName; + std::string sidebarName; + std::string location; + std::string extraTerms = ""; +}; + struct RegisterMenuInitFunc { RegisterMenuInitFunc(std::function initFunc) { auto& menuInitFuncs = MenuInit::GetInitFuncs(); diff --git a/soh/soh/SohGui/ResolutionEditor.cpp b/soh/soh/SohGui/ResolutionEditor.cpp index 41026e1e2..8e84e5ab7 100644 --- a/soh/soh/SohGui/ResolutionEditor.cpp +++ b/soh/soh/SohGui/ResolutionEditor.cpp @@ -3,8 +3,8 @@ #include #include "soh/SohGui/UIWidgets.hpp" -#include -#include +#include +#include #include "soh/OTRGlobals.h" #include "soh/SohGui/SohMenu.h" #include "soh/SohGui/SohGui.hpp" @@ -582,7 +582,6 @@ void UpdateResolutionVars() { verticalPixelCount = CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalPixelCount", pixelCountPresets[item_pixelCount]); // Additional settings - showHorizontalResField = false; horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX; // Disabling flags disabled_everything = !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", 0); @@ -598,6 +597,6 @@ bool IsDroppingFrames() { } static RegisterMenuUpdateFunc updateFunc(UpdateResolutionVars, "Settings", "Graphics"); -static RegisterMenuInitFunc initFunc(RegisterResolutionWidgets); +static RegisterMenuInitFunc menuInitFunc(RegisterResolutionWidgets); } // namespace SohGui diff --git a/soh/soh/SohGui/SohGui.cpp b/soh/soh/SohGui/SohGui.cpp index 05c69fc90..9f7c80aac 100644 --- a/soh/soh/SohGui/SohGui.cpp +++ b/soh/soh/SohGui/SohGui.cpp @@ -13,7 +13,7 @@ #include #ifdef __APPLE__ -#include "graphic/Fast3D/backends/gfx_metal.h" +#include #endif #ifdef __SWITCH__ @@ -34,6 +34,7 @@ #include "soh/Enhancements/TimeDisplay/TimeDisplay.h" #include "soh/Network/Archipelago/ArchipelagoSettingsWindow.h" #include "soh/Network/Archipelago/ArchipelagoConsoleWindow.h" +#include "soh/Enhancements/mod_menu.h" namespace SohGui { @@ -73,6 +74,7 @@ std::shared_ptr mStatsWindow; std::shared_ptr mGfxDebuggerWindow; std::shared_ptr mSohMenu; +std::shared_ptr mModMenuWindow; std::shared_ptr mAudioEditorWindow; std::shared_ptr mInputViewer; std::shared_ptr mInputViewerSettings; @@ -137,6 +139,8 @@ void SetupGuiElements() { SPDLOG_ERROR("Could not find input editor window"); }*/ + mModMenuWindow = std::make_shared(CVAR_WINDOW("ModMenu"), "Mod Menu", ImVec2(820, 630)); + gui->AddGuiWindow(mModMenuWindow); mAudioEditorWindow = std::make_shared(CVAR_WINDOW("AudioEditor"), "Audio Editor", ImVec2(820, 630)); gui->AddGuiWindow(mAudioEditorWindow); mInputViewer = std::make_shared(CVAR_WINDOW("InputViewer"), "Input Viewer"); @@ -234,6 +238,7 @@ void Destroy() { mColViewerWindow = nullptr; mActorViewerWindow = nullptr; mCosmeticsEditorWindow = nullptr; + mModMenuWindow = nullptr; mAudioEditorWindow = nullptr; mStatsWindow = nullptr; mConsoleWindow = nullptr; diff --git a/soh/soh/SohGui/SohMenu.cpp b/soh/soh/SohGui/SohMenu.cpp index a71fd1cad..78616be7e 100644 --- a/soh/soh/SohGui/SohMenu.cpp +++ b/soh/soh/SohGui/SohMenu.cpp @@ -1,10 +1,10 @@ #include "SohMenu.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/controls/SohInputEditorWindow.h" -#include "window/gui/GuiMenuBar.h" -#include "window/gui/GuiElement.h" +#include +#include #include -#include "StringHelper.h" +#include #include #include @@ -61,8 +61,9 @@ WidgetInfo& SohMenu::AddWidget(WidgetPath& pathInfo, std::string widgetName, Wid case WIDGET_WINDOW_BUTTON: widget.options = std::make_shared(); break; - case WIDGET_COLOR_24: - case WIDGET_COLOR_32: + case WIDGET_CVAR_COLOR_PICKER: + case WIDGET_COLOR_PICKER: + widget.options = std::make_shared(); break; case WIDGET_SEPARATOR_TEXT: case WIDGET_TEXT: @@ -80,14 +81,33 @@ SohMenu::SohMenu(const std::string& consoleVariable, const std::string& name) : Menu(consoleVariable, name, 0, UIWidgets::Colors::LightBlue) { } +#ifndef ENABLE_REMOTE_CONTROL +void SohMenu::AddMenuNetwork() { +#ifndef _DEBUG + // in release builds, the tab doesn't even show + return; +#endif + + // Add Network Menu + AddMenuEntry("Network", CVAR_SETTING("Menu.NetworkSidebarSection")); + + WidgetPath path = { "Network", "Info", SECTION_COLUMN_1 }; + AddSidebarEntry("Network", path.sidebarName, 2); + + AddWidget(path, + ICON_FA_EXCLAMATION_TRIANGLE " The Network features are unavailable because SoH was compiled without " + "network support (\"ENABLE_REMOTE_CONTROL\" build flag).", + WIDGET_TEXT) + .Options(TextOptions().Color(Colors::Orange)); +} +#endif + void SohMenu::InitElement() { Ship::Menu::InitElement(); AddMenuSettings(); AddMenuEnhancements(); AddMenuRandomizer(); -#ifdef ENABLE_REMOTE_CONTROL AddMenuNetwork(); -#endif AddMenuDevTools(); if (CVarGetInteger(CVAR_SETTING("Menu.SidebarSearch"), 0)) { diff --git a/soh/soh/SohGui/SohMenu.h b/soh/soh/SohGui/SohMenu.h index ec5f7705c..d6833f28b 100644 --- a/soh/soh/SohGui/SohMenu.h +++ b/soh/soh/SohGui/SohMenu.h @@ -4,7 +4,7 @@ #include #include "UIWidgets.hpp" #include "Menu.h" -#include "graphic/Fast3D/backends/gfx_rendering_api.h" +#include #include "soh/cvar_prefixes.h" #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/Presets/Presets.h" diff --git a/soh/soh/SohGui/SohMenuBar.cpp b/soh/soh/SohGui/SohMenuBar.cpp index 418d02eb5..debfc9cf5 100644 --- a/soh/soh/SohGui/SohMenuBar.cpp +++ b/soh/soh/SohGui/SohMenuBar.cpp @@ -1,11 +1,11 @@ #include "SohMenuBar.h" #include #include "regex" -#include "public/bridge/consolevariablebridge.h" +#include #include #include "UIWidgets.hpp" #include "include/z64audio.h" -#include "graphic/Fast3D/backends/gfx_rendering_api.h" +#include #include "soh/OTRGlobals.h" #include "soh/SaveManager.h" #include "z64.h" diff --git a/soh/soh/SohGui/SohMenuBar.h b/soh/soh/SohGui/SohMenuBar.h index 8c078e08f..56d0c1c6a 100644 --- a/soh/soh/SohGui/SohMenuBar.h +++ b/soh/soh/SohGui/SohMenuBar.h @@ -1,8 +1,8 @@ #pragma once #include -#include "window/gui/GuiMenuBar.h" -#include "window/gui/GuiElement.h" +#include +#include namespace SohGui { class SohMenuBar : public Ship::GuiMenuBar { diff --git a/soh/soh/SohGui/SohMenuDevTools.cpp b/soh/soh/SohGui/SohMenuDevTools.cpp index 2a0fcd62a..f9e113b55 100644 --- a/soh/soh/SohGui/SohMenuDevTools.cpp +++ b/soh/soh/SohGui/SohMenuDevTools.cpp @@ -124,6 +124,7 @@ void SohMenu::AddMenuDevTools() { .CVar(CVAR_WINDOW("SohStats")) .RaceDisable(false) .WindowName("Stats##Soh") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Stats Window.")); // Console @@ -132,6 +133,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Console", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("SohConsole")) .WindowName("Console##SoH") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Console Window.")); // Save Editor @@ -140,6 +142,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Save Editor", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("SaveEditor")) .WindowName("Save Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Save Editor Window.")); // Hook Debugger @@ -148,6 +151,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Hook Debugger", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("HookDebugger")) .WindowName("Hook Debugger") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Hook Debugger Window.")); // Collision Viewer @@ -156,6 +160,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Collision Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("CollisionViewer")) .WindowName("Collision Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Collision Viewer Window.")); // Actor Viewer @@ -164,6 +169,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Actor Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("ActorViewer")) .WindowName("Actor Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Actor Viewer Window.")); // Display List Viewer @@ -172,6 +178,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Display List Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("DisplayListViewer")) .WindowName("Display List Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Display List Viewer Window.")); // Value Viewer @@ -180,6 +187,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Value Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("ValueViewer")) .WindowName("Value Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Value Viewer Window.")); // Message Viewer @@ -188,6 +196,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Message Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("MessageViewer")) .WindowName("Message Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Message Viewer Window.")); // Gfx Debugger @@ -196,6 +205,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Gfx Debugger", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("SohGfxDebugger")) .WindowName("GfxDebugger##SoH") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Gfx Debugger Window.")); } diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index bdc6f5344..2b660fb94 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -56,7 +56,9 @@ static const std::unordered_map chestStyleMatchesContentsO static const std::unordered_map timeTravelOptions = { { TIME_TRAVEL_DISABLED, "Disabled" }, { TIME_TRAVEL_OOT, "Ocarina of Time" }, + { TIME_TRAVEL_OOT_MS, "Ocarina of Time + Master Sword" }, { TIME_TRAVEL_ANY, "Any Ocarina" }, + { TIME_TRAVEL_ANY_MS, "Any Ocarina + Master Sword" }, }; static const std::unordered_map sleepingWaterfallOptions = { @@ -410,10 +412,11 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().DefaultValue(IS_RANDO)); AddWidget(path, "Exclude Glitch-Aiding Cutscenes", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding")) - .Options(CheckboxOptions().Tooltip( - "Don't skip cutscenes that are associated with useful glitches. Currently, it is " - "only the Fire Temple Darunia CS, Forest Temple Poe Sisters CS, Dodongo Boss " - "Door Switch CS, Water Temple Dragon Switch CS, and the Box Skip One Point in Jabu.")); + .Options( + CheckboxOptions().Tooltip("Don't skip cutscenes that are associated with useful glitches. Currently, it is " + "only the Fire Temple Darunia CS, Forest Temple Poe Sisters CS, Dodongo Boss " + "Door Switch CS, Water Temple Dragon Switch CS, the Box Skip One Point in Jabu, " + "Early Hammer Switch CS in MQ Spirit, and Cow Switch Chest CS in MQ Jabu.")); AddWidget(path, "Text", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Skip Bottle Pickup Messages", WIDGET_CVAR_CHECKBOX) @@ -466,7 +469,7 @@ void SohMenu::AddMenuEnhancements() { .Options(IntSliderOptions().Min(0).Max(5).DefaultValue(0).Format("+%d")); AddWidget(path, "Crawl Speed %dx", WIDGET_CVAR_SLIDER_INT) .CVar(CVAR_ENHANCEMENT("CrawlSpeed")) - .Options(IntSliderOptions().Min(1).Max(4).DefaultValue(1).Format("%dx")); + .Options(IntSliderOptions().Min(1).Max(5).DefaultValue(1).Format("%dx")); AddWidget(path, "Exclude Glitch-Aiding Crawlspaces", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("GlitchAidingCrawlspaces")) .PreFunc([](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 0) == 1; }) @@ -552,12 +555,17 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip( "Disables Grottos rotating with the Camera. To be used in conjuction with mods that want to " "replace grottos with 3D objects.")); + AddWidget(path, "Disable 2D Pre-Rendered Scenes", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("3DSceneRender")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip("Disables 2D pre-rendered backgrounds. Enable this when using a mod that " + "implements 3D backdrops for these areas.\n" + "Requires Scene Change to alter.")); AddWidget(path, "Ingame Text Spacing: %d", WIDGET_CVAR_SLIDER_INT) .CVar(CVAR_ENHANCEMENT("TextSpacing")) .RaceDisable(false) .Options(IntSliderOptions().Min(4).Max(6).DefaultValue(6).Tooltip( "Space between text characters (useful for HD font textures).")); - AddWidget(path, "Models & Textures", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Disable LOD", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("DisableLOD")) @@ -783,9 +791,9 @@ void SohMenu::AddMenuEnhancements() { .Tooltip("Allows Link to freely change age by playing the Song of Time.\n" "Time Blocks can still be used properly.\n\n" "Requirements:\n" - " - Obtained the Ocarina of Time (depends on selection)\n" " - Obtained the Song of Time\n" - " - Obtained the Master Sword\n" + " - Obtained the Ocarina of Time (depends on selection)\n" + " - Obtained the Master Sword (depends on selection)\n" " - Not within range of a Time Block\n" " - Not within range of Ocarina Playing spots")); @@ -940,6 +948,10 @@ void SohMenu::AddMenuEnhancements() { }) .Options(CheckboxOptions().Tooltip( "Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads.")); + AddWidget(path, "Fix Dampé Going Backwards", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("FixDampeGoingBackwards")) + .Options(CheckboxOptions().Tooltip( + "Fixes Dampé going backwards in certain circumstances when the player is going backwards.")); AddWidget(path, "Fix Raised Floor Switches", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("FixFloorSwitches")) .Options(CheckboxOptions().Tooltip( @@ -1159,6 +1171,14 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("NGCKaleidoSwitcher")) .Options(CheckboxOptions().Tooltip( "Makes L and R switch pages like on the GameCube. Z opens the Debug Menu instead.")); + AddWidget(path, "Wide Door Ranges", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("WideShutterDoorRange")) + .Options(CheckboxOptions().Tooltip("Restores the wider range of certain shutter doors from NTSC 1.0.\n" + "Notably affects Jabu-Jabu and boss doors.")); + AddWidget(path, "Grave Hole Jumps", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("GraveHoles")) + .Options(CheckboxOptions().Tooltip( + "Restores NTSC 1.0 behavior where Link jumps over grave holes and grabs the ledges.")); // Difficulty Options path.sidebarName = "Difficulty"; @@ -1266,7 +1286,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("DampeWin")) .Options(CheckboxOptions().Tooltip( "Always win the Heart Piece/Purple Rupee on the first dig in Dampe's Grave Digging game. " - "In a Randomizer file, this is always enabled.")); + "In a Randomizer file, this defaults to on if this enhancement has never been changed.")); AddWidget(path, "All Dogs are Richard", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("AllDogsRichard")) .Options(CheckboxOptions().Tooltip("All dogs can be traded in and will count as Richard.")); @@ -1726,6 +1746,9 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip( "Keese and Guay no longer target you and simply ignore you as if you were wearing the " "Skull Mask.")); + AddWidget(path, "Disable Haunted Wasteland Sandstorm", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_CHEAT("DisableSandstorm")) + .Options(CheckboxOptions().Tooltip("Disables sandstorm effect in Haunted Wasteland.")); AddWidget(path, "Glitch Aids", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Easy Frame Advancing with Pause", WIDGET_CVAR_CHECKBOX) @@ -1829,6 +1852,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("CosmeticsEditor")) .RaceDisable(false) .WindowName("Cosmetics Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Cosmetics Editor Window.")); // Audio Editor @@ -1838,6 +1862,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("AudioEditor")) .RaceDisable(false) .WindowName("Audio Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Audio Editor Window.")); // Gameplay Stats @@ -1847,6 +1872,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("GameplayStats")) .RaceDisable(false) .WindowName("Gameplay Stats") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Gameplay Stats Window.")); // Time Splits @@ -1856,6 +1882,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("TimeSplits")) .RaceDisable(false) .WindowName("Time Splits") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Time Splits Window.")); // Timers @@ -1881,6 +1908,15 @@ void SohMenu::AddMenuEnhancements() { .CVar(timer.timeEnable) .Callback([](WidgetInfo& info) { TimeDisplayUpdateDisplayOptions(); }); } + + // Mod Menu + path.sidebarName = "Mod Menu"; + AddSidebarEntry("Enhancements", path.sidebarName, 1); + AddWidget(path, "Popout Mod Menu Window", WIDGET_WINDOW_BUTTON) + .CVar(CVAR_WINDOW("ModMenu")) + .WindowName("Mod Menu") + .HideInSearch(true) + .Options(WindowButtonOptions().Tooltip("Enables the separate Mod Menu Window.")); } } // namespace SohGui diff --git a/soh/soh/SohGui/SohMenuRandomizer.cpp b/soh/soh/SohGui/SohMenuRandomizer.cpp index 47e651408..ad688740a 100644 --- a/soh/soh/SohGui/SohMenuRandomizer.cpp +++ b/soh/soh/SohGui/SohMenuRandomizer.cpp @@ -22,6 +22,7 @@ void SohMenu::AddMenuRandomizer() { AddWidget(path, "Popout Randomizer Settings Window", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("RandomizerSettings")) .WindowName("Randomizer Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Randomizer Settings Window.")); // Enhancements @@ -104,6 +105,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("PlandomizerEditor")) .RaceDisable(false) .WindowName("Plandomizer Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Randomizer Settings Window.")); // Item Tracker @@ -115,6 +117,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("ItemTracker")) .RaceDisable(false) .WindowName("Item Tracker") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Item Tracker.").EmbedWindow(false)); AddWidget(path, "Item Tracker Settings", WIDGET_SEPARATOR_TEXT); @@ -122,6 +125,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("ItemTrackerSettings")) .RaceDisable(false) .WindowName("Item Tracker Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Item Tracker Settings Window.")); // Entrance Tracker @@ -133,6 +137,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("EntranceTracker")) .RaceDisable(false) .WindowName("Entrance Tracker") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Entrance Tracker.").EmbedWindow(false)); AddWidget(path, "Entrance Tracker Settings", WIDGET_SEPARATOR_TEXT); @@ -140,6 +145,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("EntranceTrackerSettings")) .RaceDisable(false) .WindowName("Entrance Tracker Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Entrance Tracker Settings Window.")); // Check Tracker @@ -151,6 +157,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("CheckTracker")) .RaceDisable(false) .WindowName("Check Tracker") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Check Tracker.").EmbedWindow(false)); AddWidget(path, "Check Tracker Settings", WIDGET_SEPARATOR_TEXT); @@ -158,6 +165,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("CheckTrackerSettings")) .RaceDisable(false) .WindowName("Check Tracker Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Check Tracker Settings Window.")); } diff --git a/soh/soh/SohGui/SohMenuSettings.cpp b/soh/soh/SohGui/SohMenuSettings.cpp index 2472e325b..925ab113d 100644 --- a/soh/soh/SohGui/SohMenuSettings.cpp +++ b/soh/soh/SohGui/SohMenuSettings.cpp @@ -400,8 +400,9 @@ void SohMenu::AddMenuSettings() { .RaceDisable(false) .PreFunc( [](WidgetInfo& info) { info.isHidden = mSohMenu->disabledMap.at(DISABLE_FOR_NO_MULTI_VIEWPORT).active; }) - .Options(CheckboxOptions().Tooltip( - "Allows multiple windows to be opened at once. Requires a reload to take effect.")); + .Options(CheckboxOptions() + .Tooltip("Allows multiple windows to be opened at once. Requires a reload to take effect.") + .DefaultValue(true)); AddWidget(path, "Texture Filter (Needs reload)", WIDGET_CVAR_COMBOBOX) .CVar(CVAR_TEXTURE_FILTER) .RaceDisable(false) @@ -433,6 +434,7 @@ void SohMenu::AddMenuSettings() { .CVar(CVAR_WINDOW("ControllerConfiguration")) .RaceDisable(false) .WindowName("Configure Controller") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Bindings Window.")); // Input Viewer @@ -443,6 +445,7 @@ void SohMenu::AddMenuSettings() { .CVar(CVAR_WINDOW("InputViewer")) .RaceDisable(false) .WindowName("Input Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Input Viewer.").EmbedWindow(false)); AddWidget(path, "Input Viewer Settings", WIDGET_SEPARATOR_TEXT); @@ -450,6 +453,7 @@ void SohMenu::AddMenuSettings() { .CVar(CVAR_WINDOW("InputViewerSettings")) .RaceDisable(false) .WindowName("Input Viewer Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Input Viewer Settings Window.")); // Notifications diff --git a/soh/soh/SohGui/SohModals.h b/soh/soh/SohGui/SohModals.h index f74f0b1bf..68a9b8510 100644 --- a/soh/soh/SohGui/SohModals.h +++ b/soh/soh/SohGui/SohModals.h @@ -1,8 +1,8 @@ #pragma once #include -#include "window/gui/GuiMenuBar.h" -#include "window/gui/GuiElement.h" +#include +#include class SohModalWindow final : public Ship::GuiWindow { public: diff --git a/soh/soh/SohGui/UIWidgets.hpp b/soh/soh/SohGui/UIWidgets.hpp index 0ed88bade..95590b1ce 100644 --- a/soh/soh/SohGui/UIWidgets.hpp +++ b/soh/soh/SohGui/UIWidgets.hpp @@ -162,6 +162,64 @@ struct ButtonOptions : WidgetOptions { } }; +struct ColorPickerOptions : WidgetOptions { + ImVec2 size = Sizes::Fill; + ImVec2 padding = ImVec2(10.0f, 8.0f); + Colors color = Colors::Gray; + Color_RGBA8 defaultValue = { 255, 255, 255, 255 }; + bool useAlpha, showReset, showRandom, showRainbow, showLock; + + ColorPickerOptions& Size(ImVec2 size_) { + size = size_; + return *this; + } + + ColorPickerOptions& Padding(ImVec2 padding_) { + padding = padding_; + return *this; + } + + ColorPickerOptions& Tooltip(const char* tooltip_) { + WidgetOptions::tooltip = tooltip_; + return *this; + } + + ColorPickerOptions& ShowReset(bool showReset_ = true) { + showReset = showReset_; + return *this; + } + + ColorPickerOptions& ShowRandom(bool showRandom_ = true) { + showRandom = showRandom_; + return *this; + } + + ColorPickerOptions& ShowRainbow(bool showRainbow_ = true) { + showRainbow = showRainbow_; + return *this; + } + + ColorPickerOptions& ShowLock(bool showLock_ = true) { + showLock = showLock_; + return *this; + } + + ColorPickerOptions& UseAlpha(bool useAlpha_ = true) { + useAlpha = useAlpha_; + return *this; + } + + ColorPickerOptions& Color(Colors color_) { + color = color_; + return *this; + } + + ColorPickerOptions& DefaultValue(Color_RGBA8 defaultValue_) { + defaultValue = defaultValue_; + return *this; + } +}; + struct WindowButtonOptions : WidgetOptions { ImVec2 size = Sizes::Inline; ImVec2 padding = ImVec2(10.0f, 8.0f); diff --git a/soh/soh/config/ConfigMigrators.h b/soh/soh/config/ConfigMigrators.h index ee7e91792..54a0dc236 100644 --- a/soh/soh/config/ConfigMigrators.h +++ b/soh/soh/config/ConfigMigrators.h @@ -1520,4 +1520,9 @@ std::vector version3Migrations = { { MigrationAction::Remove, "gPreset0" }, { MigrationAction::Remove, "gPreset1" }, }; + +std::vector version4Migrations = { + { MigrationAction::Rename, "gAudioEditor.SeqNameOverlay", "gAudioEditor.SeqNameNotification" }, + { MigrationAction::Rename, "gAudioEditor.SeqNameOverlayDuration", "gAudioEditor.SeqNameNotificationDuration" }, +}; } // namespace SOH diff --git a/soh/soh/config/ConfigUpdaters.cpp b/soh/soh/config/ConfigUpdaters.cpp index ff451d98c..a7c50a845 100644 --- a/soh/soh/config/ConfigUpdaters.cpp +++ b/soh/soh/config/ConfigUpdaters.cpp @@ -9,6 +9,8 @@ ConfigVersion2Updater::ConfigVersion2Updater() : ConfigVersionUpdater(2) { } ConfigVersion3Updater::ConfigVersion3Updater() : ConfigVersionUpdater(3) { } +ConfigVersion4Updater::ConfigVersion4Updater() : ConfigVersionUpdater(4) { +} void ConfigVersion1Updater::Update(Ship::Config* conf) { if (conf->GetInt("Window.Width", 640) == 640) { @@ -111,4 +113,13 @@ void ConfigVersion3Updater::Update(Ship::Config* conf) { CVarClear(migration.from.c_str()); } } + +void ConfigVersion4Updater::Update(Ship::Config* conf) { + for (Migration migration : version4Migrations) { + if (migration.action == MigrationAction::Rename) { + CVarCopy(migration.from.c_str(), migration.to.value().c_str()); + } + CVarClear(migration.from.c_str()); + } +} } // namespace SOH diff --git a/soh/soh/config/ConfigUpdaters.h b/soh/soh/config/ConfigUpdaters.h index 7912be7de..948188c19 100644 --- a/soh/soh/config/ConfigUpdaters.h +++ b/soh/soh/config/ConfigUpdaters.h @@ -18,4 +18,10 @@ class ConfigVersion3Updater final : public Ship::ConfigVersionUpdater { ConfigVersion3Updater(); void Update(Ship::Config* conf); }; + +class ConfigVersion4Updater final : public Ship::ConfigVersionUpdater { + public: + ConfigVersion4Updater(); + void Update(Ship::Config* conf); +}; } // namespace SOH diff --git a/soh/soh/resource/importer/AnimationFactory.cpp b/soh/soh/resource/importer/AnimationFactory.cpp index d6adfb66c..99507e4f3 100644 --- a/soh/soh/resource/importer/AnimationFactory.cpp +++ b/soh/soh/resource/importer/AnimationFactory.cpp @@ -1,8 +1,8 @@ #include "soh/resource/importer/AnimationFactory.h" #include "soh/resource/type/Animation.h" -#include "ResourceManager.h" +#include #include "spdlog/spdlog.h" -#include "Context.h" +#include namespace SOH { std::shared_ptr diff --git a/soh/soh/resource/importer/AnimationFactory.h b/soh/soh/resource/importer/AnimationFactory.h index 2312d7ad3..a28d7512c 100644 --- a/soh/soh/resource/importer/AnimationFactory.h +++ b/soh/soh/resource/importer/AnimationFactory.h @@ -1,7 +1,7 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" +#include +#include namespace SOH { class ResourceFactoryBinaryAnimationV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/ArrayFactory.cpp b/soh/soh/resource/importer/ArrayFactory.cpp index 0762704ff..0e1b2ac04 100644 --- a/soh/soh/resource/importer/ArrayFactory.cpp +++ b/soh/soh/resource/importer/ArrayFactory.cpp @@ -1,7 +1,7 @@ #include "soh/resource/importer/ArrayFactory.h" #include "soh/resource/type/Array.h" #include "spdlog/spdlog.h" -#include "graphic/Fast3D/lus_gbi.h" +#include namespace SOH { std::shared_ptr diff --git a/soh/soh/resource/importer/ArrayFactory.h b/soh/soh/resource/importer/ArrayFactory.h index a64b7a821..aae282754 100644 --- a/soh/soh/resource/importer/ArrayFactory.h +++ b/soh/soh/resource/importer/ArrayFactory.h @@ -1,7 +1,7 @@ #pragma once -#include "resource/Resource.h" -#include "resource/ResourceFactoryBinary.h" +#include +#include namespace SOH { class ResourceFactoryBinaryArrayV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/AudioSampleFactory.cpp b/soh/soh/resource/importer/AudioSampleFactory.cpp index 9fd8d746a..098efd236 100644 --- a/soh/soh/resource/importer/AudioSampleFactory.cpp +++ b/soh/soh/resource/importer/AudioSampleFactory.cpp @@ -4,9 +4,9 @@ #include "spdlog/spdlog.h" #include "z64.h" #include "z64audio.h" -#include "Context.h" -#include "resource/archive/Archive.h" -#include "resource/ResourceManager.h" +#include +#include +#include #define DR_WAV_IMPLEMENTATION #include diff --git a/soh/soh/resource/importer/AudioSampleFactory.h b/soh/soh/resource/importer/AudioSampleFactory.h index b750da4f1..e48d21be2 100644 --- a/soh/soh/resource/importer/AudioSampleFactory.h +++ b/soh/soh/resource/importer/AudioSampleFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinaryAudioSampleV2 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/AudioSequenceFactory.cpp b/soh/soh/resource/importer/AudioSequenceFactory.cpp index 850c27c16..313284f6a 100644 --- a/soh/soh/resource/importer/AudioSequenceFactory.cpp +++ b/soh/soh/resource/importer/AudioSequenceFactory.cpp @@ -2,12 +2,12 @@ #include "soh/resource/importer/AudioSoundFontFactory.h" #include "soh/resource/type/AudioSequence.h" #include "spdlog/spdlog.h" -#include "resource/ResourceManager.h" +#include #include -#include "Context.h" -#include "resource/archive/Archive.h" -#include "BinaryWriter.h" +#include +#include +#include #include namespace SOH { diff --git a/soh/soh/resource/importer/AudioSequenceFactory.h b/soh/soh/resource/importer/AudioSequenceFactory.h index 4ae249ec3..897b49c50 100644 --- a/soh/soh/resource/importer/AudioSequenceFactory.h +++ b/soh/soh/resource/importer/AudioSequenceFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinaryAudioSequenceV2 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/AudioSoundFontFactory.cpp b/soh/soh/resource/importer/AudioSoundFontFactory.cpp index 1150b2b69..f71f31d14 100644 --- a/soh/soh/resource/importer/AudioSoundFontFactory.cpp +++ b/soh/soh/resource/importer/AudioSoundFontFactory.cpp @@ -3,9 +3,9 @@ #include #include #include "z64audio.h" -#include "Context.h" -#include "resource/archive/Archive.h" -#include "resource/ResourceManager.h" +#include +#include +#include namespace SOH { std::shared_ptr diff --git a/soh/soh/resource/importer/AudioSoundFontFactory.h b/soh/soh/resource/importer/AudioSoundFontFactory.h index 0a56769cd..30d3e620f 100644 --- a/soh/soh/resource/importer/AudioSoundFontFactory.h +++ b/soh/soh/resource/importer/AudioSoundFontFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include #include "soh/resource/type/AudioSoundFont.h" namespace SOH { diff --git a/soh/soh/resource/importer/BackgroundFactory.h b/soh/soh/resource/importer/BackgroundFactory.h index e9a47a952..645174c69 100644 --- a/soh/soh/resource/importer/BackgroundFactory.h +++ b/soh/soh/resource/importer/BackgroundFactory.h @@ -1,7 +1,7 @@ #pragma once -#include "resource/Resource.h" -#include "resource/ResourceFactoryBinary.h" +#include +#include namespace SOH { class ResourceFactoryBinaryBackgroundV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/CollisionHeaderFactory.h b/soh/soh/resource/importer/CollisionHeaderFactory.h index 4db21d351..45076f1a6 100644 --- a/soh/soh/resource/importer/CollisionHeaderFactory.h +++ b/soh/soh/resource/importer/CollisionHeaderFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinaryCollisionHeaderV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/CutsceneFactory.h b/soh/soh/resource/importer/CutsceneFactory.h index 95a6f379e..be44c4686 100644 --- a/soh/soh/resource/importer/CutsceneFactory.h +++ b/soh/soh/resource/importer/CutsceneFactory.h @@ -1,7 +1,7 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" +#include +#include namespace SOH { class ResourceFactoryBinaryCutsceneV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/PathFactory.h b/soh/soh/resource/importer/PathFactory.h index f94a201c5..9c83f5183 100644 --- a/soh/soh/resource/importer/PathFactory.h +++ b/soh/soh/resource/importer/PathFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinaryPathV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/PlayerAnimationFactory.h b/soh/soh/resource/importer/PlayerAnimationFactory.h index 7761c63b6..09cbb3358 100644 --- a/soh/soh/resource/importer/PlayerAnimationFactory.h +++ b/soh/soh/resource/importer/PlayerAnimationFactory.h @@ -1,7 +1,7 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" +#include +#include namespace SOH { class ResourceFactoryBinaryPlayerAnimationV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/SceneFactory.h b/soh/soh/resource/importer/SceneFactory.h index a22291d51..11de07520 100644 --- a/soh/soh/resource/importer/SceneFactory.h +++ b/soh/soh/resource/importer/SceneFactory.h @@ -3,9 +3,9 @@ #include "soh/resource/type/Scene.h" #include "soh/resource/type/scenecommand/SceneCommand.h" #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinarySceneV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/SkeletonFactory.h b/soh/soh/resource/importer/SkeletonFactory.h index b7c90443f..209e2380d 100644 --- a/soh/soh/resource/importer/SkeletonFactory.h +++ b/soh/soh/resource/importer/SkeletonFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinarySkeletonV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/SkeletonLimbFactory.h b/soh/soh/resource/importer/SkeletonLimbFactory.h index bcf1fd4d5..3f1b76b1c 100644 --- a/soh/soh/resource/importer/SkeletonLimbFactory.h +++ b/soh/soh/resource/importer/SkeletonLimbFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinarySkeletonLimbV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/TextFactory.h b/soh/soh/resource/importer/TextFactory.h index b67f07cbb..502549600 100644 --- a/soh/soh/resource/importer/TextFactory.h +++ b/soh/soh/resource/importer/TextFactory.h @@ -1,8 +1,8 @@ #pragma once -#include "Resource.h" -#include "ResourceFactoryBinary.h" -#include "ResourceFactoryXML.h" +#include +#include +#include namespace SOH { class ResourceFactoryBinaryTextV0 final : public Ship::ResourceFactoryBinary { diff --git a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h index b1cd67ae6..6a038fa83 100644 --- a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h +++ b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h @@ -1,10 +1,10 @@ #pragma once #include -#include "Resource.h" -#include "ResourceFactory.h" +#include +#include #include "soh/resource/type/scenecommand/SceneCommand.h" -#include "public/bridge/consolevariablebridge.h" +#include namespace SOH { class SceneCommandFactoryBinaryV0 { diff --git a/soh/soh/resource/logging/PathLogger.h b/soh/soh/resource/logging/PathLogger.h index f239d5747..23f4f0d30 100644 --- a/soh/soh/resource/logging/PathLogger.h +++ b/soh/soh/resource/logging/PathLogger.h @@ -1,4 +1,4 @@ -#include "Resource.h" +#include #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" diff --git a/soh/soh/resource/logging/SceneCommandLoggers.h b/soh/soh/resource/logging/SceneCommandLoggers.h index b006b9c0a..64dc1d995 100644 --- a/soh/soh/resource/logging/SceneCommandLoggers.h +++ b/soh/soh/resource/logging/SceneCommandLoggers.h @@ -1,4 +1,4 @@ -#include "Resource.h" +#include #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" diff --git a/soh/soh/resource/type/Animation.h b/soh/soh/resource/type/Animation.h index e4ca4295f..9603e5477 100644 --- a/soh/soh/resource/type/Animation.h +++ b/soh/soh/resource/type/Animation.h @@ -1,6 +1,6 @@ #pragma once -#include "Resource.h" +#include #include namespace SOH { diff --git a/soh/soh/resource/type/Array.cpp b/soh/soh/resource/type/Array.cpp index a4bbc0e5e..8a02faad7 100644 --- a/soh/soh/resource/type/Array.cpp +++ b/soh/soh/resource/type/Array.cpp @@ -1,5 +1,5 @@ #include "Array.h" -#include "graphic/Fast3D/lus_gbi.h" +#include namespace SOH { Array::Array() : Resource(std::shared_ptr()) { } diff --git a/soh/soh/resource/type/Array.h b/soh/soh/resource/type/Array.h index c7d15a22a..23d0b7e53 100644 --- a/soh/soh/resource/type/Array.h +++ b/soh/soh/resource/type/Array.h @@ -1,6 +1,6 @@ #pragma once -#include "resource/Resource.h" +#include namespace Fast { union F3DVtx; diff --git a/soh/soh/resource/type/AudioSample.h b/soh/soh/resource/type/AudioSample.h index 84e623781..eb29bc5bc 100644 --- a/soh/soh/resource/type/AudioSample.h +++ b/soh/soh/resource/type/AudioSample.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Resource.h" +#include #include namespace SOH { diff --git a/soh/soh/resource/type/AudioSequence.h b/soh/soh/resource/type/AudioSequence.h index b76645dee..90d5dd15e 100644 --- a/soh/soh/resource/type/AudioSequence.h +++ b/soh/soh/resource/type/AudioSequence.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Resource.h" +#include namespace SOH { diff --git a/soh/soh/resource/type/AudioSoundFont.h b/soh/soh/resource/type/AudioSoundFont.h index e387ede5f..0e07c0308 100644 --- a/soh/soh/resource/type/AudioSoundFont.h +++ b/soh/soh/resource/type/AudioSoundFont.h @@ -2,7 +2,7 @@ #include #include -#include "Resource.h" +#include #include "soh/resource/type/AudioSample.h" #include diff --git a/soh/soh/resource/type/Background.h b/soh/soh/resource/type/Background.h index 728e0207e..bd14e1509 100644 --- a/soh/soh/resource/type/Background.h +++ b/soh/soh/resource/type/Background.h @@ -1,6 +1,6 @@ #pragma once -#include "resource/Resource.h" +#include namespace SOH { class Background : public Ship::Resource { diff --git a/soh/soh/resource/type/CollisionHeader.h b/soh/soh/resource/type/CollisionHeader.h index 151437442..d6cd3c6fd 100644 --- a/soh/soh/resource/type/CollisionHeader.h +++ b/soh/soh/resource/type/CollisionHeader.h @@ -2,7 +2,7 @@ #include #include -#include "Resource.h" +#include #include #include "z64math.h" diff --git a/soh/soh/resource/type/Cutscene.h b/soh/soh/resource/type/Cutscene.h index e1f786ea5..59475d1cf 100644 --- a/soh/soh/resource/type/Cutscene.h +++ b/soh/soh/resource/type/Cutscene.h @@ -2,7 +2,7 @@ #include #include -#include "Resource.h" +#include namespace SOH { diff --git a/soh/soh/resource/type/Path.h b/soh/soh/resource/type/Path.h index baef6519c..42fc2946f 100644 --- a/soh/soh/resource/type/Path.h +++ b/soh/soh/resource/type/Path.h @@ -2,7 +2,7 @@ #include #include -#include "Resource.h" +#include #include #include "z64math.h" diff --git a/soh/soh/resource/type/PlayerAnimation.h b/soh/soh/resource/type/PlayerAnimation.h index db8e8ccf9..66cac19e0 100644 --- a/soh/soh/resource/type/PlayerAnimation.h +++ b/soh/soh/resource/type/PlayerAnimation.h @@ -2,7 +2,7 @@ #include #include -#include "Resource.h" +#include namespace SOH { class PlayerAnimation : public Ship::Resource { diff --git a/soh/soh/resource/type/Scene.h b/soh/soh/resource/type/Scene.h index 73fcd57a9..371890e76 100644 --- a/soh/soh/resource/type/Scene.h +++ b/soh/soh/resource/type/Scene.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "scenecommand/SceneCommand.h" #include diff --git a/soh/soh/resource/type/Skeleton.cpp b/soh/soh/resource/type/Skeleton.cpp index 027da1790..f2541dd06 100644 --- a/soh/soh/resource/type/Skeleton.cpp +++ b/soh/soh/resource/type/Skeleton.cpp @@ -1,4 +1,4 @@ -#include "resource/ResourceManager.h" +#include #include "Skeleton.h" #include "soh/OTRGlobals.h" #include "libultraship/libultraship.h" diff --git a/soh/soh/resource/type/Skeleton.h b/soh/soh/resource/type/Skeleton.h index 4d5dc0119..c3fd6f181 100644 --- a/soh/soh/resource/type/Skeleton.h +++ b/soh/soh/resource/type/Skeleton.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Resource.h" +#include #include "SkeletonLimb.h" #include diff --git a/soh/soh/resource/type/SkeletonLimb.h b/soh/soh/resource/type/SkeletonLimb.h index 5ee73b99a..84acd7741 100644 --- a/soh/soh/resource/type/SkeletonLimb.h +++ b/soh/soh/resource/type/SkeletonLimb.h @@ -1,6 +1,6 @@ #pragma once -#include "Resource.h" +#include #include "libultraship/libultra.h" #include "z64math.h" diff --git a/soh/soh/resource/type/Text.h b/soh/soh/resource/type/Text.h index 535203716..ff921e731 100644 --- a/soh/soh/resource/type/Text.h +++ b/soh/soh/resource/type/Text.h @@ -2,7 +2,7 @@ #include #include -#include "Resource.h" +#include #include namespace SOH { diff --git a/soh/soh/resource/type/scenecommand/EndMarker.h b/soh/soh/resource/type/scenecommand/EndMarker.h index 37b06911d..5d3a0f7df 100644 --- a/soh/soh/resource/type/scenecommand/EndMarker.h +++ b/soh/soh/resource/type/scenecommand/EndMarker.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SceneCommand.h b/soh/soh/resource/type/scenecommand/SceneCommand.h index 99234b24a..1e71599dc 100644 --- a/soh/soh/resource/type/scenecommand/SceneCommand.h +++ b/soh/soh/resource/type/scenecommand/SceneCommand.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include namespace SOH { diff --git a/soh/soh/resource/type/scenecommand/SetActorList.h b/soh/soh/resource/type/scenecommand/SetActorList.h index d4ee3a902..b444aadd0 100644 --- a/soh/soh/resource/type/scenecommand/SetActorList.h +++ b/soh/soh/resource/type/scenecommand/SetActorList.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" // #include #include "z64math.h" diff --git a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h index 11dabd31f..38817d1a6 100644 --- a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h +++ b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include "soh/resource/type/Scene.h" #include "RomFile.h" diff --git a/soh/soh/resource/type/scenecommand/SetCameraSettings.h b/soh/soh/resource/type/scenecommand/SetCameraSettings.h index ad674d306..0cc03cfd5 100644 --- a/soh/soh/resource/type/scenecommand/SetCameraSettings.h +++ b/soh/soh/resource/type/scenecommand/SetCameraSettings.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetCollisionHeader.h b/soh/soh/resource/type/scenecommand/SetCollisionHeader.h index b24673242..283a8bc0a 100644 --- a/soh/soh/resource/type/scenecommand/SetCollisionHeader.h +++ b/soh/soh/resource/type/scenecommand/SetCollisionHeader.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "soh/resource/type/scenecommand/SceneCommand.h" #include "soh/resource/type/CollisionHeader.h" // #include diff --git a/soh/soh/resource/type/scenecommand/SetCsCamera.h b/soh/soh/resource/type/scenecommand/SetCsCamera.h index fbd51e06c..42db07754 100644 --- a/soh/soh/resource/type/scenecommand/SetCsCamera.h +++ b/soh/soh/resource/type/scenecommand/SetCsCamera.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetCutscenes.h b/soh/soh/resource/type/scenecommand/SetCutscenes.h index 5ad28d4ae..0988b2027 100644 --- a/soh/soh/resource/type/scenecommand/SetCutscenes.h +++ b/soh/soh/resource/type/scenecommand/SetCutscenes.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "soh/resource/type/scenecommand/SceneCommand.h" #include "soh/resource/type/Cutscene.h" // #include diff --git a/soh/soh/resource/type/scenecommand/SetEchoSettings.h b/soh/soh/resource/type/scenecommand/SetEchoSettings.h index 2d17a879e..dfa0538a4 100644 --- a/soh/soh/resource/type/scenecommand/SetEchoSettings.h +++ b/soh/soh/resource/type/scenecommand/SetEchoSettings.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetEntranceList.h b/soh/soh/resource/type/scenecommand/SetEntranceList.h index e41050c87..08fcf9fca 100644 --- a/soh/soh/resource/type/scenecommand/SetEntranceList.h +++ b/soh/soh/resource/type/scenecommand/SetEntranceList.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetExitList.h b/soh/soh/resource/type/scenecommand/SetExitList.h index 56026075f..d9598c3cd 100644 --- a/soh/soh/resource/type/scenecommand/SetExitList.h +++ b/soh/soh/resource/type/scenecommand/SetExitList.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetLightList.h b/soh/soh/resource/type/scenecommand/SetLightList.h index d79a73aec..3a95a4f8f 100644 --- a/soh/soh/resource/type/scenecommand/SetLightList.h +++ b/soh/soh/resource/type/scenecommand/SetLightList.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetLightingSettings.h b/soh/soh/resource/type/scenecommand/SetLightingSettings.h index cb2089517..ca9282225 100644 --- a/soh/soh/resource/type/scenecommand/SetLightingSettings.h +++ b/soh/soh/resource/type/scenecommand/SetLightingSettings.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetMesh.h b/soh/soh/resource/type/scenecommand/SetMesh.h index d96661c43..1ab86530a 100644 --- a/soh/soh/resource/type/scenecommand/SetMesh.h +++ b/soh/soh/resource/type/scenecommand/SetMesh.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include "libultraship/libultra.h" #include "z64math.h" diff --git a/soh/soh/resource/type/scenecommand/SetObjectList.h b/soh/soh/resource/type/scenecommand/SetObjectList.h index 74081763a..5650f6d94 100644 --- a/soh/soh/resource/type/scenecommand/SetObjectList.h +++ b/soh/soh/resource/type/scenecommand/SetObjectList.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetPathways.h b/soh/soh/resource/type/scenecommand/SetPathways.h index 377b5923d..ec2011367 100644 --- a/soh/soh/resource/type/scenecommand/SetPathways.h +++ b/soh/soh/resource/type/scenecommand/SetPathways.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" // #include #include "soh/resource/type/Path.h" diff --git a/soh/soh/resource/type/scenecommand/SetRoomBehavior.h b/soh/soh/resource/type/scenecommand/SetRoomBehavior.h index db59fa76b..8a1c2b832 100644 --- a/soh/soh/resource/type/scenecommand/SetRoomBehavior.h +++ b/soh/soh/resource/type/scenecommand/SetRoomBehavior.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetRoomList.h b/soh/soh/resource/type/scenecommand/SetRoomList.h index b60a75dbe..6fe6d33ff 100644 --- a/soh/soh/resource/type/scenecommand/SetRoomList.h +++ b/soh/soh/resource/type/scenecommand/SetRoomList.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include "RomFile.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h b/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h index 7ed86ddc5..189e4ab3d 100644 --- a/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h +++ b/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h b/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h index d3d7b5a4c..cf3bbfbad 100644 --- a/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h +++ b/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetSoundSettings.h b/soh/soh/resource/type/scenecommand/SetSoundSettings.h index 57e3beaae..ba180d823 100644 --- a/soh/soh/resource/type/scenecommand/SetSoundSettings.h +++ b/soh/soh/resource/type/scenecommand/SetSoundSettings.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetSpecialObjects.h b/soh/soh/resource/type/scenecommand/SetSpecialObjects.h index 51a57c599..1e9e44e9f 100644 --- a/soh/soh/resource/type/scenecommand/SetSpecialObjects.h +++ b/soh/soh/resource/type/scenecommand/SetSpecialObjects.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetStartPositionList.h b/soh/soh/resource/type/scenecommand/SetStartPositionList.h index f2b097b0c..2b1ddce89 100644 --- a/soh/soh/resource/type/scenecommand/SetStartPositionList.h +++ b/soh/soh/resource/type/scenecommand/SetStartPositionList.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include "soh/resource/type/scenecommand/SetActorList.h" // #include diff --git a/soh/soh/resource/type/scenecommand/SetTimeSettings.h b/soh/soh/resource/type/scenecommand/SetTimeSettings.h index ca95841e7..c5b63283b 100644 --- a/soh/soh/resource/type/scenecommand/SetTimeSettings.h +++ b/soh/soh/resource/type/scenecommand/SetTimeSettings.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/resource/type/scenecommand/SetTransitionActorList.h b/soh/soh/resource/type/scenecommand/SetTransitionActorList.h index e740f128a..0b7149fa6 100644 --- a/soh/soh/resource/type/scenecommand/SetTransitionActorList.h +++ b/soh/soh/resource/type/scenecommand/SetTransitionActorList.h @@ -4,7 +4,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" // #include #include "z64math.h" diff --git a/soh/soh/resource/type/scenecommand/SetWindSettings.h b/soh/soh/resource/type/scenecommand/SetWindSettings.h index 755ad0d0d..87e0a3039 100644 --- a/soh/soh/resource/type/scenecommand/SetWindSettings.h +++ b/soh/soh/resource/type/scenecommand/SetWindSettings.h @@ -3,7 +3,7 @@ #include #include #include -#include "Resource.h" +#include #include "SceneCommand.h" #include diff --git a/soh/soh/util.cpp b/soh/soh/util.cpp index f1405abbb..c05f03f0c 100644 --- a/soh/soh/util.cpp +++ b/soh/soh/util.cpp @@ -7,6 +7,7 @@ #include #include #include "Enhancements/randomizer/randomizerTypes.h" +#include std::vector sceneNames = { "Inside the Deku Tree", @@ -121,7 +122,7 @@ std::vector sceneNames = { "Treasure Chest Room", }; -std::vector itemNames = { +std::vector itemNamesEng = { "Deku Stick", "Deku Nut", "Bomb", @@ -280,7 +281,325 @@ std::vector itemNames = { "Deku Nut Upgrade (40)", }; -std::vector questItemNames = { +std::vector itemNamesFra = { + "Bâton Mojo", + "Noix Mojo", + "Bombe", + "Arc des Fées", + "Flèche de Feu", + "Feu de Din", + "Lance-Pierre des Fées", + "Ocarina des Fées", + "Ocarina du Temps", + "Missile Teigneux", + "Grappin", + "Super Grappin", + "Flèche de Glace", + "Vent de Farore", + "Boomerang", + "Monocle de Vérité", + "Haricot Magique", + "Masse des Titans", + "Flèche de Lumière", + "Amour de Nayru", + "Bouteille Vide", + "Potion Rouge", + "Potion Verte", + "Potion Bleue", + "Fée en Bouteille", + "Poisson", + "Lait Lon Lon et Bouteille", + "Lettre de Ruto", + "Flamme Bleue", + "Insectes", + "Grand Spectre", + "Lait Lon Lon (Demi)", + "Spectre", + "Oeuf Suspect", + "Poule", + "Lettre de Zelda", + "Masque Renard", + "Masque de Mort", + "Masque du Fantôme", + "Capuche de Lapin", + "Masque Goron", + "Masque Zora", + "Masque Gerudo", + "Masque de Vérité", + "ÉPUISÉ", + "Oeuf de Poche", + "Cocotte de Poche", + "Cojiro", + "Champignon Suspect", + "Potion Suspecte", + "Scie du Chasseur", + "Épée Goron (Cassée)", + "Ordonnance", + "Crapaud-qui-louche", + "Super Gouttes", + "Certificat", + "Arc des Fées & Flèche de Feu", + "Arc des Fées & Flèche de Glace", + "Arc des Fées & Flèche de Lumière", + "Épée Kokiri", + "Épée de Légende", + "Lame des Géants & Épée Biggoron", + "Bouclier Mojo", + "Bouclier Hylien", + "Bouclier Miroir", + "Tunique Kokiri", + "Tunique Goron", + "Tunique Zora", + "Bottes Kokiri", + "Bottes de Plomb", + "Bottes des Airs", + "Sac de Graines (30)", + "Sac de Graines (40)", + "Sac de Graines (50)", + "Carquois (30)", + "Grand Carquois (40)", + "Énorme Grand Carquois (50)", + "Sac de Bombes (20)", + "Gros Sac de Bombes (30)", + "Énorme Sac de Bombes (40)", + "Bracelet Goron", + "Gantelets d'Argent", + "Gantelets d'Or", + "Écaille d'Argent", + "Écaille d'Or", + "Lame des Géants (Cassée)", + "Grande Bourse", + "Bourse de Géant", + "Graines Mojo (5)", + "Canne à Pêche", + "Menuet des Bois", + "Boléro du Feu", + "Sérénade de l'Eau", + "Requiem de l'Esprit", + "Nocturne de l'Ombre", + "Prélude de la Lumière", + "Berceuse de Zelda", + "Chant d'Epona", + "Chant de Saria", + "Chant du Soleil", + "Chant du Temps", + "Chant des Tempêtes", + "Médaillon de la Forêt", + "Médaillon du Feu", + "Médaillon de l'Eau", + "Médaillon de l'Esprit", + "Médaillon de l'Ombre", + "Médaillon de la Lumière", + "Émeraude Kokiri", + "Rubis Goron", + "Saphir Zora", + "Pierre de Souffrance", + "Carte Gerudo", + "Symbole de Skulltula d'Or", + "Réceptacle de Coeur", + "Quart de Coeur", + "Clé du Boss", + "Boussole", + "Carte du Donjon", + "Petite Clé", + "Petite Magie", + "Grande Magie", + "Quart de Coeur", + "[Retiré]", + "[Retiré]", + "[Retiré]", + "[Retiré]", + "[Retiré]", + "[Retiré]", + "[Retiré]", + "Lait Lon Lon", + "Coeur", + "Rubis Vert", + "Rubis Bleu", + "Rubis Rouge", + "Rubis Pourpre", + "Énorme Rubis", + "[Retiré]", + "Bâtons Mojo (5)", + "Bâtons Mojo (10)", + "Noix Mojo (5)", + "Noix Mojo (10)", + "Bombes (5)", + "Bombes (10)", + "Bombes (20)", + "Bombes (30)", + "Flèches (Petites)", + "Flèches (Moyennes)", + "Flèches (Grandes)", + "Graines Mojo (30)", + "Missile Teigneux (5)", + "Missile Teigneux (20)", + "Amélioration des Bâtons Mojo (20)", + "Amélioration des Bâtons Mojo (30)", + "Amélioration des Noix Mojo (30)", + "Amélioration des Noix Mojo (40)", +}; + +std::vector itemNamesGer = { + "Deku-Stab", + "Deku-Nuß", + "Bombe", + "Feen-Bogen", + "Feuer-Pfeil", + "Dins Feuerinferno", + "Feen-Schleuder", + "Feen-Okarina", + "Okarina der Zeit", + "Krabbelmine", + "Fanghaken", + "Enterhaken", + "Eis-Pfeil", + "Farores Donnersturm", + "Bumerang", + "Auge der Wahrheit", + "Wundererbse", + "Stahlhammer", + "Licht-Pfeil", + "Nayrus Umarmung", + "Leere Flasche", + "Rotes Elixier", + "Grünes Elixier", + "Blaues Elixier", + "Flasche (Fee)", + "Fisch", + "Flasche (Milch)", + "Rutos Brief", + "Blaues Feuer", + "Käfer", + "Nachtschwärmer", + "Lon Lon-Milch (Halbe Füllung)", + "Irrlicht", + "Seltsames Ei", + "Huhn", + "Zeldas Brief", + "Fuchs-Maske", + "Geister-Maske", + "Schädel-Maske", + "Hasenohren", + "Goronen-Maske", + "Zora-Maske", + "Gerudo-Maske", + "Maske des Wissens", + "AUSVERKAUFT", + "Ei", + "Kiki", + "Henni", + "Schimmelpilz", + "Modertrank", + "Säge", + "Zerbr. Goronen-Schwert", + "Rezept", + "Glotzfrosch", + "Augentropfen", + "Zertifikat", + "Feen-Bogen & Feuer-Pfeil", + "Feen-Bogen & Eis-Pfeil", + "Feen-Bogen & Licht-Pfeil", + "Kokiri-Schwert", + "Master-Schwert", + "Langschwert & Biggoron-Schwert", + "Deku-Schild", + "Hylia-Schild", + "Spiegel-Schild", + "Kokiri-Rüstung", + "Goronen-Rüstung", + "Zora-Rüstung", + "Lederstiefel", + "Eisenstiefel", + "Gleitstiefel", + "Munitionstasche (30)", + "Große Munitionstasche (40)", + "Riesen-Munitionstasche (50)", + "Köcher (30)", + "Großer Köcher (40)", + "Riesenköcher (50)", + "Bombentasche (20)", + "Große Bombentasche (30)", + "Riesen-Bombentasche (40)", + "Goronen-Armband", + "Krafthandschuhe", + "Titanhandschuhe", + "Silberne Schuppe", + "Goldene Schuppe", + "Zerbr. Langschwert", + "Große Börse", + "Riesenbörse", + "Deku-Kerne (5)", + "Angelrute", + "Menuett des Waldes", + "Bolero des Feuers", + "Serenade des Wassers", + "Requiem der Geister", + "Nocturne des Schattens", + "Kantate des Lichts", + "Zeldas Wiegenlied", + "Eponas Lied", + "Salias Lied", + "Hymne der Sonne", + "Hymne der Zeit", + "Hymne des Sturms", + "Amulett des Waldes", + "Amulett des Feuers", + "Amulett des Wassers", + "Amulett der Geister", + "Amulett des Schattens", + "Amulett des Lichts", + "Kokiri-Smaragd", + "Goronen-Rubin", + "Zora-Saphir", + "Stein des Wissens", + "Gerudo-Paß", + "Skulltula-Symbol", + "Herzcontainer", + "Herzteil", + "Master-Schlüssel", + "Kompaß", + "Labyrinth-Karte", + "Kleiner Schlüssel", + "Kleine Magieflasche", + "Große Magieflasche", + "Herzteil", + "[Entfernt]", + "[Entfernt]", + "[Entfernt]", + "[Entfernt]", + "[Entfernt]", + "[Entfernt]", + "[Entfernt]", + "Lon Lon-Milch", + "Herz", + "Grüner Rubin", + "Blauer Rubin", + "Roter Rubin", + "Violetter Rubin", + "Silberner Rubin", + "[Entfernt]", + "Deku-Stäbe (5)", + "Deku-Stäbe (10)", + "Deku-Nüsse (5)", + "Deku-Nüsse (10)", + "Bomben (5)", + "Bomben (10)", + "Bomben (20)", + "Bomben (30)", + "Pfeile (5)", + "Pfeile (10)", + "Pfeile (30)", + "Deku-Kerne (30)", + "Krabbelminen (5)", + "Krabbelminen (20)", + "Deku-Stab-Kapazität (20)", + "Deku-Stab-Kapazität (30)", + "Deku-Nuß-Kapazität (30)", + "Deku-Nuß-Kapazität (40)", +}; + +std::vector questItemNamesEng = { "Forest Medallion", "Fire Medallion", "Water Medallion", "Spirit Medallion", "Shadow Medallion", "Light Medallion", "Minuet of Forest", "Bolero of Fire", "Serenade of Water", "Requiem of Spirit", "Nocturne of Shadow", "Prelude of Light", "Zelda's Lullaby", "Epona's Song", "Saria's Song", @@ -288,6 +607,42 @@ std::vector questItemNames = { "Zora's Sapphire", "Stone of Agony", "Gerudo's Card", "Gold Skulltula Token", }; +std::vector questItemNamesFra = { + "Médaillon de la Forêt", "Médaillon du Feu", "Médaillon de l'Eau", "Médaillon de l'Esprit", + "Médaillon de l'Ombre", "Médaillon de la Lumière", "Menuet des Bois", "Boléro du Feu", + "Sérénade de l'Eau", "Requiem de l'Esprit", "Nocturne de l'Ombre", "Prélude de la Lumière", + "Berceuse de Zelda", "Chant d'Epona", "Chant de Saria", "Chant du Soleil", + "Chant du Temps", "Chant des Tempêtes", "Émeraude Kokiri", "Rubis Goron", + "Saphir Zora", "Pierre de Souffrance", "Carte Gerudo", "Symbole de Skulltula d'Or", +}; + +std::vector questItemNamesGer = { + "Amulett des Waldes", + "Amulett des Feuers", + "Amulett des Wassers", + "Amulett der Geister", + "Amulett des Schattens", + "Amulett des Lichts", + "Menuett des Waldes", + "Bolero des Feuers", + "Serenade des Wassers", + "Requiem der Geister", + "Nocturne des Schattens", + "Kantate des Lichts", + "Zeldas Wiegenlied", + "Eponas Lied", + "Salias Lied", + "Hymne der Sonne", + "Hymne der Zeit", + "Hymne des Sturms", + "Kokiri-Smaragd", + "Goronen-Rubin", + "Zora-Saphir", + "Stein des Wissens", + "Gerudo-Paß", + "Goldenes Skulltula-Symbol", +}; + std::array rcareaPrefixes = { "KF", "LW", @@ -334,23 +689,52 @@ const std::string& SohUtils::GetSceneName(int32_t scene) { } const std::string& SohUtils::GetItemName(int32_t item) { - if (item > itemNames.size()) { + const std::vector* currentItemNames = nullptr; + + switch (gSaveContext.language) { + case LANGUAGE_FRA: + currentItemNames = &itemNamesFra; + break; + case LANGUAGE_GER: + currentItemNames = &itemNamesGer; + break; + case LANGUAGE_ENG: + default: + currentItemNames = &itemNamesEng; + break; + } + + if (item >= currentItemNames->size()) { SPDLOG_WARN("Passed invalid item id to SohUtils::GetItemName: ({})", item); assert(false); return ""; } - return itemNames[item]; + return (*currentItemNames)[item]; } const std::string& SohUtils::GetQuestItemName(int32_t item) { - if (item > questItemNames.size()) { + const std::vector* currentQuestItemNames = nullptr; + + switch (gSaveContext.language) { + case LANGUAGE_FRA: + currentQuestItemNames = &questItemNamesFra; + break; + case LANGUAGE_GER: + currentQuestItemNames = &questItemNamesGer; + break; + case LANGUAGE_ENG: + default: + currentQuestItemNames = &questItemNamesEng; + break; + } + if (item > questItemNamesEng.size()) { SPDLOG_WARN("Passed invalid quest item id to SohUtils::GetQuestItemName: ({})", item); assert(false); return ""; } - return questItemNames[item]; + return (*currentQuestItemNames)[item]; } const std::string& SohUtils::GetRandomizerCheckAreaPrefix(int32_t rcarea) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index ea849af05..403541948 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -1,7 +1,7 @@ #include "OTRGlobals.h" #include #include "soh/resource/type/Scene.h" -#include +#include #include "global.h" #include "vt.h" #include "soh/resource/type/Text.h" diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index 23e61261c..8864351b4 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -2,11 +2,11 @@ #include "ResourceManagerHelpers.h" #include #include "soh/resource/type/Scene.h" -#include +#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "global.h" #include "vt.h" -#include +#include extern "C" void Play_InitScene(PlayState* play, s32 spawn); extern "C" void Play_InitEnvironment(PlayState* play, s16 skyboxId); @@ -79,6 +79,7 @@ void OTRPlay_InitScene(PlayState* play, s32 spawn) { YREG(15) = 0; gSaveContext.worldMapArea = 0; OTRScene_ExecuteCommands(play, (SOH::Scene*)play->sceneSegment); + GameInteractor_ExecuteAfterSceneCommands(play->sceneNum); Play_InitEnvironment(play, play->skyboxId); /* auto data = static_cast(Ship::Context::GetInstance() diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index b4f8a29e8..d49367024 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -2,15 +2,15 @@ #include "ResourceManagerHelpers.h" #include #include "soh/resource/type/Scene.h" -#include +#include #include "global.h" #include "vt.h" #include "soh/resource/type/CollisionHeader.h" -#include +#include #include "soh/resource/type/Cutscene.h" #include "soh/resource/type/Path.h" #include "soh/resource/type/Text.h" -#include +#include #include #include #include "soh/resource/type/scenecommand/SetCameraSettings.h" @@ -472,6 +472,10 @@ extern "C" s32 OTRfunc_800973FC(PlayState* play, RoomContext* roomCtx) { gSegments[3] = VIRTUAL_TO_PHYSICAL(roomCtx->unk_34); OTRScene_ExecuteCommands(play, (SOH::Scene*)roomCtx->roomToLoad); + if (!GameInteractor_Should(VB_DRAW_2D_BACKGROUND, true)) { + play->envCtx.skyboxDisabled = false; + } + Player_SetBootData(play, GET_PLAYER(play)); Actor_SpawnTransitionActors(play, &play->actorCtx); diff --git a/soh/src/code/audio_load.c b/soh/src/code/audio_load.c index 81f67f9c0..f5d24756d 100644 --- a/soh/src/code/audio_load.c +++ b/soh/src/code/audio_load.c @@ -8,6 +8,7 @@ #include "soh/Enhancements/audio/AudioCollection.h" #include "soh/Enhancements/audio/AudioEditor.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #ifdef _MSC_VER #define strdup _strdup @@ -630,21 +631,7 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { AudioSeq_SkipForwardSequence(seqPlayer); //! @bug missing return (but the return value is not used so it's not UB) - // Keep track of the previous sequence/scene so we don't repeat notifications - static uint16_t previousSeqId = UINT16_MAX; - static int16_t previousSceneNum = INT16_MAX; - if (CVarGetInteger(CVAR_AUDIO("SeqNameOverlay"), 0) && playerIdx == SEQ_PLAYER_BGM_MAIN && - (seqId != previousSeqId || (gPlayState != NULL && gPlayState->sceneNum != previousSceneNum))) { - - previousSeqId = seqId; - if (gPlayState != NULL) { - previousSceneNum = gPlayState->sceneNum; - } - const char* sequenceName = AudioCollection_GetSequenceName(seqId); - if (sequenceName != NULL) { - Overlay_DisplayText_Seconds(CVarGetInteger(CVAR_AUDIO("SeqNameOverlayDuration"), 5), sequenceName); - } - } + GameInteractor_ExecuteOnSeqPlayerInit(playerIdx, seqId); } u8* AudioLoad_SyncLoadSeq(s32 seqId) { diff --git a/soh/src/code/main.c b/soh/src/code/main.c index 0a255f48d..558b30d2f 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -1,5 +1,6 @@ #ifdef _WIN32 #include +#include #endif #include "global.h" @@ -44,7 +45,7 @@ void Main_LogSystemHeap(void) { } #ifdef _WIN32 -int SDL_main(int argc, char** argv) { +int SDL_main(int argc, char* argv[]) { AllocConsole(); (void)freopen("CONIN$", "r", stdin); (void)freopen("CONOUT$", "w", stdout); @@ -52,13 +53,14 @@ int SDL_main(int argc, char** argv) { #ifndef _DEBUG ShowWindow(GetConsoleWindow(), SW_HIDE); #endif + // Allow non-ascii characters for Windows + setlocale(LC_ALL, ".UTF8"); #else //_WIN32 -int main(int argc, char** argv) { +int main(int argc, char* argv[]) { #endif - GameConsole_Init(); - InitOTR(); + InitOTR(argc, argv); // TODO: Was moved to below InitOTR because it requires window to be setup. But will be late to catch crashes. CrashHandlerRegisterCallback(CrashHandler_PrintSohData); BootCommands_Init(); diff --git a/soh/src/code/sys_ucode.c b/soh/src/code/sys_ucode.c index 39bbe3531..678c58c36 100644 --- a/soh/src/code/sys_ucode.c +++ b/soh/src/code/sys_ucode.c @@ -1,6 +1,6 @@ #include "global.h" -#include "public/bridge/gfxbridge.h" +#include UcodeHandlers sDefaultGSPUCodeText = ucode_f3dex2; // u64* sDefaultGSPUCodeData = gspF3DZEX2_NoN_PosLight_fifoDataStart; diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index fc63f96c8..6c357c612 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -2782,7 +2782,6 @@ void Message_OpenText(PlayState* play, u16 textId) { gSaveContext.eventInf[0] = gSaveContext.eventInf[1] = gSaveContext.eventInf[2] = gSaveContext.eventInf[3] = 0; } - // RANDOTODO: Use this for ice trap messages if (CustomMessage_RetrieveIfExists(play)) { osSyncPrintf("Found custom message"); if (gSaveContext.language == LANGUAGE_JPN) { diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 930ed8eb0..cab1d3cff 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -8,7 +8,6 @@ #include "libultraship/bridge.h" #include "soh/Enhancements/gameplaystats.h" -#include "soh/Enhancements/boss-rush/BossRushTypes.h" #include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" #include "soh/Enhancements/enhancementTypes.h" @@ -6425,11 +6424,10 @@ void Interface_Draw(PlayState* play) { void Interface_DrawTotalGameplayTimer(PlayState* play) { // Draw timer based on the Gameplay Stats total time. - - if ((IS_BOSS_RUSH && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_TIMER] == BR_CHOICE_TIMER_YES) || - (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowIngameTimer"), 0) && gSaveContext.fileNum >= 0 && - gSaveContext.fileNum <= 2)) { - + if (GameInteractor_Should(VB_SHOW_GAMEPLAY_TIMER, + CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowIngameTimer"), 0) && gSaveContext.fileNum >= 0 && + gSaveContext.fileNum <= 2, + play)) { s32 X_Margins_Timer = 0; if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.UseMargins"), 0) != 0) { if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosType"), 0) == ORIGINAL_LOCATION) { diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index dfc832fc7..b1a714dcb 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -1390,6 +1390,8 @@ void Play_Draw(PlayState* play) { Gfx_SetupFrame(gfxCtx, 0, 0, 0); if ((HREG(80) != 10) || (HREG(82) != 0)) { + GameInteractor_ExecuteOnPlayDrawBegin(); + POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); POLY_XLU_DISP = Play_SetFog(play, POLY_XLU_DISP); diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index 0aba1ae8e..37f4e68fe 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -5,10 +5,11 @@ #include "global.h" #include "vt.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #include -#include "public/bridge/gfxbridge.h" +#include #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" @@ -256,6 +257,9 @@ s32 swapAndConvertJPEG(void* data) { void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 tlutMode, u16 tlutCount, f32 offsetX, f32 offsetY) { + if (!GameInteractor_Should(VB_DRAW_2D_BACKGROUND, true)) { + return; + } Gfx* gfx = *gfxP; uObjBg* bg; diff --git a/soh/src/code/z_vr_box.c b/soh/src/code/z_vr_box.c index c11db1605..f03f9dc7f 100644 --- a/soh/src/code/z_vr_box.c +++ b/soh/src/code/z_vr_box.c @@ -71,6 +71,9 @@ #include "assets/textures/skyboxes/vr_holy1_static.h" #include "assets/textures/skyboxes/vr_holy1_pal_static.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + u32 D_8012AC90[4] = { 0x00000000, 0x00010000, @@ -449,17 +452,23 @@ void func_800AF178(SkyboxContext* skyboxCtx, s32 arg1) { void LoadSkyboxTex(SkyboxContext* skyboxCtx, int segmentIndex, int imageIndex, char* tex, int width, int height, int offsetW, int offsetH) { - skyboxCtx->textures[segmentIndex][imageIndex] = tex; + if (GameInteractor_Should(VB_LOAD_SKYBOX, true)) { + skyboxCtx->textures[segmentIndex][imageIndex] = tex; + } } void LoadSkyboxTexAtOffset(SkyboxContext* skyboxCtx, int segmentIndex, int imageIndex, char* tex, int width, int height, int offset) { - skyboxCtx->textures[segmentIndex][imageIndex] = tex; + if (GameInteractor_Should(VB_LOAD_SKYBOX, true)) { + skyboxCtx->textures[segmentIndex][imageIndex] = tex; + } } void LoadSkyboxPalette(SkyboxContext* skyboxCtx, int paletteIndex, char* palTex, int width, int height) { - skyboxCtx->palettes[paletteIndex] = palTex; - skyboxCtx->palette_size = width * height; + if (GameInteractor_Should(VB_LOAD_SKYBOX, true)) { + skyboxCtx->palettes[paletteIndex] = palTex; + skyboxCtx->palette_size = width * height; + } } static const char* sSBVRFine0Tex[] = { gSunriseSkybox1Tex, gSunriseSkybox2Tex, gSunriseSkybox3Tex, gSunriseSkybox4Tex, diff --git a/soh/src/overlays/actors/ovl_Bg_Mizu_Movebg/z_bg_mizu_movebg.c b/soh/src/overlays/actors/ovl_Bg_Mizu_Movebg/z_bg_mizu_movebg.c index 093e73eb4..7dbe531d5 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mizu_Movebg/z_bg_mizu_movebg.c +++ b/soh/src/overlays/actors/ovl_Bg_Mizu_Movebg/z_bg_mizu_movebg.c @@ -1,7 +1,7 @@ /* * File: z_bg_mizu_movebg.c * Overlay: ovl_Bg_Mizu_Movebg - * Description: Kakariko Village Well Water + * Description: Water Temple Moving Objects */ #include "z_bg_mizu_movebg.h" diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index 1a491064a..ea983771f 100644 --- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -335,7 +335,7 @@ f32 func_80996840(PlayState* play, DoorShutter* this, f32 arg2, f32 arg3, f32 ar sp28.y = player->actor.world.pos.y + arg2; sp28.z = player->actor.world.pos.z; Actor_WorldToActorCoords(&this->dyna.actor, &sp1C, &sp28); - if (arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y)) { + if (GameInteractor_Should(VB_BE_NEAR_DOOR_SHUTTER, arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y), this, &sp1C)) { return FLT_MAX; } else { return sp1C.z; diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index 54e9768b4..25e33243e 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -1,7 +1,6 @@ #include "z_door_warp1.h" #include "objects/object_warp1/object_warp1.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" -#include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" @@ -693,12 +692,7 @@ void DoorWarp1_AdultWarpIdle(DoorWarp1* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EV_WARP_HOLE - SFX_FLAG); - if (DoorWarp1_PlayerInRange(this, play)) { - // Heal player in Boss Rush - if (IS_BOSS_RUSH) { - BossRush_HandleBlueWarpHeal(play); - } - + if (GameInteractor_Should(VB_BLUE_WARP_CONSIDER_ADULT_IN_RANGE, DoorWarp1_PlayerInRange(this, play), this)) { player = GET_PLAYER(play); OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM); @@ -813,8 +807,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { - if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, - !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { @@ -832,8 +825,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { - if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, - !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 9a3a8fb77..f52b4a458 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -567,8 +567,10 @@ void EnBox_Update(Actor* thisx, PlayState* play) { Actor_SetFocus(&this->dyna.actor, 40.0f); } - if ((this->dyna.actor.params >> 5 & 0x7F) == GI_ICE_TRAP && this->actionFunc == EnBox_Open && - this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) { + if (GameInteractor_Should(VB_CHEST_USE_ICE_EFFECT, + (this->dyna.actor.params >> 5 & 0x7F) == GI_ICE_TRAP && this->actionFunc == EnBox_Open && + this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100, + this)) { EnBox_SpawnIceSmoke(this, play); } } diff --git a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c index 3dee59f27..cb59641fd 100644 --- a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c +++ b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c @@ -79,7 +79,8 @@ void EnOkarinaTag_Init(Actor* thisx, PlayState* play) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 当り?\t\t ☆☆☆☆☆ %d\n" VT_RST, this->unk_158); osSyncPrintf("\n\n"); - if ((this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag))) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETED, + (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)), this)) { Actor_Kill(&this->actor); } else { switch (this->type) { @@ -113,7 +114,8 @@ void func_80ABEF2C(EnOkarinaTag* this, PlayState* play) { player = GET_PLAYER(play); this->unk_15A++; - if ((this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag))) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETED, + (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)), this)) { this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; } else { if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { @@ -148,7 +150,7 @@ void func_80ABF0CC(EnOkarinaTag* this, PlayState* play) { this->actionFunc = func_80ABEF2C; } else { if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { - if (this->switchFlag >= 0) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETE, this->switchFlag >= 0, this)) { Flags_SetSwitch(play, this->switchFlag); } if (play->sceneNum == SCENE_WATER_TEMPLE) { @@ -167,7 +169,7 @@ void func_80ABF0CC(EnOkarinaTag* this, PlayState* play) { (play->msgCtx.ocarinaMode == OCARINA_MODE_07) || (play->msgCtx.ocarinaMode == OCARINA_MODE_08) || (play->msgCtx.ocarinaMode == OCARINA_MODE_09) || (play->msgCtx.ocarinaMode == OCARINA_MODE_0A) || (play->msgCtx.ocarinaMode == OCARINA_MODE_0D)) { - if (this->switchFlag >= 0) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETE, this->switchFlag >= 0, this)) { Flags_SetSwitch(play, this->switchFlag); } play->msgCtx.ocarinaMode = OCARINA_MODE_04; @@ -190,7 +192,8 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) { this->unk_15A++; if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { - if ((this->switchFlag >= 0) && Flags_GetSwitch(play, this->switchFlag)) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETED, + (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)), this)) { this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; } else if (((this->type != 4) || GameInteractor_Should(VB_BE_ELIGIBLE_TO_OPEN_DOT, @@ -237,7 +240,7 @@ void func_80ABF4C8(EnOkarinaTag* this, PlayState* play) { this->actionFunc = func_80ABF28C; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); - if (this->switchFlag >= 0) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETE, this->switchFlag >= 0, this)) { Flags_SetSwitch(play, this->switchFlag); } switch (this->type) { diff --git a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c index d850021a4..c62db2dd8 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c +++ b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c @@ -238,6 +238,11 @@ void EnPoRelay_Race(EnPoRelay* this, PlayState* play) { } else { speed = 3.5f; } + + if (CVarGetInteger(CVAR_ENHANCEMENT("FixDampeGoingBackwards"), false)) { + speed = ABS(speed); + } + multiplier = 250.0f - this->actor.xzDistToPlayer; multiplier = CLAMP_MIN(multiplier, 0.0f); speed += multiplier * 0.02f + 1.0f; diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index 2fe2445a6..1fe96d38c 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -357,16 +357,18 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) { dropsSpawnPt = this->actor.world.pos; dropsSpawnPt.y += 200.0f; - if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) { - if (GameInteractor_Should(VB_TREE_DROP_COLLECTIBLE, true, this)) { - Item_DropCollectibleRandom(play, &this->actor, &dropsSpawnPt, this->unk_14C << 4); + if (GameInteractor_Should(VB_TREE_DROP_ITEM, true, this)) { + if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) { + if (GameInteractor_Should(VB_TREE_DROP_COLLECTIBLE, true, this)) { + Item_DropCollectibleRandom(play, &this->actor, &dropsSpawnPt, this->unk_14C << 4); + } + } else if (this->actor.home.rot.z != 0) { + this->actor.home.rot.z &= 0x1FFF; + this->actor.home.rot.z |= 0xE000; + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SW, dropsSpawnPt.x, dropsSpawnPt.y, dropsSpawnPt.z, 0, + this->actor.world.rot.y, 0, this->actor.home.rot.z, true); + this->actor.home.rot.z = 0; } - } else if (this->actor.home.rot.z != 0) { - this->actor.home.rot.z &= 0x1FFF; - this->actor.home.rot.z |= 0xE000; - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SW, dropsSpawnPt.x, dropsSpawnPt.y, dropsSpawnPt.z, 0, - this->actor.world.rot.y, 0, this->actor.home.rot.z, true); - this->actor.home.rot.z = 0; } // Spawn falling leaves @@ -457,12 +459,13 @@ void EnWood02_Draw(Actor* thisx, PlayState* play) { } Gfx_SetupDL_25Xlu(gfxCtx); - - if ((this->actor.params == WOOD_LEAF_GREEN) || (this->actor.params == WOOD_LEAF_YELLOW)) { + if (GameInteractor_Should(VB_TREE_SETUP_DRAW, + (this->actor.params == WOOD_LEAF_GREEN) || (this->actor.params == WOOD_LEAF_YELLOW), + this)) { Gfx_SetupDL_25Opa(gfxCtx); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, red, green, blue, 127); Gfx_DrawDListOpa(play, object_wood02_DL_000700); - } else if (D_80B3BF70[this->drawType & 0xF] != NULL) { + } else if (GameInteractor_Should(VB_TREE_SETUP_DRAW, D_80B3BF70[this->drawType & 0xF] != NULL, this)) { Gfx_DrawDListOpa(play, D_80B3BF54[this->drawType & 0xF]); gDPSetEnvColor(POLY_XLU_DISP++, red, green, blue, 0); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); 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 f8c3c7203..64ae0415a 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -5797,7 +5797,10 @@ void func_8083AA10(Player* this, PlayState* play) { if (this->hoverBootsTimer != 0) { this->actor.velocity.y = 1.0f; - sPrevFloorProperty = 9; + + if (GameInteractor_Should(VB_SET_STATIC_PREV_FLOOR_TYPE, true, this)) { + sPrevFloorProperty = 9; + } return; } @@ -11152,7 +11155,9 @@ s32 Player_UpdateHoverBoots(Player* this) { } return false; } else { - sFloorType = 0; + if (GameInteractor_Should(VB_SET_STATIC_FLOOR_TYPE, true, this)) { + sFloorType = 0; + } this->floorPitch = this->floorPitchAlt = sFloorShapePitch = 0; return true; @@ -11183,7 +11188,9 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { f32 ceilingCheckHeight; u32 flags; - sPrevFloorProperty = this->floorProperty; + if (GameInteractor_Should(VB_SET_STATIC_PREV_FLOOR_TYPE, true, this)) { + sPrevFloorProperty = this->floorProperty; + } #define vWallCheckRadius float0 #define vWallCheckHeight float1 @@ -11454,7 +11461,9 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { } if (this->actor.bgCheckFlags & 1) { - sFloorType = func_80041D4C(&play->colCtx, floorPoly, this->actor.floorBgId); + if (GameInteractor_Should(VB_SET_STATIC_FLOOR_TYPE, true, this)) { + sFloorType = func_80041D4C(&play->colCtx, floorPoly, this->actor.floorBgId); + } if (!Player_UpdateHoverBoots(this)) { f32 floorPolyNormalX; @@ -12101,7 +12110,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { Actor_UpdatePos(&this->actor); Player_ProcessSceneCollision(play, this); } else { - sFloorType = 0; + if (GameInteractor_Should(VB_SET_STATIC_FLOOR_TYPE, true, this)) { + sFloorType = 0; + } this->floorProperty = 0; if (!(this->stateFlags1 & PLAYER_STATE1_LOADING) && (this->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index c7a0e23de..717988755 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1403,110 +1403,6 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) { } } -static s8 sLastBossRushOptionIndex = -1; -static s8 sLastBossRushOptionValue = -1; - -void FileChoose_UpdateBossRushMenu(GameState* thisx) { - FileChoose_UpdateStickDirectionPromptAnim(thisx); - FileChooseContext* this = (FileChooseContext*)thisx; - Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); - - // Fade in elements after opening Boss Rush options menu - this->bossRushUIAlpha += 25; - if (this->bossRushUIAlpha > 255) { - this->bossRushUIAlpha = 255; - } - - // Animate up/down arrows. - this->bossRushArrowOffset += 1; - if (this->bossRushArrowOffset >= 30) { - this->bossRushArrowOffset = 0; - } - - // Move menu selection up or down. - if (ABS(this->stickRelY) > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) { - // Move down - if (this->stickRelY < -30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN))) { - // When selecting past the last option, cycle back to the first option. - if ((this->bossRushIndex + 1) > BR_OPTIONS_MAX - 1) { - this->bossRushIndex = 0; - this->bossRushOffset = 0; - } else { - this->bossRushIndex++; - // When last visible option is selected when moving down, offset the list down by one. - if (this->bossRushIndex - this->bossRushOffset > BOSSRUSH_MAX_OPTIONS_ON_SCREEN - 1) { - this->bossRushOffset++; - } - } - } else if (this->stickRelY > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DUP))) { - // When selecting past the first option, cycle back to the last option and offset the list to view it - // properly. - if ((this->bossRushIndex - 1) < 0) { - this->bossRushIndex = BR_OPTIONS_MAX - 1; - this->bossRushOffset = this->bossRushIndex - BOSSRUSH_MAX_OPTIONS_ON_SCREEN + 1; - } else { - // When first visible option is selected when moving up, offset the list up by one. - if (this->bossRushIndex - this->bossRushOffset == 0) { - this->bossRushOffset--; - } - this->bossRushIndex--; - } - } - - Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - } - - // Cycle through choices for currently selected option. - if (ABS(this->stickRelX) > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DRIGHT))) { - if (this->stickRelX > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DRIGHT))) { - // If exceeding the amount of choices for the selected option, cycle back to the first. - if ((gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex] + 1) == - BossRush_GetSettingOptionsAmount(this->bossRushIndex)) { - gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex] = 0; - } else { - gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex]++; - } - } else if (this->stickRelX < -30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT))) { - // If cycling back when already at the first choice for the selected option, cycle back to the last choice. - if ((gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex] - 1) < 0) { - gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex] = - BossRush_GetSettingOptionsAmount(this->bossRushIndex) - 1; - } else { - gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex]--; - } - } - - Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - } - - if (sLastBossRushOptionIndex != this->bossRushIndex || - sLastBossRushOptionValue != gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex]) { - GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection( - this->bossRushIndex, gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex]); - sLastBossRushOptionIndex = this->bossRushIndex; - sLastBossRushOptionValue = gSaveContext.ship.quest.data.bossRush.options[this->bossRushIndex]; - } - - if (CHECK_BTN_ALL(input->press.button, BTN_B)) { - this->configMode = CM_BOSS_RUSH_TO_QUEST; - return; - } - - // Load into the game. - if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) { - Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - this->buttonIndex = 0xFE; - this->menuMode = FS_MENU_MODE_SELECT; - this->selectMode = SM_FADE_OUT; - this->prevConfigMode = this->configMode; - return; - } -} - void FileChoose_UpdateRandomizerMenu(GameState* thisx) { FileChoose_UpdateStickDirectionPromptAnim(thisx); FileChooseContext* this = (FileChooseContext*)thisx; @@ -2849,63 +2745,7 @@ void FileChoose_DrawWindowContents(GameState* thisx) { break; } } else if (this->configMode == CM_BOSS_RUSH_MENU) { - uint8_t language = (gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language; - uint8_t listOffset = this->bossRushOffset; - uint8_t textAlpha = this->bossRushUIAlpha; - - // Draw arrows to indicate that the list can scroll up or down. - // Arrow up - if (listOffset > 0) { - uint16_t arrowUpX = 140; - uint16_t arrowUpY = 76 - (this->bossRushArrowOffset / 10); - gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowUpTex, G_IM_FMT_IA, G_IM_SIZ_16b, 16, 16, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, - G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(POLY_OPA_DISP++, arrowUpX << 2, arrowUpY << 2, (arrowUpX + 8) << 2, - (arrowUpY + 8) << 2, G_TX_RENDERTILE, 0, 0, (1 << 11), (1 << 11)); - } - // Arrow down - if (BR_OPTIONS_MAX - listOffset > BOSSRUSH_MAX_OPTIONS_ON_SCREEN) { - uint16_t arrowDownX = 140; - uint16_t arrowDownY = 181 + (this->bossRushArrowOffset / 10); - gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowDownTex, G_IM_FMT_IA, G_IM_SIZ_16b, 16, 16, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, - G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(POLY_OPA_DISP++, arrowDownX << 2, arrowDownY << 2, (arrowDownX + 8) << 2, - (arrowDownY + 8) << 2, G_TX_RENDERTILE, 0, 0, (1 << 11), (1 << 11)); - } - - // Draw options. There's more options than what fits on the screen, so the visible options - // depend on the current offset of the list. Currently selected option pulses in - // color and has arrows surrounding the option. - for (uint8_t i = listOffset; i - listOffset < BOSSRUSH_MAX_OPTIONS_ON_SCREEN; i++) { - uint16_t textYOffset = (i - listOffset) * 16; - - // Option name. - Interface_DrawTextLine(this->state.gfxCtx, BossRush_GetSettingName(i, language), 65, (87 + textYOffset), - 255, 255, 80, textAlpha, 0.8f, true); - - // Selected choice for option. - uint16_t finalKerning = Interface_DrawTextLine( - this->state.gfxCtx, - BossRush_GetSettingChoiceName(i, gSaveContext.ship.quest.data.bossRush.options[i], language), 165, - (87 + textYOffset), 255, 255, 255, textAlpha, 0.8f, true); - - // Draw arrows around selected option. - if (this->bossRushIndex == i) { - Gfx_SetupDL_39Opa(this->state.gfxCtx); - gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowCursorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 24, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD, - G_TX_NOLOD); - FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.arrowColorR, - this->stickLeftPrompt.arrowColorG, this->stickLeftPrompt.arrowColorB, textAlpha, - 160, (92 + textYOffset), 0.42f, 0, 0, -1.0f, 1.0f); - FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.arrowColorR, - this->stickRightPrompt.arrowColorG, this->stickRightPrompt.arrowColorB, - textAlpha, (171 + finalKerning), (92 + textYOffset), 0.42f, 0, 0, 1.0f, 1.0f); - } - } + FileChoose_DrawBossRushMenuWindowContents(this); } else if (this->configMode == CM_RANDOMIZER_SETTINGS_MENU) { uint8_t language = (gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language; uint8_t textAlpha = this->randomizerUIAlpha; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c index 78a072c6f..ade62acc3 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c @@ -8,51 +8,6 @@ extern const char* digitTextures[]; void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { - Color_RGB8 aButtonColor = { 80, 150, 255 }; - if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { - aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); - } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { - aButtonColor = (Color_RGB8){ 80, 255, 150 }; - } - if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_D4, true)) { - aButtonColor = (Color_RGB8){ 191, 191, 191 }; - } - - Color_RGB8 cButtonsColor = { 255, 255, 50 }; - if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { - cButtonsColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor); - } - Color_RGB8 cUpButtonColor = cButtonsColor; - if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { - cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor); - } - if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_D5, true)) { - cUpButtonColor = (Color_RGB8){ 191, 191, 191 }; - } - - Color_RGB8 cDownButtonColor = cButtonsColor; - if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { - cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor); - } - if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_F4, true)) { - cDownButtonColor = (Color_RGB8){ 191, 191, 191 }; - } - - Color_RGB8 cLeftButtonColor = cButtonsColor; - if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { - cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor); - } - if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_B4, true)) { - cLeftButtonColor = (Color_RGB8){ 191, 191, 191 }; - } - - Color_RGB8 cRightButtonColor = cButtonsColor; - if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { - cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor); - } - if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_A4, true)) { - cRightButtonColor = (Color_RGB8){ 191, 191, 191 }; - } static s16 D_8082A070[][4] = { { 255, 0, 0, 255 }, @@ -124,22 +79,22 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { s16 pad2; s16 phi_s0_2; s16 sp208[3]; - if (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0)) { - if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { - pauseCtx->stickRelX = -35; - } else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) { - pauseCtx->stickRelX = 35; - } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { - pauseCtx->stickRelY = -35; - } else if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) { - pauseCtx->stickRelY = 35; - } - } OPEN_DISPS(gfxCtx); if (((pauseCtx->unk_1E4 == 0) || (pauseCtx->unk_1E4 == 5) || (pauseCtx->unk_1E4 == 8)) && (pauseCtx->pageIndex == PAUSE_QUEST)) { + if (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0)) { + if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { + pauseCtx->stickRelX = -35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) { + pauseCtx->stickRelX = 35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { + pauseCtx->stickRelY = -35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) { + pauseCtx->stickRelY = 35; + } + } pauseCtx->cursorColorSet = 0; if (pauseCtx->cursorSpecialPos == 0) { @@ -516,6 +471,52 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } if (pauseCtx->state == 6) { + Color_RGB8 aButtonColor = { 80, 150, 255 }; + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + aButtonColor = (Color_RGB8){ 80, 255, 150 }; + } + if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_D4, true)) { + aButtonColor = (Color_RGB8){ 191, 191, 191 }; + } + + Color_RGB8 cButtonsColor = { 255, 255, 50 }; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + cButtonsColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor); + } + Color_RGB8 cUpButtonColor = cButtonsColor; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { + cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor); + } + if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_D5, true)) { + cUpButtonColor = (Color_RGB8){ 191, 191, 191 }; + } + + Color_RGB8 cDownButtonColor = cButtonsColor; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { + cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor); + } + if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_F4, true)) { + cDownButtonColor = (Color_RGB8){ 191, 191, 191 }; + } + + Color_RGB8 cLeftButtonColor = cButtonsColor; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { + cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor); + } + if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_B4, true)) { + cLeftButtonColor = (Color_RGB8){ 191, 191, 191 }; + } + + Color_RGB8 cRightButtonColor = cButtonsColor; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { + cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor); + } + if (!GameInteractor_Should(VB_HAVE_OCARINA_NOTE_A4, true)) { + cRightButtonColor = (Color_RGB8){ 191, 191, 191 }; + } + gDPPipeSync(POLY_OPA_DISP++); gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index aa18912ea..cec05af72 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -183,10 +183,6 @@ void KaleidoScope_DrawEquipment(PlayState* play) { s16 cursorX; s16 cursorY; s16 oldCursorPoint; - bool dpad = (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); - bool pauseAnyCursor = - (CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); OPEN_DISPS(play->state.gfxCtx); @@ -204,6 +200,11 @@ void KaleidoScope_DrawEquipment(PlayState* play) { } if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_EQUIP)) { + bool dpad = (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); + bool pauseAnyCursor = + (CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + oldCursorPoint = pauseCtx->cursorPoint[PAUSE_EQUIP]; pauseCtx->cursorColorSet = 0; 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 beef301c4..7f0cfcc7a 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 @@ -421,11 +421,6 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { s16 cursorY; s16 oldCursorPoint; s16 moveCursorResult; - bool dpad = (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); - bool pauseAnyCursor = - pauseCtx->cursorSpecialPos == 0 && - ((CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON)); OPEN_DISPS(play->state.gfxCtx); @@ -437,6 +432,12 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->nameColorSet = 0; if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM)) { + bool dpad = (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); + bool pauseAnyCursor = + pauseCtx->cursorSpecialPos == 0 && + ((CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger(CVAR_ENHANCEMENT("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON)); + moveCursorResult = 0 || IsItemCycling(); oldCursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM]; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c index 3ff61d783..5b5665dab 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c @@ -8,7 +8,7 @@ #include "textures/icon_item_dungeon_static/icon_item_dungeon_static.h" #include "textures/icon_item_nes_static/icon_item_nes_static.h" -#include "public/bridge/gfxbridge.h" +#include void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { static void* dungeonItemTexs[] = { @@ -59,11 +59,11 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { s16 stepG; s16 stepB; u16 rgba16; - bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); OPEN_DISPS(gfxCtx); if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_MAP)) { + bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); pauseCtx->cursorColorSet = 0; oldCursorPoint = pauseCtx->cursorPoint[PAUSE_MAP];