Merge remote-tracking branch 'origin/develop' into actor-accessibility-experiments

This commit is contained in:
Demur Rumed 2025-06-25 00:52:22 +00:00
commit 0564a0f821
185 changed files with 16119 additions and 6262 deletions

View file

@ -1 +1 @@
libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev nlohmann-json3-dev libtinyxml2-dev libspdlog-dev ninja-build
libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libespeak-ng-dev ninja-build

View file

@ -62,16 +62,16 @@ jobs:
cmake ..
make
sudo make install
- name: Generate soh.otr
- name: Generate soh.o2r
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
cmake --build build-cmake --config Release --target GenerateSohOtr -j3
- name: Upload soh.otr
- name: Upload soh.o2r
uses: actions/upload-artifact@v4
with:
name: soh.otr
path: soh.otr
name: soh.o2r
path: soh.o2r
retention-days: 3
build-macos:
@ -122,10 +122,10 @@ jobs:
brew uninstall --ignore-dependencies libpng
sudo port install $(cat .github/workflows/macports-deps.txt)
brew install ninja
- name: Download soh.otr
- name: Download soh.o2r
uses: actions/download-artifact@v4
with:
name: soh.otr
name: soh.o2r
path: build-cmake/soh
- name: Build SoH
run: |
@ -233,10 +233,10 @@ jobs:
make
sudo make install
sudo cp -av /usr/local/lib/libzip* /lib/x86_64-linux-gnu/
- name: Download soh.otr
- name: Download soh.o2r
uses: actions/download-artifact@v4
with:
name: soh.otr
name: soh.o2r
path: build-cmake/soh
- name: Build SoH
run: |
@ -298,10 +298,10 @@ jobs:
path: vcpkg
- name: Configure Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
- name: Download soh.otr
- name: Download soh.o2r
uses: actions/download-artifact@v4
with:
name: soh.otr
name: soh.o2r
path: build-windows/soh
- name: Build SoH
env:

View file

@ -48,7 +48,7 @@ jobs:
});
return allArtifacts.data.artifacts.reduce((acc, item) => {
if (item.name === "soh.otr") return acc;
if (item.name === "soh.o2r") return acc;
acc += `
- [${item.name}.zip](https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/artifacts/${item.id}.zip)`;
return acc;

View file

@ -23,24 +23,24 @@ jobs:
if: ${{ matrix.image == 'archlinux:base' }}
run: |
echo arch
echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost
echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net
pacman -Syu --noconfirm
pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost
pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net
- name: Install dependencies (dnf)
if: ${{ matrix.image == 'fedora:39' }}
run: |
echo fedora
echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel boost-devel
echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel
dnf -y upgrade
dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel boost-devel
dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel
- name: Install dependencies (apt)
if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }}
run: |
echo debian based
echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev
echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libopengl-dev
apt-get update
apt-get -y full-upgrade
apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev
apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libopengl-dev
- name: Install dependencies (zypper)
if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }}
run: |

1
.gitignore vendored
View file

@ -412,6 +412,7 @@ ReleaseObj/*
.tags
tags
*.otr
*.o2r
*.sav
shipofharkinian.ini
shipofharkinian.json

View file

@ -174,24 +174,15 @@ set_property(TARGET soh PROPERTY APPIMAGE_DESKTOP_FILE "${CMAKE_SOURCE_DIR}/scri
set_property(TARGET soh PROPERTY APPIMAGE_ICON_FILE "${CMAKE_BINARY_DIR}/sohIcon.png")
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
install(PROGRAMS "${CMAKE_BINARY_DIR}/linux/soh.sh" DESTINATION . COMPONENT appimage)
install(FILES "${CMAKE_BINARY_DIR}/soh/soh.otr" DESTINATION . COMPONENT ship)
install(FILES "${CMAKE_BINARY_DIR}/soh/soh.o2r" DESTINATION . COMPONENT ship)
install(TARGETS ZAPD DESTINATION ./assets/extractor COMPONENT extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor COMPONENT extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls COMPONENT extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists COMPONENT extractor)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets COMPONENT extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT extractor)
endif()
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor COMPONENT ship)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls COMPONENT ship)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists COMPONENT ship)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT ship)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT ship)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT ship)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/ COMPONENT ship)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT ship)
endif()
find_package(Python3 COMPONENTS Interpreter)
@ -199,42 +190,42 @@ find_package(Python3 COMPONENTS Interpreter)
# Target to generate OTRs
add_custom_target(
ExtractAssets
COMMAND ${CMAKE_COMMAND} -E rm -f oot.otr oot-mq.otr soh.otr
COMMAND ${CMAKE_COMMAND} -E rm -f oot.o2r oot-mq.o2r soh.o2r
# 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 ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --xml-root ../soh/assets/xml --custom-otr-file soh.otr "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}"
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --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="$<TARGET_FILE_DIR:ZAPD>" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
COMMENT "Running asset extraction..."
DEPENDS ZAPD
BYPRODUCTS oot.otr ${CMAKE_SOURCE_DIR}/oot.otr oot-mq.otr ${CMAKE_SOURCE_DIR}/oot-mq.otr ${CMAKE_SOURCE_DIR}/soh.otr
BYPRODUCTS oot.o2r ${CMAKE_SOURCE_DIR}/oot.o2r oot-mq.o2r ${CMAKE_SOURCE_DIR}/oot-mq.o2r ${CMAKE_SOURCE_DIR}/soh.o2r
)
# Target to generate headers
add_custom_target(
ExtractAssetHeaders
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --xml-root ../soh/assets/xml --gen-headers
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --xml-root assets/xml --gen-headers
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
COMMENT "Generating asset headers..."
DEPENDS ZAPD
)
# Target to generate only soh.otr
# Target to generate only soh.o2r
add_custom_target(
GenerateSohOtr
COMMAND ${CMAKE_COMMAND} -E rm -f soh.otr
COMMAND ${CMAKE_COMMAND} -E rm -f soh.o2r
# 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 ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --norom --custom-otr-file soh.otr "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}"
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --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="$<TARGET_FILE_DIR:ZAPD>" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -DONLYSOHOTR=On -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
COMMENT "Generating soh.otr..."
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
COMMENT "Generating soh.o2r..."
DEPENDS ZAPD
)
@ -267,22 +258,12 @@ add_custom_target(CreateOSXIcons
)
add_dependencies(soh CreateOSXIcons)
install(TARGETS ZAPD DESTINATION ${CMAKE_BINARY_DIR}/assets/extractor)
install(TARGETS ZAPD DESTINATION ${CMAKE_BINARY_DIR}/assets)
set(PROGRAM_PERMISSIONS_EXECUTE OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
install(DIRECTORY ${CMAKE_BINARY_DIR}/assets
DESTINATION .
PATTERN ZAPD.out
PERMISSIONS ${PROGRAM_PERMISSIONS_EXECUTE}
)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml)
# Rename the installed soh binary to drop the macos suffix
INSTALL(CODE "FILE(RENAME \${CMAKE_INSTALL_PREFIX}/../MacOS/soh-macos \${CMAKE_INSTALL_PREFIX}/../MacOS/soh)")

@ -1 +1 @@
Subproject commit 41052efcdf8df8e67517cc93da8975fcd4e14af9
Subproject commit 461ab19a36cde807591543397e136cae19aa6e7c

2
ZAPDTR

@ -1 +1 @@
Subproject commit 2aeababbfb81b00d34673406453e8e8e2deaa27b
Subproject commit 684f21a475dcfeee89938ae1f4afc42768a3e7ef

View file

@ -1,37 +1,37 @@
message(STATUS "Copying otr files...")
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot.otr)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${BINARY_DIR}/soh/)
message(STATUS "Copied oot.otr")
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot.o2r)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${BINARY_DIR}/soh/)
message(STATUS "Copied oot.o2r")
endif()
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot-mq.otr)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${BINARY_DIR}/soh/)
message(STATUS "Copied oot-mq.otr")
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot-mq.o2r)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${BINARY_DIR}/soh/)
message(STATUS "Copied oot-mq.o2r")
endif()
if(EXISTS ${SOURCE_DIR}/OTRExporter/soh.otr)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${BINARY_DIR}/soh/)
message(STATUS "Copied soh.otr")
if(EXISTS ${SOURCE_DIR}/soh/soh.o2r)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${BINARY_DIR}/soh/)
message(STATUS "Copied soh.o2r")
endif()
# Additionally for Windows, copy the otrs to the target dir, side by side with soh.exe
if(SYSTEM_NAME MATCHES "Windows")
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot.otr)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${TARGET_DIR})
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot.o2r)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${TARGET_DIR})
endif()
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot-mq.otr)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${TARGET_DIR})
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot-mq.o2r)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${TARGET_DIR})
endif()
if(EXISTS ${SOURCE_DIR}/OTRExporter/soh.otr)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${TARGET_DIR})
if(EXISTS ${SOURCE_DIR}/soh/soh.o2r)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${TARGET_DIR})
endif()
endif()
if(NOT ONLYSOHOTR AND (NOT EXISTS ${SOURCE_DIR}/oot.otr AND NOT EXISTS ${SOURCE_DIR}/oot-mq.otr))
if(NOT ONLYSOHOTR AND (NOT EXISTS ${SOURCE_DIR}/oot.o2r AND NOT EXISTS ${SOURCE_DIR}/oot-mq.o2r))
message(FATAL_ERROR "Failed to copy. No OTR files found.")
endif()
if(NOT EXISTS ${SOURCE_DIR}/soh.otr)
if(NOT EXISTS ${SOURCE_DIR}/soh.o2r)
message(FATAL_ERROR "Failed to copy. No soh OTR found.")
endif()

View file

@ -90,26 +90,26 @@ C:\Program Files\CMake\bin\cmake.exe --build build-cmake --target ExtractAssetHe
#### Debian/Ubuntu
```sh
# using gcc
apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev
apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libopengl-dev
# or using clang
apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev
apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libopengl-dev
```
#### Arch
```sh
# using gcc
pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost
pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net
# or using clang
pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost
pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net
```
#### Fedora
```sh
# using gcc
dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel
dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel
# or using clang
dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel
dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel
```
#### openSUSE
```sh

View file

@ -1,7 +1,7 @@
[Desktop Entry]
Version=1.0
Name=SOH
Exec=soh.sh
Exec=soh.elf
Terminal=false
Icon=sohIcon
Type=Application

View file

@ -1,338 +0,0 @@
#!/bin/bash
HERE="$(dirname "$(readlink -f "${0}")")"/../..
export PATH="$HERE"/bin:"$HERE"/usr/bin:"$PATH"
export LD_LIBRARY_PATH="$HERE"/usr/lib:"$LD_LIBRARY_PATH"
export ZENITY=$(command -v zenity)
if [ -z ${SHIP_HOME+x} ]; then
export SHIP_HOME=$PWD
fi
if [ -z ${SHIP_BIN_DIR+x} ]; then
export SHIP_BIN_DIR="$HERE/usr/bin"
fi
if [[ ! -e "$SHIP_HOME"/mods ]]; then
mkdir -p "$SHIP_HOME"/mods
touch "$SHIP_HOME"/mods/custom_otr_files_go_here.txt
fi
while [[ (! -e "$SHIP_HOME"/oot.otr) || (! -e "$SHIP_HOME"/oot-mq.otr) ]]; do
for romfile in "$SHIP_HOME"/*.*64
do
if [[ -e "$romfile" ]] || [[ -L "$romfile" ]]; then
export ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)"
ln -s "$SHIP_BIN_DIR"/{assets,soh.elf,ZAPD} "$ASSETDIR"
export OLDPWD="$PWD"
mkdir -p "$ASSETDIR"/tmp
if [[ -e "$romfile" ]]; then
ln -s "$romfile" "$ASSETDIR"/tmp/rom.z64
else
ORIG_ROM_PATH=$(readlink "$romfile")
ln -s "$ORIG_ROM_PATH" "$ASSETDIR"/tmp/rom.z64
fi
cd "$ASSETDIR"
ROMHASH=$(sha1sum -b "$ASSETDIR"/tmp/rom.z64 | awk '{ print $1 }')
# Remap v64 and n64 hashes to their z64 hash equivalent
# ZAPD will handle converting the data into z64 format
case "$ROMHASH" in
a9059b56e761c9034fbe02fe4c24985aaa835dac) # v64
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
;;
24708102dc504d3f375a37f4ae4e149c167dc515) # n64
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
;;
580dd0bd1b6d2c51cc20a764eece84dba558964c) # v64
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
;;
d6342c59007e57c1194661ec6880b2f078403f4e) # n64
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
;;
d0bdc2eb320668b4ba6893b9aefe4040a73123ff) # v64
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
;;
4946ab250f6ac9b32d76b21f309ebb8ebc8103d2) # n64
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
;;
663c34f1b2c05a09e5beffe4d0dcd440f7d49dc7) # v64
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
;;
24c73d378b0620a380ce5ef9f2b186c6c157a68b) # n64
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
;;
8ebf2e29313f44f2d49e5b4191971d09919e8e48) # v64
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
;;
4264bf7b875737b8fae77d52322a5099d051fc11) # n64
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
;;
973bc6fe56010a8d646166a1182a81b4f13b8cf9) # v64
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
;;
d327752c46edc70ff3668b9514083dbbee08927c) # v64
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
;;
ecdeb1747560834e079c22243febea7f6f26ba3b) # v64
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
;;
f19f8662ec7abee29484a272a6fda53e39efe0f1) # n64
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
;;
ab519ce04a33818ce2c39b3c514a751d807a494a) # v64
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
;;
c19a34f7646305e1755249fca2071e178bd7cd00) # n64
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
;;
25e8ae79ea0839ca5c984473f7460d8040c36f9c) # v64
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
;;
166c02770d67fcc3954c443eb400a6a3573d3fc0) # n64
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
;;
79a4f053d34018e59279e6d4b83c7daccd985c87) # v64
ROMHASH=ad69c91157f6705e8ab06c79fe08aad47bb57ba7
;;
82fafee9c6ac7946739282958364ce606077ac65) # n64
ROMHASH=ad69c91157f6705e8ab06c79fe08aad47bb57ba7
;;
18cd0eb65914a21d8fa08dfe71c29d865e9d728a) # v64
ROMHASH=d3ecb253776cd847a5aa63d859d8c89a2f37b364
;;
07940d5609e04b7caac63570731e01189129212e) # n64
ROMHASH=d3ecb253776cd847a5aa63d859d8c89a2f37b364
;;
3ac86253e0c0d55486d212e647350c1527b9c92d) # v64
ROMHASH=41b3bdc48d98c48529219919015a1af22f5057c2
;;
70bf30a9980026e615a1ae8d2735a773cf9fcc94) # n64
ROMHASH=41b3bdc48d98c48529219919015a1af22f5057c2
;;
f9e2b6840b9103e9707ea390089a7b6943592a98) # v64
ROMHASH=c892bbda3993e66bd0d56a10ecd30b1ee612210f
;;
2fae1601aa7ae8d3e03ba3f4dcdfca3a36002ac5) # n64
ROMHASH=c892bbda3993e66bd0d56a10ecd30b1ee612210f
;;
1181034d5f9533f53ebe8e1c781badbee115f5aa) # v64
ROMHASH=dbfc81f655187dc6fefd93fa6798face770d579d
;;
07477067943abe8d0c50285eb4a6cb9ece99e79b) # n64
ROMHASH=dbfc81f655187dc6fefd93fa6798face770d579d
;;
2d8fb7140a9c5d11ce614561e5a36ffef0c17540) # v64
ROMHASH=fa5f5942b27480d60243c2d52c0e93e26b9e6b86
;;
d90bbe422ac728ac54ac6a2c9fec942f7ff04df9) # n64
ROMHASH=fa5f5942b27480d60243c2d52c0e93e26b9e6b86
;;
44c75962911e13bdfdc31b35e0b8e3be6a6a49ab) # v64
b82710ba2bd3b4c6ee8aa1a7e9acf787dfc72e9b
;;
5d47025581060af5ba19e6719c25fea7398e87cf) # n64
b82710ba2bd3b4c6ee8aa1a7e9acf787dfc72e9b
;;
e1d070ad7b017de9f992b362164dcd9d7f820f7e) # v64
8b5d13aac69bfbf989861cfdc50b1d840945fc1d
;;
a8c04cd5aa94a6a32198f36ff2069d43342d18a8) # n64
8b5d13aac69bfbf989861cfdc50b1d840945fc1d
;;
245410280d152f28d5b1c0c0fc37f384db0020cd) # v64
0769c84615422d60f16925cd859593cdfa597f84
;;
fbdc9e444807f9b881e3432cedf66f38746b81d8) # n64
0769c84615422d60f16925cd859593cdfa597f84
;;
b6d33d6bf5d6700c64b6a873ab8b06ff039619bc) # v64
2ce2d1a9f0534c9cd9fa04ea5317b80da21e5e73
;;
2c7113d20044f93c82ec888c19aa09ea7797396d) # n64
2ce2d1a9f0534c9cd9fa04ea5317b80da21e5e73
;;
06c3c098f0e14ed61811dfaf0e8e4519d7d7a826) # v64
dd14e143c4275861fe93ea79d0c02e36ae8c6c2f
;;
bb3f85bfaad9ae7a20afbf618fc9fe126c8c1b4f) # n64
dd14e143c4275861fe93ea79d0c02e36ae8c6c2f
;;
esac
case "$ROMHASH" in
cee6bc3c2a634b41728f2af8da54d9bf8cc14099)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=GC_NMQ_D
OTRNAME="oot.otr"
fi
;;
0227d7c0074f2d0ac935631990da8ec5914597b4)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=GC_NMQ_PAL_F
OTRNAME="oot.otr"
else
continue
fi
;;
328a1f1beba30ce5e178f031662019eb32c5f3b5)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=N64_PAL_10
OTRNAME="oot.otr"
else
continue
fi
;;
cfbb98d392e4a9d39da8285d10cbef3974c2f012)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=N64_PAL_11
OTRNAME="oot.otr"
else
continue
fi
;;
ad69c91157f6705e8ab06c79fe08aad47bb57ba7|c892bbda3993e66bd0d56a10ecd30b1ee612210f)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=N64_NTSC_10
OTRNAME="oot.otr"
else
continue
fi
;;
d3ecb253776cd847a5aa63d859d8c89a2f37b364|dbfc81f655187dc6fefd93fa6798face770d579d)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=N64_NTSC_11
OTRNAME="oot.otr"
else
continue
fi
;;
41b3bdc48d98c48529219919015a1af22f5057c2|fa5f5942b27480d60243c2d52c0e93e26b9e6b86)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=N64_NTSC_12
OTRNAME="oot.otr"
else
continue
fi
;;
f46239439f59a2a594ef83cf68ef65043b1bffe2)
if [[ ! -e "$SHIP_HOME"/oot-mq.otr ]]; then
ROM=GC_MQ_PAL_F
OTRNAME="oot-mq.otr"
else
continue
fi
;;
50bebedad9e0f10746a52b07239e47fa6c284d03)
if [[ ! -e "$SHIP_HOME"/oot-mq.otr ]]; then
ROM=GC_MQ_D
OTRNAME="oot-mq.otr"
else
continue
fi
;;
079b855b943d6ad8bd1eb026c0ed169ecbdac7da)
if [[ ! -e "$SHIP_HOME"/oot-mq.otr ]]; then
ROM=GC_MQ_D
OTRNAME="oot-mq.otr"
else
continue
fi
;;
cfecfdc58d650e71a200c81f033de4e6d617a9f6)
if [[ ! -e "$SHIP_HOME"/oot-mq.otr ]]; then
ROM=GC_MQ_D
OTRNAME="oot-mq.otr"
else
continue
fi
;;
517bd9714c73cb96c21e7c2ef640d7b55186102f)
if [[ ! -e "$SHIP_HOME"/oot-mq.otr ]]; then
ROM=GC_MQ_D
OTRNAME="oot-mq.otr"
else
continue
fi
;;
b82710ba2bd3b4c6ee8aa1a7e9acf787dfc72e9b)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=GC_NMQ_NTSC_U
OTRNAME="oot.otr"
else
continue
fi
;;
8b5d13aac69bfbf989861cfdc50b1d840945fc1d)
if [[ ! -e "$SHIP_HOME"/oot-mq.otr ]]; then
ROM=GC_MQ_NTSC_U
OTRNAME="oot-mq.otr"
else
continue
fi
;;
0769c84615422d60f16925cd859593cdfa597f84)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=GC_NMQ_NTSC_J
OTRNAME="oot.otr"
else
continue
fi
;;
2ce2d1a9f0534c9cd9fa04ea5317b80da21e5e73)
if [[ ! -e "$SHIP_HOME"/oot.otr ]]; then
ROM=GC_NMQ_NTSC_J_CE
OTRNAME="oot.otr"
else
continue
fi
;;
dd14e143c4275861fe93ea79d0c02e36ae8c6c2f)
if [[ ! -e "$SHIP_HOME"/oot-mq.otr ]]; then
ROM=GC_MQ_NTSC_J
OTRNAME="oot-mq.otr"
else
continue
fi
;;
*)
echo -e "\n$romfile - $ROMHASH rom hash does not match\n"
continue;;
esac
if [[ ! -e "$SHIP_HOME"/"$OTRNAME" ]]; then
if [ -n "$ZENITY" ]; then
(echo "# 25%"; echo "25"; sleep 2; echo "# 50%"; echo "50"; sleep 3; echo "# 75%"; echo "75"; sleep 2; echo "# 100%"; echo "100"; sleep 3) |
zenity --progress --title="OTR Generating..." --timeout=10 --percentage=0 --icon-name=soh --window-icon=soh.png --height=80 --width=400 &
else
echo "Processing..."
fi
assets/extractor/ZAPD.out ed -eh -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR --otrfile "${OTRNAME}" --portVer "@CMAKE_PROJECT_VERSION@" > /dev/null 2>&1
cp "$ASSETDIR"/"$OTRNAME" "$SHIP_HOME"
fi
else
if [[ (! -e "$SHIP_HOME"/oot.otr) && (! -e "$SHIP_HOME"/oot-mq.otr) ]]; then
if [ -n "$ZENITY" ]; then
zenity --error --timeout=5 --text="Place ROM in $SHIP_HOME" --title="Missing ROM file" --width=500 --width=200
else
echo -e "\nPlace ROM in this folder\n"
fi
exit
fi
fi
done
if [[ (! -e "$SHIP_HOME"/oot.otr) && (! -e "$SHIP_HOME"/oot-mq.otr) ]]; then
if [ -n "$ZENITY" ]; then
zenity --error --timeout=10 --text="No valid ROMs were provided, No OTR was generated." --title="Incorrect ROM file" --width=500 --width=200
else
echo "No valid roms provided, no OTR was generated."
fi
rm -r "$ASSETDIR"
exit
else
(cd "$SHIP_BIN_DIR"; ./soh.elf)
exit
fi
rm -r "$ASSETDIR"
done
(cd "$SHIP_BIN_DIR"; ./soh.elf)
exit

View file

@ -138,20 +138,27 @@ endforeach()
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set_source_files_properties(soh/OTRGlobals.cpp PROPERTIES COMPILE_FLAGS "/utf-8")
set_source_files_properties(soh/Enhancements/tts/tts.cpp PROPERTIES COMPILE_FLAGS "/utf-8")
set_source_files_properties(soh/Enhancements/custom-message/CustomMessageManager.cpp PROPERTIES COMPILE_FLAGS "/utf-8")
set_source_files_properties(soh/Enhancements/custom-message/CustomMessageManager.h PROPERTIES COMPILE_FLAGS "/utf-8")
endif()
# handle Network removals
if (!BUILD_REMOTE_CONTROL)
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/crowd-control/*")
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/crowd-control/")
endif()
# handle speechsynthesizer removals
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/Darwin*")
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/Darwin")
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/SAPI*")
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/SAPI")
else()
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/(Darwin|SAPI).*")
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/(Darwin|SAPI)")
endif()
find_library(ESPEAK espeak-ng)
if (NOT ESPEAK)
list(FILTER soh__ EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/ESpeak")
endif()
# handle accessible audio engine removals
@ -182,12 +189,12 @@ file(GLOB_RECURSE src__ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.c" "src/*.h"
set_source_files_properties(${src__} PROPERTIES COMPILE_OPTIONS "${WARNING_OVERRIDE}")
list(APPEND src__ ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc)
list(FILTER src__ EXCLUDE REGEX "src/dmadata/*")
list(FILTER src__ EXCLUDE REGEX "src/elf_message/*")
list(FILTER src__ EXCLUDE REGEX "src/libultra/io/*")
list(FILTER src__ EXCLUDE REGEX "src/libultra/libc/*")
list(FILTER src__ EXCLUDE REGEX "src/libultra/os/*")
list(FILTER src__ EXCLUDE REGEX "src/libultra/rmon/*")
list(FILTER src__ EXCLUDE REGEX "src/dmadata/")
list(FILTER src__ EXCLUDE REGEX "src/elf_message/")
list(FILTER src__ EXCLUDE REGEX "src/libultra/io/")
list(FILTER src__ EXCLUDE REGEX "src/libultra/libc/")
list(FILTER src__ EXCLUDE REGEX "src/libultra/os/")
list(FILTER src__ EXCLUDE REGEX "src/libultra/rmon/")
list(APPEND src__ "src/libultra/libc/sprintf.c")
list(REMOVE_ITEM src__ "src/libultra/gu/cosf.c")
list(REMOVE_ITEM src__ "src/libultra/gu/lookat.c")
@ -281,32 +288,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set_target_properties(${PROJECT_NAME} PROPERTIES MSVC_RUNTIME_LIBRARY ${MSVC_RUNTIME_LIBRARY_STR})
endif()
################################################################################
# Find/download Boost
################################################################################
include(FetchContent)
FetchContent_Declare(
Boost
URL https://archives.boost.io/release/1.81.0/source/boost_1_81_0.tar.gz
URL_HASH SHA256=205666dea9f6a7cfed87c7a6dfbeb52a2c1b9de55712c9c1a87735d7181452b6
SOURCE_SUBDIR "null" # Set to a nonexistent directory so boost is not built (we don't need to build it)
DOWNLOAD_EXTRACT_TIMESTAMP false # supress timestamp warning, not needed since the url wont change
)
set(Boost_NO_BOOST_CMAKE false)
set(BOOST_INCLUDEDIR ${FETCHCONTENT_BASE_DIR}/boost-src) # Location where FetchContent stores the source
message("Searching for Boost installation")
find_package(Boost)
if (NOT ${Boost_FOUND})
message("Boost not found. Downloading now...")
FetchContent_MakeAvailable(Boost)
message("Boost downloaded to " ${FETCHCONTENT_BASE_DIR}/boost-src)
set(BOOST-INCLUDE ${FETCHCONTENT_BASE_DIR}/boost-src)
else()
message("Boost found in " ${Boost_INCLUDE_DIRS})
set(BOOST-INCLUDE ${Boost_INCLUDE_DIRS})
endif()
################################################################################
# Compile definitions
################################################################################
find_package(SDL2)
@ -323,6 +304,10 @@ if (BUILD_REMOTE_CONTROL)
endif()
endif()
if (ESPEAK)
add_compile_definitions(ESPEAK=1)
endif()
target_include_directories(${PROJECT_NAME} PRIVATE assets
${CMAKE_CURRENT_SOURCE_DIR}/include/
${CMAKE_CURRENT_SOURCE_DIR}/src/
@ -354,7 +339,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets
${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD/resource/type
${SDL2-INCLUDE}
${SDL2-NET-INCLUDE}
${BOOST-INCLUDE}
${CMAKE_CURRENT_SOURCE_DIR}/assets/
.
)
@ -615,21 +599,22 @@ endif()
# Pre build events
################################################################################
if (CMAKE_GENERATOR MATCHES "Visual Studio")
set(VS_COPY_ASSETS_CMD ${CMAKE_COMMAND} -E copy_directory_if_different $<TARGET_FILE_DIR:soh>/assets ${CMAKE_BINARY_DIR}/soh/assets)
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/extractor ${CMAKE_BINARY_DIR}/soh/assets
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/xml ${CMAKE_BINARY_DIR}/soh/assets/xml
)
endif()
if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMENT "Copying asset xmls..."
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/extractor $<TARGET_FILE_DIR:soh>/assets/extractor
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/xml $<TARGET_FILE_DIR:soh>/assets/extractor/xmls
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists $<TARGET_FILE_DIR:soh>/assets/extractor/filelists
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
COMMAND ${VS_COPY_ASSETS_CMD}
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/extractor $<TARGET_FILE_DIR:soh>/assets
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/xml $<TARGET_FILE_DIR:soh>/assets/xml
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:soh>/assets/symbols
# COMMAND ${VS_COPY_ASSETS_CMD}
)
endif()
################################################################################
@ -715,11 +700,7 @@ endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
INSTALL(FILES $<TARGET_PDB_FILE:soh> DESTINATION ./debug COMPONENT ship)
INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.otr DESTINATION . COMPONENT ship)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/appimage/soh.sh.in ${CMAKE_BINARY_DIR}/linux/soh.sh @ONLY)
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.")
@ -729,7 +710,7 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/macosx/Info.plist.in ${CMAKE_BINARY_DIR}/macosx/Info.plist @ONLY)
INSTALL(TARGETS soh DESTINATION ../MacOS COMPONENT ship)
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION ../MacOS COMPONENT ship)
INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.otr DESTINATION ../Resources COMPONENT ship)
INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.o2r DESTINATION ../Resources COMPONENT ship)
elseif(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "NintendoSwitch|CafeOS")
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship)
endif()

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_D/"/>
<ExternalXMLFolder Path="assets/xml/GC_MQ_D/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_NTSC_J/"/>
<ExternalXMLFolder Path="assets/xml/GC_MQ_NTSC_J/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_NTSC_U/"/>
<ExternalXMLFolder Path="assets/xml/GC_MQ_NTSC_U/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_PAL_F/"/>
<ExternalXMLFolder Path="assets/xml/GC_MQ_PAL_F/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_D/"/>
<ExternalXMLFolder Path="assets/xml/GC_NMQ_D/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_J/"/>
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_J/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_J_CE/"/>
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_J_CE/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_U/"/>
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_U/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_PAL_F/"/>
<ExternalXMLFolder Path="assets/xml/GC_NMQ_PAL_F/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/N64_NTSC_10/"/>
<ExternalXMLFolder Path="assets/xml/N64_NTSC_10/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/N64_NTSC_11/"/>
<ExternalXMLFolder Path="assets/xml/N64_NTSC_11/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/N64_NTSC_12/"/>
<ExternalXMLFolder Path="assets/xml/N64_NTSC_12/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/N64_PAL_10/"/>
<ExternalXMLFolder Path="assets/xml/N64_PAL_10/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View file

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/N64_PAL_11/"/>
<ExternalXMLFolder Path="assets/xml/N64_PAL_11/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,472 @@
ACTOR_PLAYER
ACTOR_UNSET_1
ACTOR_EN_TEST
ACTOR_UNSET_3
ACTOR_EN_GIRLA
ACTOR_UNSET_5
ACTOR_UNSET_6
ACTOR_EN_PART
ACTOR_EN_LIGHT
ACTOR_EN_DOOR
ACTOR_EN_BOX
ACTOR_BG_DY_YOSEIZO
ACTOR_BG_HIDAN_FIREWALL
ACTOR_EN_POH
ACTOR_EN_OKUTA
ACTOR_BG_YDAN_SP
ACTOR_EN_BOM
ACTOR_EN_WALLMAS
ACTOR_EN_DODONGO
ACTOR_EN_FIREFLY
ACTOR_EN_HORSE
ACTOR_EN_ITEM00
ACTOR_EN_ARROW
ACTOR_UNSET_17
ACTOR_EN_ELF
ACTOR_EN_NIW
ACTOR_UNSET_1A
ACTOR_EN_TITE
ACTOR_EN_REEBA
ACTOR_EN_PEEHAT
ACTOR_EN_BUTTE
ACTOR_UNSET_1F
ACTOR_EN_INSECT
ACTOR_EN_FISH
ACTOR_UNSET_22
ACTOR_EN_HOLL
ACTOR_EN_SCENE_CHANGE
ACTOR_EN_ZF
ACTOR_EN_HATA
ACTOR_BOSS_DODONGO
ACTOR_BOSS_GOMA
ACTOR_EN_ZL1
ACTOR_EN_VIEWER
ACTOR_EN_GOMA
ACTOR_BG_PUSHBOX
ACTOR_EN_BUBBLE
ACTOR_DOOR_SHUTTER
ACTOR_EN_DODOJR
ACTOR_EN_BDFIRE
ACTOR_UNSET_31
ACTOR_EN_BOOM
ACTOR_EN_TORCH2
ACTOR_EN_BILI
ACTOR_EN_TP
ACTOR_UNSET_36
ACTOR_EN_ST
ACTOR_EN_BW
ACTOR_EN_A_OBJ
ACTOR_EN_EIYER
ACTOR_EN_RIVER_SOUND
ACTOR_EN_HORSE_NORMAL
ACTOR_EN_OSSAN
ACTOR_BG_TREEMOUTH
ACTOR_BG_DODOAGO
ACTOR_BG_HIDAN_DALM
ACTOR_BG_HIDAN_HROCK
ACTOR_EN_HORSE_GANON
ACTOR_BG_HIDAN_ROCK
ACTOR_BG_HIDAN_RSEKIZOU
ACTOR_BG_HIDAN_SEKIZOU
ACTOR_BG_HIDAN_SIMA
ACTOR_BG_HIDAN_SYOKU
ACTOR_EN_XC
ACTOR_BG_HIDAN_CURTAIN
ACTOR_BG_SPOT00_HANEBASI
ACTOR_EN_MB
ACTOR_EN_BOMBF
ACTOR_EN_ZL2
ACTOR_BG_HIDAN_FSLIFT
ACTOR_EN_OE2
ACTOR_BG_YDAN_HASI
ACTOR_BG_YDAN_MARUTA
ACTOR_BOSS_GANONDROF
ACTOR_UNSET_53
ACTOR_EN_AM
ACTOR_EN_DEKUBABA
ACTOR_EN_M_FIRE1
ACTOR_EN_M_THUNDER
ACTOR_BG_DDAN_JD
ACTOR_BG_BREAKWALL
ACTOR_EN_JJ
ACTOR_EN_HORSE_ZELDA
ACTOR_BG_DDAN_KD
ACTOR_DOOR_WARP1
ACTOR_OBJ_SYOKUDAI
ACTOR_ITEM_B_HEART
ACTOR_EN_DEKUNUTS
ACTOR_BG_MENKURI_KAITEN
ACTOR_BG_MENKURI_EYE
ACTOR_EN_VALI
ACTOR_BG_MIZU_MOVEBG
ACTOR_BG_MIZU_WATER
ACTOR_ARMS_HOOK
ACTOR_EN_FHG
ACTOR_BG_MORI_HINERI
ACTOR_EN_BB
ACTOR_BG_TOKI_HIKARI
ACTOR_EN_YUKABYUN
ACTOR_BG_TOKI_SWD
ACTOR_EN_FHG_FIRE
ACTOR_BG_MJIN
ACTOR_BG_HIDAN_KOUSI
ACTOR_DOOR_TOKI
ACTOR_BG_HIDAN_HAMSTEP
ACTOR_EN_BIRD
ACTOR_UNSET_73
ACTOR_UNSET_74
ACTOR_UNSET_75
ACTOR_UNSET_76
ACTOR_EN_WOOD02
ACTOR_UNSET_78
ACTOR_UNSET_79
ACTOR_UNSET_7A
ACTOR_UNSET_7B
ACTOR_EN_LIGHTBOX
ACTOR_EN_PU_BOX
ACTOR_UNSET_7E
ACTOR_UNSET_7F
ACTOR_EN_TRAP
ACTOR_EN_AROW_TRAP
ACTOR_EN_VASE
ACTOR_UNSET_83
ACTOR_EN_TA
ACTOR_EN_TK
ACTOR_BG_MORI_BIGST
ACTOR_BG_MORI_ELEVATOR
ACTOR_BG_MORI_KAITENKABE
ACTOR_BG_MORI_RAKKATENJO
ACTOR_EN_VM
ACTOR_DEMO_EFFECT
ACTOR_DEMO_KANKYO
ACTOR_BG_HIDAN_FWBIG
ACTOR_EN_FLOORMAS
ACTOR_EN_HEISHI1
ACTOR_EN_RD
ACTOR_EN_PO_SISTERS
ACTOR_BG_HEAVY_BLOCK
ACTOR_BG_PO_EVENT
ACTOR_OBJ_MURE
ACTOR_EN_SW
ACTOR_BOSS_FD
ACTOR_OBJECT_KANKYO
ACTOR_EN_DU
ACTOR_EN_FD
ACTOR_EN_HORSE_LINK_CHILD
ACTOR_DOOR_ANA
ACTOR_BG_SPOT02_OBJECTS
ACTOR_BG_HAKA
ACTOR_MAGIC_WIND
ACTOR_MAGIC_FIRE
ACTOR_UNSET_A0
ACTOR_EN_RU1
ACTOR_BOSS_FD2
ACTOR_EN_FD_FIRE
ACTOR_EN_DH
ACTOR_EN_DHA
ACTOR_EN_RL
ACTOR_EN_ENCOUNT1
ACTOR_DEMO_DU
ACTOR_DEMO_IM
ACTOR_DEMO_TRE_LGT
ACTOR_EN_FW
ACTOR_BG_VB_SIMA
ACTOR_EN_VB_BALL
ACTOR_BG_HAKA_MEGANE
ACTOR_BG_HAKA_MEGANEBG
ACTOR_BG_HAKA_SHIP
ACTOR_BG_HAKA_SGAMI
ACTOR_UNSET_B2
ACTOR_EN_HEISHI2
ACTOR_EN_ENCOUNT2
ACTOR_EN_FIRE_ROCK
ACTOR_EN_BROB
ACTOR_MIR_RAY
ACTOR_BG_SPOT09_OBJ
ACTOR_BG_SPOT18_OBJ
ACTOR_BOSS_VA
ACTOR_BG_HAKA_TUBO
ACTOR_BG_HAKA_TRAP
ACTOR_BG_HAKA_HUTA
ACTOR_BG_HAKA_ZOU
ACTOR_BG_SPOT17_FUNEN
ACTOR_EN_SYATEKI_ITM
ACTOR_EN_SYATEKI_MAN
ACTOR_EN_TANA
ACTOR_EN_NB
ACTOR_BOSS_MO
ACTOR_EN_SB
ACTOR_EN_BIGOKUTA
ACTOR_EN_KAREBABA
ACTOR_BG_BDAN_OBJECTS
ACTOR_DEMO_SA
ACTOR_DEMO_GO
ACTOR_EN_IN
ACTOR_EN_TR
ACTOR_BG_SPOT16_BOMBSTONE
ACTOR_UNSET_CE
ACTOR_BG_HIDAN_KOWARERUKABE
ACTOR_BG_BOMBWALL
ACTOR_BG_SPOT08_ICEBLOCK
ACTOR_EN_RU2
ACTOR_OBJ_DEKUJR
ACTOR_BG_MIZU_UZU
ACTOR_BG_SPOT06_OBJECTS
ACTOR_BG_ICE_OBJECTS
ACTOR_BG_HAKA_WATER
ACTOR_UNSET_D8
ACTOR_EN_MA2
ACTOR_EN_BOM_CHU
ACTOR_EN_HORSE_GAME_CHECK
ACTOR_BOSS_TW
ACTOR_EN_RR
ACTOR_EN_BA
ACTOR_EN_BX
ACTOR_EN_ANUBICE
ACTOR_EN_ANUBICE_FIRE
ACTOR_BG_MORI_HASHIGO
ACTOR_BG_MORI_HASHIRA4
ACTOR_BG_MORI_IDOMIZU
ACTOR_BG_SPOT16_DOUGHNUT
ACTOR_BG_BDAN_SWITCH
ACTOR_EN_MA1
ACTOR_BOSS_GANON
ACTOR_BOSS_SST
ACTOR_UNSET_EA
ACTOR_UNSET_EB
ACTOR_EN_NY
ACTOR_EN_FR
ACTOR_ITEM_SHIELD
ACTOR_BG_ICE_SHELTER
ACTOR_EN_ICE_HONO
ACTOR_ITEM_OCARINA
ACTOR_UNSET_F2
ACTOR_UNSET_F3
ACTOR_MAGIC_DARK
ACTOR_DEMO_6K
ACTOR_EN_ANUBICE_TAG
ACTOR_BG_HAKA_GATE
ACTOR_BG_SPOT15_SAKU
ACTOR_BG_JYA_GOROIWA
ACTOR_BG_JYA_ZURERUKABE
ACTOR_UNSET_FB
ACTOR_BG_JYA_COBRA
ACTOR_BG_JYA_KANAAMI
ACTOR_FISHING
ACTOR_OBJ_OSHIHIKI
ACTOR_BG_GATE_SHUTTER
ACTOR_EFF_DUST
ACTOR_BG_SPOT01_FUSYA
ACTOR_BG_SPOT01_IDOHASHIRA
ACTOR_BG_SPOT01_IDOMIZU
ACTOR_BG_PO_SYOKUDAI
ACTOR_BG_GANON_OTYUKA
ACTOR_BG_SPOT15_RRBOX
ACTOR_BG_UMAJUMP
ACTOR_UNSET_109
ACTOR_ARROW_FIRE
ACTOR_ARROW_ICE
ACTOR_ARROW_LIGHT
ACTOR_UNSET_10D
ACTOR_UNSET_10E
ACTOR_ITEM_ETCETERA
ACTOR_OBJ_KIBAKO
ACTOR_OBJ_TSUBO
ACTOR_EN_WONDER_ITEM
ACTOR_EN_IK
ACTOR_DEMO_IK
ACTOR_EN_SKJ
ACTOR_EN_SKJNEEDLE
ACTOR_EN_G_SWITCH
ACTOR_DEMO_EXT
ACTOR_DEMO_SHD
ACTOR_EN_DNS
ACTOR_ELF_MSG
ACTOR_EN_HONOTRAP
ACTOR_EN_TUBO_TRAP
ACTOR_OBJ_ICE_POLY
ACTOR_BG_SPOT03_TAKI
ACTOR_BG_SPOT07_TAKI
ACTOR_EN_FZ
ACTOR_EN_PO_RELAY
ACTOR_BG_RELAY_OBJECTS
ACTOR_EN_DIVING_GAME
ACTOR_EN_KUSA
ACTOR_OBJ_BEAN
ACTOR_OBJ_BOMBIWA
ACTOR_UNSET_128
ACTOR_UNSET_129
ACTOR_OBJ_SWITCH
ACTOR_OBJ_ELEVATOR
ACTOR_OBJ_LIFT
ACTOR_OBJ_HSBLOCK
ACTOR_EN_OKARINA_TAG
ACTOR_EN_YABUSAME_MARK
ACTOR_EN_GOROIWA
ACTOR_EN_EX_RUPPY
ACTOR_EN_TORYO
ACTOR_EN_DAIKU
ACTOR_UNSET_134
ACTOR_EN_NWC
ACTOR_EN_BLKOBJ
ACTOR_ITEM_INBOX
ACTOR_EN_GE1
ACTOR_OBJ_BLOCKSTOP
ACTOR_EN_SDA
ACTOR_EN_CLEAR_TAG
ACTOR_EN_NIW_LADY
ACTOR_EN_GM
ACTOR_EN_MS
ACTOR_EN_HS
ACTOR_BG_INGATE
ACTOR_EN_KANBAN
ACTOR_EN_HEISHI3
ACTOR_EN_SYATEKI_NIW
ACTOR_EN_ATTACK_NIW
ACTOR_BG_SPOT01_IDOSOKO
ACTOR_EN_SA
ACTOR_EN_WONDER_TALK
ACTOR_BG_GJYO_BRIDGE
ACTOR_EN_DS
ACTOR_EN_MK
ACTOR_EN_BOM_BOWL_MAN
ACTOR_EN_BOM_BOWL_PIT
ACTOR_EN_OWL
ACTOR_EN_ISHI
ACTOR_OBJ_HANA
ACTOR_OBJ_LIGHTSWITCH
ACTOR_OBJ_MURE2
ACTOR_EN_GO
ACTOR_EN_FU
ACTOR_UNSET_154
ACTOR_EN_CHANGER
ACTOR_BG_JYA_MEGAMI
ACTOR_BG_JYA_LIFT
ACTOR_BG_JYA_BIGMIRROR
ACTOR_BG_JYA_BOMBCHUIWA
ACTOR_BG_JYA_AMISHUTTER
ACTOR_BG_JYA_BOMBIWA
ACTOR_BG_SPOT18_BASKET
ACTOR_UNSET_15D
ACTOR_EN_GANON_ORGAN
ACTOR_EN_SIOFUKI
ACTOR_EN_STREAM
ACTOR_UNSET_161
ACTOR_EN_MM
ACTOR_EN_KO
ACTOR_EN_KZ
ACTOR_EN_WEATHER_TAG
ACTOR_BG_SST_FLOOR
ACTOR_EN_ANI
ACTOR_EN_EX_ITEM
ACTOR_BG_JYA_IRONOBJ
ACTOR_EN_JS
ACTOR_EN_JSJUTAN
ACTOR_EN_CS
ACTOR_EN_MD
ACTOR_EN_HY
ACTOR_EN_GANON_MANT
ACTOR_EN_OKARINA_EFFECT
ACTOR_EN_MAG
ACTOR_DOOR_GERUDO
ACTOR_ELF_MSG2
ACTOR_DEMO_GT
ACTOR_EN_PO_FIELD
ACTOR_EFC_ERUPC
ACTOR_BG_ZG
ACTOR_EN_HEISHI4
ACTOR_EN_ZL3
ACTOR_BOSS_GANON2
ACTOR_EN_KAKASI
ACTOR_EN_TAKARA_MAN
ACTOR_OBJ_MAKEOSHIHIKI
ACTOR_OCEFF_SPOT
ACTOR_END_TITLE
ACTOR_UNSET_180
ACTOR_EN_TORCH
ACTOR_DEMO_EC
ACTOR_SHOT_SUN
ACTOR_EN_DY_EXTRA
ACTOR_EN_WONDER_TALK2
ACTOR_EN_GE2
ACTOR_OBJ_ROOMTIMER
ACTOR_EN_SSH
ACTOR_EN_STH
ACTOR_OCEFF_WIPE
ACTOR_OCEFF_STORM
ACTOR_EN_WEIYER
ACTOR_BG_SPOT05_SOKO
ACTOR_BG_JYA_1FLIFT
ACTOR_BG_JYA_HAHENIRON
ACTOR_BG_SPOT12_GATE
ACTOR_BG_SPOT12_SAKU
ACTOR_EN_HINTNUTS
ACTOR_EN_NUTSBALL
ACTOR_BG_SPOT00_BREAK
ACTOR_EN_SHOPNUTS
ACTOR_EN_IT
ACTOR_EN_GELDB
ACTOR_OCEFF_WIPE2
ACTOR_OCEFF_WIPE3
ACTOR_EN_NIW_GIRL
ACTOR_EN_DOG
ACTOR_EN_SI
ACTOR_BG_SPOT01_OBJECTS2
ACTOR_OBJ_COMB
ACTOR_BG_SPOT11_BAKUDANKABE
ACTOR_OBJ_KIBAKO2
ACTOR_EN_DNT_DEMO
ACTOR_EN_DNT_JIJI
ACTOR_EN_DNT_NOMAL
ACTOR_EN_GUEST
ACTOR_BG_BOM_GUARD
ACTOR_EN_HS2
ACTOR_DEMO_KEKKAI
ACTOR_BG_SPOT08_BAKUDANKABE
ACTOR_BG_SPOT17_BAKUDANKABE
ACTOR_UNSET_1AA
ACTOR_OBJ_MURE3
ACTOR_EN_TG
ACTOR_EN_MU
ACTOR_EN_GO2
ACTOR_EN_WF
ACTOR_EN_SKB
ACTOR_DEMO_GJ
ACTOR_DEMO_GEFF
ACTOR_BG_GND_FIREMEIRO
ACTOR_BG_GND_DARKMEIRO
ACTOR_BG_GND_SOULMEIRO
ACTOR_BG_GND_NISEKABE
ACTOR_BG_GND_ICEBLOCK
ACTOR_EN_GB
ACTOR_EN_GS
ACTOR_BG_MIZU_BWALL
ACTOR_BG_MIZU_SHUTTER
ACTOR_EN_DAIKU_KAKARIKO
ACTOR_BG_BOWL_WALL
ACTOR_EN_WALL_TUBO
ACTOR_EN_PO_DESERT
ACTOR_EN_CROW
ACTOR_DOOR_KILLER
ACTOR_BG_SPOT11_OASIS
ACTOR_BG_SPOT18_FUTA
ACTOR_BG_SPOT18_SHUTTER
ACTOR_EN_MA3
ACTOR_EN_COW
ACTOR_BG_ICE_TURARA
ACTOR_BG_ICE_SHUTTER
ACTOR_EN_KAKASI2
ACTOR_EN_KAKASI3
ACTOR_OCEFF_WIPE4
ACTOR_EN_EG
ACTOR_BG_MENKURI_NISEKABE
ACTOR_EN_ZO
ACTOR_OBJ_MAKEKINSUTA
ACTOR_EN_GE3
ACTOR_OBJ_TIMEBLOCK
ACTOR_OBJ_HAMISHI
ACTOR_EN_ZL4
ACTOR_EN_MM2
ACTOR_BG_JYA_BLOCK
ACTOR_OBJ_WARP2BLOCK
ACTOR_ID_MAX

View file

@ -0,0 +1,402 @@
OBJECT_INVALID
OBJECT_GAMEPLAY_KEEP
OBJECT_GAMEPLAY_FIELD_KEEP
OBJECT_GAMEPLAY_DANGEON_KEEP
OBJECT_UNSET_4
OBJECT_UNSET_5
OBJECT_HUMAN
OBJECT_OKUTA
OBJECT_CROW
OBJECT_POH
OBJECT_DY_OBJ
OBJECT_WALLMASTER
OBJECT_DODONGO
OBJECT_FIREFLY
OBJECT_BOX
OBJECT_FIRE
OBJECT_UNSET_10
OBJECT_UNSET_11
OBJECT_BUBBLE
OBJECT_NIW
OBJECT_LINK_BOY
OBJECT_LINK_CHILD
OBJECT_TITE
OBJECT_REEBA
OBJECT_PEEHAT
OBJECT_KINGDODONGO
OBJECT_HORSE
OBJECT_ZF
OBJECT_GOMA
OBJECT_ZL1
OBJECT_GOL
OBJECT_DODOJR
OBJECT_TORCH2
OBJECT_BL
OBJECT_TP
OBJECT_OA1
OBJECT_ST
OBJECT_BW
OBJECT_EI
OBJECT_HORSE_NORMAL
OBJECT_OB1
OBJECT_O_ANIME
OBJECT_SPOT04_OBJECTS
OBJECT_DDAN_OBJECTS
OBJECT_HIDAN_OBJECTS
OBJECT_HORSE_GANON
OBJECT_OA2
OBJECT_SPOT00_OBJECTS
OBJECT_MB
OBJECT_BOMBF
OBJECT_SK2
OBJECT_OE1
OBJECT_OE_ANIME
OBJECT_OE2
OBJECT_YDAN_OBJECTS
OBJECT_GND
OBJECT_AM
OBJECT_DEKUBABA
OBJECT_UNSET_3A
OBJECT_OA3
OBJECT_OA4
OBJECT_OA5
OBJECT_OA6
OBJECT_OA7
OBJECT_JJ
OBJECT_OA8
OBJECT_OA9
OBJECT_OB2
OBJECT_OB3
OBJECT_OB4
OBJECT_HORSE_ZELDA
OBJECT_OPENING_DEMO1
OBJECT_WARP1
OBJECT_B_HEART
OBJECT_DEKUNUTS
OBJECT_OE3
OBJECT_OE4
OBJECT_MENKURI_OBJECTS
OBJECT_OE5
OBJECT_OE6
OBJECT_OE7
OBJECT_OE8
OBJECT_OE9
OBJECT_OE10
OBJECT_OE11
OBJECT_OE12
OBJECT_VALI
OBJECT_OA10
OBJECT_OA11
OBJECT_MIZU_OBJECTS
OBJECT_FHG
OBJECT_OSSAN
OBJECT_MORI_HINERI1
OBJECT_BB
OBJECT_TOKI_OBJECTS
OBJECT_YUKABYUN
OBJECT_ZL2
OBJECT_MJIN
OBJECT_MJIN_FLASH
OBJECT_MJIN_DARK
OBJECT_MJIN_FLAME
OBJECT_MJIN_ICE
OBJECT_MJIN_SOUL
OBJECT_MJIN_WIND
OBJECT_MJIN_OKA
OBJECT_HAKA_OBJECTS
OBJECT_SPOT06_OBJECTS
OBJECT_ICE_OBJECTS
OBJECT_RELAY_OBJECTS
OBJECT_PO_FIELD
OBJECT_PO_COMPOSER
OBJECT_MORI_HINERI1A
OBJECT_MORI_HINERI2
OBJECT_MORI_HINERI2A
OBJECT_MORI_OBJECTS
OBJECT_MORI_TEX
OBJECT_SPOT08_OBJ
OBJECT_WARP2
OBJECT_HATA
OBJECT_BIRD
OBJECT_UNSET_78
OBJECT_UNSET_79
OBJECT_UNSET_7A
OBJECT_UNSET_7B
OBJECT_WOOD02
OBJECT_UNSET_7D
OBJECT_UNSET_7E
OBJECT_UNSET_7F
OBJECT_UNSET_80
OBJECT_LIGHTBOX
OBJECT_PU_BOX
OBJECT_UNSET_83
OBJECT_UNSET_84
OBJECT_TRAP
OBJECT_VASE
OBJECT_IM
OBJECT_TA
OBJECT_TK
OBJECT_XC
OBJECT_VM
OBJECT_BV
OBJECT_HAKACH_OBJECTS
OBJECT_EFC_CRYSTAL_LIGHT
OBJECT_EFC_FIRE_BALL
OBJECT_EFC_FLASH
OBJECT_EFC_LGT_SHOWER
OBJECT_EFC_STAR_FIELD
OBJECT_GOD_LGT
OBJECT_LIGHT_RING
OBJECT_TRIFORCE_SPOT
OBJECT_BDAN_OBJECTS
OBJECT_SD
OBJECT_RD
OBJECT_PO_SISTERS
OBJECT_HEAVY_OBJECT
OBJECT_GNDD
OBJECT_FD
OBJECT_DU
OBJECT_FW
OBJECT_MEDAL
OBJECT_HORSE_LINK_CHILD
OBJECT_SPOT02_OBJECTS
OBJECT_HAKA
OBJECT_RU1
OBJECT_SYOKUDAI
OBJECT_FD2
OBJECT_DH
OBJECT_RL
OBJECT_EFC_TW
OBJECT_DEMO_TRE_LGT
OBJECT_GI_KEY
OBJECT_MIR_RAY
OBJECT_BROB
OBJECT_GI_JEWEL
OBJECT_SPOT09_OBJ
OBJECT_SPOT18_OBJ
OBJECT_BDOOR
OBJECT_SPOT17_OBJ
OBJECT_SHOP_DUNGEN
OBJECT_NB
OBJECT_MO
OBJECT_SB
OBJECT_GI_MELODY
OBJECT_GI_HEART
OBJECT_GI_COMPASS
OBJECT_GI_BOSSKEY
OBJECT_GI_MEDAL
OBJECT_GI_NUTS
OBJECT_SA
OBJECT_GI_HEARTS
OBJECT_GI_ARROWCASE
OBJECT_GI_BOMBPOUCH
OBJECT_IN
OBJECT_TR
OBJECT_SPOT16_OBJ
OBJECT_OE1S
OBJECT_OE4S
OBJECT_OS_ANIME
OBJECT_GI_BOTTLE
OBJECT_GI_STICK
OBJECT_GI_MAP
OBJECT_OF1D_MAP
OBJECT_RU2
OBJECT_GI_SHIELD_1
OBJECT_DEKUJR
OBJECT_GI_MAGICPOT
OBJECT_GI_BOMB_1
OBJECT_OF1S
OBJECT_MA2
OBJECT_GI_PURSE
OBJECT_HNI
OBJECT_TW
OBJECT_RR
OBJECT_BXA
OBJECT_ANUBICE
OBJECT_GI_GERUDO
OBJECT_GI_ARROW
OBJECT_GI_BOMB_2
OBJECT_GI_EGG
OBJECT_GI_SCALE
OBJECT_GI_SHIELD_2
OBJECT_GI_HOOKSHOT
OBJECT_GI_OCARINA
OBJECT_GI_MILK
OBJECT_MA1
OBJECT_GANON
OBJECT_SST
OBJECT_NY_UNUSED
OBJECT_UNSET_E4
OBJECT_NY
OBJECT_FR
OBJECT_GI_PACHINKO
OBJECT_GI_BOOMERANG
OBJECT_GI_BOW
OBJECT_GI_GLASSES
OBJECT_GI_LIQUID
OBJECT_ANI
OBJECT_DEMO_6K
OBJECT_GI_SHIELD_3
OBJECT_GI_LETTER
OBJECT_SPOT15_OBJ
OBJECT_JYA_OBJ
OBJECT_GI_CLOTHES
OBJECT_GI_BEAN
OBJECT_GI_FISH
OBJECT_GI_SAW
OBJECT_GI_HAMMER
OBJECT_GI_GRASS
OBJECT_GI_LONGSWORD
OBJECT_SPOT01_OBJECTS
OBJECT_MD_UNUSED
OBJECT_MD
OBJECT_KM1
OBJECT_KW1
OBJECT_ZO
OBJECT_KZ
OBJECT_UMAJUMP
OBJECT_MASTERKOKIRI
OBJECT_MASTERKOKIRIHEAD
OBJECT_MASTERGOLON
OBJECT_MASTERZOORA
OBJECT_AOB
OBJECT_IK
OBJECT_AHG
OBJECT_CNE
OBJECT_GI_NIWATORI
OBJECT_SKJ
OBJECT_GI_BOTTLE_LETTER
OBJECT_BJI
OBJECT_BBA
OBJECT_GI_OCARINA_0
OBJECT_DS
OBJECT_ANE
OBJECT_BOJ
OBJECT_SPOT03_OBJECT
OBJECT_SPOT07_OBJECT
OBJECT_FZ
OBJECT_BOB
OBJECT_GE1
OBJECT_YABUSAME_POINT
OBJECT_GI_BOOTS_2
OBJECT_GI_SEED
OBJECT_GND_MAGIC
OBJECT_D_ELEVATOR
OBJECT_D_HSBLOCK
OBJECT_D_LIFT
OBJECT_MAMENOKI
OBJECT_GOROIWA
OBJECT_UNSET_120
OBJECT_TORYO
OBJECT_DAIKU
OBJECT_UNSET_123
OBJECT_NWC
OBJECT_BLKOBJ
OBJECT_GM
OBJECT_MS
OBJECT_HS
OBJECT_INGATE
OBJECT_LIGHTSWITCH
OBJECT_KUSA
OBJECT_TSUBO
OBJECT_GI_GLOVES
OBJECT_GI_COIN
OBJECT_KANBAN
OBJECT_GJYO_OBJECTS
OBJECT_OWL
OBJECT_MK
OBJECT_FU
OBJECT_GI_KI_TAN_MASK
OBJECT_GI_REDEAD_MASK
OBJECT_GI_SKJ_MASK
OBJECT_GI_RABIT_MASK
OBJECT_GI_TRUTH_MASK
OBJECT_GANON_OBJECTS
OBJECT_SIOFUKI
OBJECT_STREAM
OBJECT_MM
OBJECT_FA
OBJECT_OS
OBJECT_GI_EYE_LOTION
OBJECT_GI_POWDER
OBJECT_GI_MUSHROOM
OBJECT_GI_TICKETSTONE
OBJECT_GI_BROKENSWORD
OBJECT_JS
OBJECT_CS
OBJECT_GI_PRESCRIPTION
OBJECT_GI_BRACELET
OBJECT_GI_SOLDOUT
OBJECT_GI_FROG
OBJECT_MAG
OBJECT_DOOR_GERUDO
OBJECT_GT
OBJECT_EFC_ERUPC
OBJECT_ZL2_ANIME1
OBJECT_ZL2_ANIME2
OBJECT_GI_GOLONMASK
OBJECT_GI_ZORAMASK
OBJECT_GI_GERUDOMASK
OBJECT_GANON2
OBJECT_KA
OBJECT_TS
OBJECT_ZG
OBJECT_GI_HOVERBOOTS
OBJECT_GI_M_ARROW
OBJECT_DS2
OBJECT_EC
OBJECT_FISH
OBJECT_GI_SUTARU
OBJECT_GI_GODDESS
OBJECT_SSH
OBJECT_BIGOKUTA
OBJECT_BG
OBJECT_SPOT05_OBJECTS
OBJECT_SPOT12_OBJ
OBJECT_BOMBIWA
OBJECT_HINTNUTS
OBJECT_RS
OBJECT_SPOT00_BREAK
OBJECT_GLA
OBJECT_SHOPNUTS
OBJECT_GELDB
OBJECT_GR
OBJECT_DOG
OBJECT_JYA_IRON
OBJECT_JYA_DOOR
OBJECT_UNSET_16E
OBJECT_SPOT11_OBJ
OBJECT_KIBAKO2
OBJECT_DNS
OBJECT_DNK
OBJECT_GI_FIRE
OBJECT_GI_INSECT
OBJECT_GI_BUTTERFLY
OBJECT_GI_GHOST
OBJECT_GI_SOUL
OBJECT_BOWL
OBJECT_DEMO_KEKKAI
OBJECT_EFC_DOUGHNUT
OBJECT_GI_DEKUPOUCH
OBJECT_GANON_ANIME1
OBJECT_GANON_ANIME2
OBJECT_GANON_ANIME3
OBJECT_GI_RUPY
OBJECT_SPOT01_MATOYA
OBJECT_SPOT01_MATOYAB
OBJECT_MU
OBJECT_WF
OBJECT_SKB
OBJECT_GJ
OBJECT_GEFF
OBJECT_HAKA_DOOR
OBJECT_GS
OBJECT_PS
OBJECT_BWALL
OBJECT_COW
OBJECT_COB
OBJECT_GI_SWORD_1
OBJECT_DOOR_KILLER
OBJECT_OUKE_HAKA
OBJECT_TIMEBLOCK
OBJECT_ZL4

View file

@ -0,0 +1 @@
8012DB20 gMtxClear

View file

@ -1,47 +0,0 @@
// 32 bit implementation based off of Boost hash
#ifndef BOOST_HASH_DETAIL_HASH_MIX_32_HPP
#define BOOST_HASH_DETAIL_HASH_MIX_32_HPP
#include <boost/cstdint.hpp>
#include <cstddef>
#include <climits>
namespace boost
{
namespace hash_detail
{
template<uint32_t Bits> struct hash_mix_impl_32;
// hash_mix for 32 bit
//
// We use the "best xmxmx" implementation from
// https://github.com/skeeto/hash-prospector/issues/19
template<> struct hash_mix_impl_32<32>
{
inline static boost::uint32_t fn( boost::uint32_t x )
{
boost::uint32_t const m1 = 0x21f0aaad;
boost::uint32_t const m2 = 0x735a2d97;
x ^= x >> 16;
x *= m1;
x ^= x >> 15;
x *= m2;
x ^= x >> 15;
return x;
}
};
inline uint32_t hash_mix_32( uint32_t v )
{
return hash_mix_impl_32<32>::fn( v );
}
} // namespace hash_detail
} // namespace boost
#endif // #ifndef BOOST_HASH_DETAIL_HASH_MIX_32_HPP

View file

@ -1,128 +0,0 @@
// 32 bit implementation based off of Boost hash
// Only implementing 32 bit version of char based ranges
#ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
#define BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
#include <boost_custom/container_hash/hash_fwd_32.hpp>
#include <boost_custom/container_hash/version.hpp>
#if BOOST_VERSION_HAS_HASH_RANGE
#include <boost/container_hash/detail/hash_range.hpp>
#else
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/cstdint.hpp>
#include <cstddef>
#include <climits>
#include <iterator>
#endif // #if BOOST_VERSION_HAS_HASH_RANGE
namespace boost
{
namespace hash_detail
{
#if !BOOST_VERSION_HAS_HASH_RANGE
template<class T> struct is_char_type: public boost::false_type {};
#if CHAR_BIT == 8
template<> struct is_char_type<char>: public boost::true_type {};
template<> struct is_char_type<signed char>: public boost::true_type {};
template<> struct is_char_type<unsigned char>: public boost::true_type {};
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
template<> struct is_char_type<char8_t>: public boost::true_type {};
#endif
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
template<> struct is_char_type<std::byte>: public boost::true_type {};
#endif
#endif
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
#if BOOST_USE_STD_TYPES
#define BOOST_ENABLE_IF std::enable_if
#define BOOST_IS_SAME std::is_same
#else
#define BOOST_ENABLE_IF boost::enable_if_
#define BOOST_IS_SAME is_same
#endif
template<class It>
inline typename BOOST_ENABLE_IF<
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
BOOST_IS_SAME<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value,
std::size_t>::type
hash_range_32( uint32_t seed, It first, It last )
{
std::size_t n = static_cast<std::size_t>( last - first );
for( ; n >= 4; first += 4, n -= 4 )
{
// clang 5+, gcc 5+ figure out this pattern and use a single mov on x86
// gcc on s390x and power BE even knows how to use load-reverse
boost::uint32_t w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[3] ) ) << 24;
hash_combine_32( seed, w );
}
{
// add a trailing suffix byte of 0x01 because otherwise sequences of
// trailing zeroes are indistinguishable from end of string
boost::uint32_t w = 0x01u;
switch( n )
{
case 1:
w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
0x0100u;
break;
case 2:
w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
0x010000u;
break;
case 3:
w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
0x01000000u;
break;
}
hash_combine_32( seed, w );
}
return seed;
}
} // namespace hash_detail
} // namespace boost
#undef BOOST_ENABLE_IF
#undef BOOST_IS_SAME
#endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP

View file

@ -1,188 +0,0 @@
// 32 bit implementation based off of Boost hash
// Only implementing 32 bit versions integral and string based hashes
#ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
#define BOOST_FUNCTIONAL_HASH_HASH_32_HPP
#include <boost/container_hash/hash.hpp>
#include <boost_custom/container_hash/hash_fwd_32.hpp>
#include <boost_custom/container_hash/detail/hash_mix_32.hpp>
#include <boost_custom/container_hash/detail/hash_range_32.hpp>
#include <boost_custom/container_hash/version.hpp>
#if !BOOST_VERSION_HAS_HASH_RANGE
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#if BOOST_WORKAROUND(__GNUC__, < 3) \
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
#define BOOST_HASH_CHAR_TRAITS string_char_traits
#else
#define BOOST_HASH_CHAR_TRAITS char_traits
#endif
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
#if BOOST_USE_STD_TYPES
#define BOOST_ENABLE_IF std::enable_if
#define BOOST_IS_INTEGRAL hash_detail::is_integral
#define BOOST_IS_UNSIGNED is_unsigned
#define BOOST_MAKE_UNSIGNED make_unsigned
#else
#define BOOST_ENABLE_IF boost::enable_if_
#define BOOST_IS_INTEGRAL boost::is_integral
#define BOOST_IS_UNSIGNED boost::is_unsigned
#define BOOST_MAKE_UNSIGNED boost::make_unsigned
#endif
namespace boost
{
//
// boost::hash_value
//
// integral types
namespace hash_detail
{
template<class T,
bool bigger_than_size_t = (sizeof(T) > sizeof(uint32_t)),
bool is_unsigned = BOOST_IS_UNSIGNED<T>::value,
std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT,
std::size_t type_bits = sizeof(T) * CHAR_BIT>
struct hash_integral_impl_32;
template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl_32<T, false, is_unsigned, size_t_bits, type_bits>
{
static uint32_t fn( T v )
{
return static_cast<uint32_t>( v );
}
};
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl_32<T, true, false, size_t_bits, type_bits>
{
static uint32_t fn( T v )
{
typedef typename BOOST_MAKE_UNSIGNED<T>::type U;
if( v >= 0 )
{
return hash_integral_impl_32<U>::fn( static_cast<U>( v ) );
}
else
{
return ~hash_integral_impl_32<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
}
}
};
template<class T> struct hash_integral_impl_32<T, true, true, 32, 64>
{
static uint32_t fn( T v )
{
uint32_t seed = 0;
seed = static_cast<uint32_t>( v >> 32 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v ) + hash_detail::hash_mix_32( seed );
return seed;
}
};
template<class T> struct hash_integral_impl_32<T, true, true, 32, 128>
{
static uint32_t fn( T v )
{
uint32_t seed = 0;
seed = static_cast<uint32_t>( v >> 96 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v >> 64 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v >> 32 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v ) + hash_detail::hash_mix_32( seed );
return seed;
}
};
} // namespace hash_detail
template <typename T>
typename BOOST_ENABLE_IF<BOOST_IS_INTEGRAL<T>::value, uint32_t>::type
hash_value_32( T v )
{
return hash_detail::hash_integral_impl_32<T>::fn( v );
}
// contiguous ranges (string, vector, array)
#if BOOST_VERSION_HAS_HASH_RANGE
template <typename T>
typename BOOST_ENABLE_IF<container_hash::is_contiguous_range<T>::value, uint32_t>::type
hash_value_32( T const& v )
{
return boost::hash_range_32( v.data(), v.data() + v.size() );
}
#else
template <class Ch, class A>
inline uint32_t hash_value_32(
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v)
{
return boost::hash_range_32( v.data(), v.data() + v.size() );
}
#endif
//
// boost::hash_combine
//
template <class T>
inline void hash_combine_32( uint32_t& seed, T const& v )
{
seed = boost::hash_detail::hash_mix_32( seed + 0x9e3779b9 + boost::hash_32<T>()( v ) );
}
//
// boost::hash_range
//
template <class It>
inline void hash_range_32( uint32_t& seed, It first, It last )
{
seed = hash_detail::hash_range_32( seed, first, last );
}
template <class It>
inline uint32_t hash_range_32( It first, It last )
{
uint32_t seed = 0;
hash_range_32( seed, first, last );
return seed;
}
//
// boost::hash
//
template <class T> struct hash_32
{
typedef T argument_type;
typedef uint32_t result_type;
uint32_t operator()( T const& val ) const
{
return hash_value_32( val );
}
};
} // namespace boost
#undef BOOST_HASH_CHAR_TRAITS
#undef BOOST_ENABLE_IF
#undef BOOST_IS_INTEGRAL
#undef BOOST_IS_UNSIGNED
#undef BOOST_MAKE_UNSIGNED
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP

View file

@ -1,25 +0,0 @@
// 32 bit implementation based off of Boost hash
#ifndef BOOST_FUNCTIONAL_HASH_FWD_32_HPP
#define BOOST_FUNCTIONAL_HASH_FWD_32_HPP
#include <boost/container_hash/hash_fwd.hpp>
namespace boost
{
namespace container_hash
{
} // namespace container_hash
template<class T> struct hash_32;
template<class T> void hash_combine_32( uint32_t& seed, T const& v );
template<class It> void hash_range_32( uint32_t&, It, It );
template<class It> uint32_t hash_range_32( It, It );
} // namespace boost
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_32_HPP

View file

@ -1,11 +0,0 @@
#ifndef BOOST_CONTAINER_HASH_VERSION_HPP
#define BOOST_CONTAINER_HASH_VERSION_HPP
#include <boost/version.hpp>
#define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81)
#define BOOST_USE_STD_TYPES ((BOOST_VERSION / 100 % 1000) >= 84)
#endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP

View file

@ -1339,9 +1339,9 @@ typedef struct {
/* */ char* frenchAge;
} BetterSceneSelectAgeLabels;
// NTSC TODO: japanese bettersceneselect
typedef struct {
// /* */ char* japaneseName;
/* */ char* japaneseName;
/* */ char* englishName;
/* */ char* germanName;
/* */ char* frenchName;
@ -1350,7 +1350,7 @@ typedef struct {
} BetterSceneSelectEntrancePair;
typedef struct {
// /* */ char* japaneseName;
/* */ char* japaneseName;
/* */ char* englishName;
/* */ char* germanName;
/* */ char* frenchName;

View file

@ -0,0 +1,47 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/ShipInit.hpp"
#include "functions.h"
extern "C" {
#include "z64.h"
#include "overlays/gamestates/ovl_file_choose/file_choose.h"
}
static constexpr int32_t CVAR_DEBUG_ENABLED_DEFAULT = 0;
#define CVAR_DEBUG_ENABLED_NAME CVAR_DEVELOPER_TOOLS("DebugEnabled")
#define CVAR_DEBUG_ENABLED_VALUE CVarGetInteger(CVAR_DEBUG_ENABLED_NAME, CVAR_DEBUG_ENABLED_DEFAULT)
static constexpr int32_t CVAR_BOOT_TO_DEBUG_WARP_SCREEN_DEFAULT = 0;
#define CVAR_BOOT_TO_DEBUG_WARP_SCREEN_NAME CVAR_DEVELOPER_TOOLS("BootToDebugWarpScreen")
#define CVAR_BOOT_TO_DEBUG_WARP_SCREEN_VALUE \
CVarGetInteger(CVAR_BOOT_TO_DEBUG_WARP_SCREEN_NAME, CVAR_BOOT_TO_DEBUG_WARP_SCREEN_DEFAULT)
void OnFileChooseMainBootToDebugWarpScreen(void* gameState) {
FileChooseContext* fileChooseContext = (FileChooseContext*)gameState;
fileChooseContext->buttonIndex = 0xFF;
fileChooseContext->menuMode = FS_MENU_MODE_SELECT;
fileChooseContext->selectMode = SM_LOAD_GAME;
}
void OnZTitleUpdateBootToDebugWarpScreen(void* gameState) {
TitleContext* titleContext = (TitleContext*)gameState;
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.natureAmbienceId = 0xFF;
gSaveContext.gameMode = GAMEMODE_FILE_SELECT;
titleContext->state.running = false;
SET_NEXT_GAMESTATE(&titleContext->state, FileChoose_Init, FileChooseContext);
}
void RegisterBootToDebugWarpScreen() {
COND_HOOK(OnFileChooseMain, CVAR_DEBUG_ENABLED_VALUE && CVAR_BOOT_TO_DEBUG_WARP_SCREEN_VALUE,
OnFileChooseMainBootToDebugWarpScreen);
COND_HOOK(OnZTitleUpdate, CVAR_DEBUG_ENABLED_VALUE && CVAR_BOOT_TO_DEBUG_WARP_SCREEN_VALUE,
OnZTitleUpdateBootToDebugWarpScreen);
}
static RegisterShipInitFunc initFunc_BootToDebugWarpScreen(RegisterBootToDebugWarpScreen,
{ CVAR_DEBUG_ENABLED_NAME,
CVAR_BOOT_TO_DEBUG_WARP_SCREEN_NAME });

View file

@ -0,0 +1,23 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "macros.h"
}
static constexpr int32_t CVAR_NOKEESEGUAYTARGET_DEFAULT = 0;
#define CVAR_NOKEESEGUAYTARGET_NAME CVAR_CHEAT("NoKeeseGuayTarget")
#define CVAR_NOKEESEGUAYTARGET_VALUE CVarGetInteger(CVAR_NOKEESEGUAYTARGET_NAME, CVAR_NOKEESEGUAYTARGET_DEFAULT)
void RegisterNoKeeseGuayTarget() {
// Dive Attack
COND_VB_SHOULD(VB_KEESE_DO_DIVE_ATTACK, CVAR_NOKEESEGUAYTARGET_VALUE, { *should = false; });
COND_VB_SHOULD(VB_GUAY_DO_DIVE_ATTACK, CVAR_NOKEESEGUAYTARGET_VALUE, { *should = false; });
// Force Fly Away
COND_VB_SHOULD(VB_KEESE_FORCE_FLY_AWAY, CVAR_NOKEESEGUAYTARGET_VALUE, { *should = true; });
COND_VB_SHOULD(VB_GUAY_FORCE_FLY_AWAY, CVAR_NOKEESEGUAYTARGET_VALUE, { *should = true; });
}
static RegisterShipInitFunc initFunc_NoKeeseGuayTarget(RegisterNoKeeseGuayTarget, { CVAR_NOKEESEGUAYTARGET_NAME });

View file

@ -0,0 +1,17 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "macros.h"
}
static constexpr int32_t CVAR_NOREDEADFREEZE_DEFAULT = 0;
#define CVAR_NOREDEADFREEZE_NAME CVAR_CHEAT("NoRedeadFreeze")
#define CVAR_NOREDEADFREEZE_VALUE CVarGetInteger(CVAR_NOREDEADFREEZE_NAME, CVAR_NOREDEADFREEZE_DEFAULT)
void RegisterNoRedeadFreeze() {
COND_VB_SHOULD(VB_REDEAD_GIBDO_FREEZE_LINK, CVAR_NOREDEADFREEZE_VALUE, { *should = false; });
}
static RegisterShipInitFunc initFunc_NoRedeadFreeze(RegisterNoRedeadFreeze, { CVAR_NOREDEADFREEZE_NAME });

View file

@ -11,7 +11,7 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
// English
"Start Randomizer",
// German
"Start Randomizer",
"Randomizer starten",
// French
"Commencer le Randomizer",
},
@ -19,7 +19,7 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
// English
"Generate New Randomizer Seed",
// German
"Generate New Randomizer Seed",
"Neuen Randomizer Seed generieren",
// French
"Générer une nouvelle seed pour le Randomizer",
},
@ -27,7 +27,7 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
// English
"Open Randomizer Settings",
// German
"Open Randomizer Settings",
"Randomizer Optionen öffnen",
// French
"Ouvrir les paramètres du Randomizer",
},
@ -35,7 +35,7 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
// English
"Generating...",
// German
"Generating...",
"Generiere...",
// French
"Génération en cours...",
},
@ -47,11 +47,11 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
",\nor drop a spoiler log on the game window.",
#endif
// German
"No randomizer seed loaded.\nPlease generate one first"
"Kein Randomizer Seed gefunden.\nBitte generiere zuerst einen"
#if defined(__WIIU__) || defined(__SWITCH__)
".",
#else
",\nor drop a spoiler log on the game window.",
",\noder ziehe ein Spoiler Log\nauf das Spielfenster.",
#endif
// French
"Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\""

View file

@ -0,0 +1,170 @@
#include "public/bridge/consolevariablebridge.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/ShipInit.hpp"
#include <vector>
#include <spdlog/spdlog.h>
#include "WeirdAnimation.h"
extern "C" {
#include "macros.h"
#include "z64player.h"
#include "objects/gameplay_keep/gameplay_keep.h"
int ResourceMgr_OTRSigCheck(char* imgData);
AnimationHeaderCommon* ResourceMgr_LoadAnimByName(const char* path);
}
#define CVAR_NAME CVAR_ENHANCEMENT("N64WeirdFrames")
#define CVAR_DEFAULT 0
#define CVAR_VALUE CVarGetInteger(CVAR_NAME, CVAR_DEFAULT)
// A list of weird animations to contruct. These can either be an index out of bounds before
// the start of the animation or past the end of it. In either case you add a list of animations'
// data that are neighboring before or after the target animation. If more weird frame data is
// required then add more of the neighboring animations in ROM.
static std::vector<WeirdAnimation> weirdAnimations{
// For weirdshots.
{ gPlayerAnim_link_bow_side_walk,
PLAYER_LIMB_MAX,
IndexDirection::BACKWARD,
{
"__OTR__misc/link_animetion/gPlayerAnimData_0940E0",
"__OTR__misc/link_animetion/gPlayerAnimData_096370",
"__OTR__misc/link_animetion/gPlayerAnimData_096610",
"__OTR__misc/link_animetion/gPlayerAnimData_097650",
"__OTR__misc/link_animetion/gPlayerAnimData_097FC0",
} },
// For weirdslides.
{ gPlayerAnim_link_normal_side_walk,
PLAYER_LIMB_MAX,
IndexDirection::BACKWARD,
{
"__OTR__misc/link_animetion/gPlayerAnimData_1AFDD0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B0E10",
"__OTR__misc/link_animetion/gPlayerAnimData_1B1910",
"__OTR__misc/link_animetion/gPlayerAnimData_1B20F0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B25B0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B2B80",
"__OTR__misc/link_animetion/gPlayerAnimData_1B3600",
"__OTR__misc/link_animetion/gPlayerAnimData_1B4080",
"__OTR__misc/link_animetion/gPlayerAnimData_1B4B00",
"__OTR__misc/link_animetion/gPlayerAnimData_1B51D0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B5BD0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B6C10",
"__OTR__misc/link_animetion/gPlayerAnimData_1B72E0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B7B40",
} },
// For weirdslides.
{ gPlayerAnim_link_normal_side_walk,
PLAYER_LIMB_MAX,
IndexDirection::FORWARD,
{
"__OTR__misc/link_animetion/gPlayerAnimData_1B92D0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B9B30",
"__OTR__misc/link_animetion/gPlayerAnimData_1BA390",
"__OTR__misc/link_animetion/gPlayerAnimData_1BB2C0",
"__OTR__misc/link_animetion/gPlayerAnimData_1BC6B0",
"__OTR__misc/link_animetion/gPlayerAnimData_1BCA60",
"__OTR__misc/link_animetion/gPlayerAnimData_1BDC30",
"__OTR__misc/link_animetion/gPlayerAnimData_1BE410",
"__OTR__misc/link_animetion/gPlayerAnimData_1BF6F0",
"__OTR__misc/link_animetion/gPlayerAnimData_1C01F0",
"__OTR__misc/link_animetion/gPlayerAnimData_1C0CF0",
"__OTR__misc/link_animetion/gPlayerAnimData_1C1230",
} },
// For weirdslides.
{ gPlayerAnim_link_normal_side_walk_free,
PLAYER_LIMB_MAX,
IndexDirection::BACKWARD,
{
"__OTR__misc/link_animetion/gPlayerAnimData_1B1910",
"__OTR__misc/link_animetion/gPlayerAnimData_1B20F0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B25B0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B2B80",
"__OTR__misc/link_animetion/gPlayerAnimData_1B3600",
"__OTR__misc/link_animetion/gPlayerAnimData_1B4080",
"__OTR__misc/link_animetion/gPlayerAnimData_1B4B00",
"__OTR__misc/link_animetion/gPlayerAnimData_1B51D0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B5BD0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B6C10",
"__OTR__misc/link_animetion/gPlayerAnimData_1B72E0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B7B40",
"__OTR__misc/link_animetion/gPlayerAnimData_1B83A0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B92D0",
"__OTR__misc/link_animetion/gPlayerAnimData_1B9B30",
} },
// For weirdslides.
{ gPlayerAnim_link_normal_side_walk_free,
PLAYER_LIMB_MAX,
IndexDirection::FORWARD,
{
"__OTR__misc/link_animetion/gPlayerAnimData_1BB2C0",
"__OTR__misc/link_animetion/gPlayerAnimData_1BC6B0",
"__OTR__misc/link_animetion/gPlayerAnimData_1BCA60",
"__OTR__misc/link_animetion/gPlayerAnimData_1BDC30",
"__OTR__misc/link_animetion/gPlayerAnimData_1BE410",
"__OTR__misc/link_animetion/gPlayerAnimData_1BF6F0",
"__OTR__misc/link_animetion/gPlayerAnimData_1C01F0",
"__OTR__misc/link_animetion/gPlayerAnimData_1C0CF0",
"__OTR__misc/link_animetion/gPlayerAnimData_1C1230",
"__OTR__misc/link_animetion/gPlayerAnimData_1C1C30",
"__OTR__misc/link_animetion/gPlayerAnimData_1C2630",
} },
};
void RegisterN64WeirdFrames() {
COND_VB_SHOULD(VB_LOAD_PLAYER_ANIMATION_FRAME, CVAR_VALUE, {
const auto entry = va_arg(args, AnimationEntry*);
if (entry == nullptr) {
return;
}
auto animation = va_arg(args, LinkAnimationHeader*);
auto frame = va_arg(args, s32);
const auto limbCount = va_arg(args, s32);
const auto frameTable = va_arg(args, Vec3s*);
std::optional<const char*> animationName;
if (ResourceMgr_OTRSigCheck(reinterpret_cast<char*>(animation)) != 0) {
animationName = reinterpret_cast<const char*>(animation);
animation = reinterpret_cast<LinkAnimationHeader*>(ResourceMgr_LoadAnimByName(*animationName));
}
const auto playerAnimHeader =
static_cast<LinkAnimationHeader*>(SEGMENTED_TO_VIRTUAL(static_cast<void*>(animation)));
if (frame < 0 || frame >= playerAnimHeader->common.frameCount) {
const auto direction = frame < 0 ? IndexDirection::BACKWARD : IndexDirection::FORWARD;
if (animationName.has_value()) {
for (auto& weirdAnimation : weirdAnimations) {
if (weirdAnimation.GetDirection() == direction &&
weirdAnimation.GetTargetAnimation() == *animationName) {
if (const auto frameData = weirdAnimation.GetFrame(frame, playerAnimHeader->common.frameCount);
frameData != nullptr) {
*should = false;
SPDLOG_DEBUG("Weird animation for \"{}\": frame {}", weirdAnimation.GetTargetAnimation(),
frame);
std::memcpy(frameTable, frameData, sizeof(Vec3s) * limbCount + sizeof(s16));
} else {
SPDLOG_WARN("Weird Frame {} not included in weird animation for \"{}\"", frame,
weirdAnimation.GetTargetAnimation());
}
return;
}
}
}
SPDLOG_WARN("Weird Animation not present for \"{}\" but frame {} is out of bounds",
animationName.has_value() ? *animationName : "<null>", frame);
}
});
}
static RegisterShipInitFunc initFunc(RegisterN64WeirdFrames, { CVAR_NAME });

View file

@ -0,0 +1,65 @@
#include "WeirdAnimation.h"
#include "resource/ResourceManager.h"
#include "Context.h"
#include <cassert>
#include <cstring>
#include <spdlog/spdlog.h>
extern "C" {
#include "z64math.h"
}
const void* WeirdAnimation::GetFrame(s32 frame, s32 targetAnimationFrameCount) {
if (!animationData.has_value()) {
Build();
}
if (direction == IndexDirection::BACKWARD) {
const auto frameData = std::end(*animationData) + (((sizeof(Vec3s) * limbCount + sizeof(s16)) * frame));
return frameData >= std::begin(*animationData) ? &*frameData : nullptr;
} else if (direction == IndexDirection::FORWARD) {
const auto frameData = std::begin(*animationData) +
(((sizeof(Vec3s) * limbCount + sizeof(s16)) * (frame - targetAnimationFrameCount)));
return frameData < std::end(*animationData) ? &*frameData : nullptr;
} else {
SPDLOG_ERROR("Expected valid IndexDirection, got: {}", static_cast<int>(direction));
assert(false);
return nullptr;
}
}
void WeirdAnimation::Build() {
auto& animation = animationData.emplace();
for (const auto& neighborName : neighborAnimations) {
const auto neighbor = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(neighborName);
const auto prevSize = animation.size();
animation.resize(prevSize + neighbor->GetPointerSize());
std::memcpy(animation.data() + prevSize, neighbor->GetRawPointer(), neighbor->GetPointerSize());
// Animation data in ROM is padded to 0x10 bytes. Align the buffer the same way.
animation.resize((animation.size() + 0xF) & ~0xF);
}
const auto frameCount = animation.size() / (sizeof(Vec3s) * limbCount + sizeof(s16));
const auto directionStr = [this] {
switch (direction) {
case IndexDirection::BACKWARD:
return "backward";
case IndexDirection::FORWARD:
return "forward";
default:
SPDLOG_ERROR("Expected valid IndexDirection, got: {}", static_cast<int>(direction));
assert(false);
return "???";
}
}();
SPDLOG_DEBUG("Weird animation built for \"{}\": frameCount = {}, direction = {}", targetAnimation, frameCount,
directionStr);
}

View file

@ -0,0 +1,43 @@
#pragma once
#include <libultraship/libultra/types.h>
#include <cstddef>
#include <optional>
#include <string>
#include <utility>
#include <vector>
enum class IndexDirection {
BACKWARD,
FORWARD,
};
class WeirdAnimation {
public:
WeirdAnimation(std::string targetAnimation, s32 limbCount, IndexDirection direction,
std::vector<std::string> neighborAnimations)
: targetAnimation(std::move(targetAnimation)), limbCount(limbCount), direction(direction),
neighborAnimations(std::move(neighborAnimations)) {
}
const std::string& GetTargetAnimation() {
return targetAnimation;
}
IndexDirection GetDirection() {
return direction;
}
const void* GetFrame(s32 frame, s32 targetAnimationFrameCount);
private:
std::string targetAnimation;
s32 limbCount;
IndexDirection direction;
std::vector<std::string> neighborAnimations;
std::optional<std::vector<std::byte>> animationData;
void Build();
};

View file

@ -1,7 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "spdlog/spdlog.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
@ -12,29 +10,29 @@ extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
#define CVAR_BLOCKLIFT_NAME CVAR_ENHANCEMENT("FasterHeavyBlockLift")
#define CVAR_BLOCKLIFT_VALUE CVarGetInteger(CVAR_BLOCKLIFT_NAME, 0)
#define CVAR_SKIP_CUTSCENE_NAME CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint")
#define CVAR_SKIP_CUTSCENE_VALUE CVarGetInteger(CVAR_SKIP_CUTSCENE_NAME, IS_RANDO)
/**
* This primarily handles speeding up the heavy block lifts (OGC and in the Fire Trial) but also handles skipping
* the one point cutscene since the two options are so similar in what they do.
*/
void FasterHeavyBlockLift_Register() {
REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, {
void RegisterFasterHeavyBlockLift() {
COND_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, CVAR_BLOCKLIFT_VALUE || CVAR_SKIP_CUTSCENE_VALUE, {
Actor* actor = va_arg(args, Actor*);
if (actor->id == ACTOR_BG_HEAVY_BLOCK &&
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))) {
if (actor->id == ACTOR_BG_HEAVY_BLOCK) {
*should = false;
}
});
REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, {
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
*should = false;
}
});
COND_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, CVAR_BLOCKLIFT_VALUE || CVAR_SKIP_CUTSCENE_VALUE,
{ *should = false; });
REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, {
COND_VB_SHOULD(VB_PLAY_THROW_ANIMATION, CVAR_BLOCKLIFT_VALUE, {
Player* player = GET_PLAYER(gPlayState);
Actor* interactRangeActor = player->interactRangeActor;
s32 interactActorId = interactRangeActor->id;
@ -42,18 +40,17 @@ void FasterHeavyBlockLift_Register() {
// Same actor is used for small and large silver rocks, use actor params to identify large ones
bool isLargeSilverRock = (interactActorId == ACTOR_EN_ISHI) && ((interactRangeActor->params & 1) == 1);
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
if (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK) {
*should = false;
LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f);
}
});
REGISTER_VB_SHOULD(VB_MOVE_THROWN_ACTOR, {
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) {
COND_VB_SHOULD(VB_MOVE_THROWN_ACTOR, CVAR_BLOCKLIFT_VALUE, {
Actor* heldActor = va_arg(args, Actor*);
heldActor->shape.rot.x -= 3510;
}
});
}
static RegisterShipInitFunc initFunc(RegisterFasterHeavyBlockLift, { CVAR_BLOCKLIFT_NAME, CVAR_SKIP_CUTSCENE_NAME });

View file

@ -1,7 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "spdlog/spdlog.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
@ -12,11 +10,8 @@ extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
void FasterRupeeAccumulator_Register() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnInterfaceUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0))
return;
void RegisterFasterRupeeAccumulator() {
COND_HOOK(OnInterfaceUpdate, CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0), []() {
if (gSaveContext.rupeeAccumulator == 0) {
return;
}
@ -46,3 +41,5 @@ void FasterRupeeAccumulator_Register() {
}
});
}
static RegisterShipInitFunc initFunc(RegisterFasterRupeeAccumulator, { CVAR_ENHANCEMENT("FasterRupeeAccumulator") });

View file

@ -0,0 +1,26 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "functions.h"
#include "src/overlays/actors/ovl_Bg_Haka_Ship/z_bg_haka_ship.h"
}
void RegisterFasterShadowShip() {
COND_VB_SHOULD(VB_SHADOW_SHIP_SET_SPEED, CVarGetInteger(CVAR_ENHANCEMENT("FasterShadowShip"), 0), {
BgHakaShip* ship = va_arg(args, BgHakaShip*);
PlayState* play = va_arg(args, PlayState*);
if (!Play_InCsMode(play)) {
if (Actor_FindNearby(play, &ship->dyna.actor, ACTOR_EN_TEST, ACTORCAT_ENEMY, 800.0) == NULL &&
Actor_FindNearby(play, &ship->dyna.actor, ACTOR_PLAYER, ACTORCAT_PLAYER, 450.0) != NULL) {
*should = false;
ship->dyna.actor.speedXZ = 25.0f;
} else if (ship->dyna.actor.speedXZ > 4.0f) {
*should = false;
ship->dyna.actor.speedXZ = 4.0f;
}
}
});
}
static RegisterShipInitFunc initFunc(RegisterFasterShadowShip, { CVAR_ENHANCEMENT("FasterShadowShip") });

View file

@ -1,6 +1,6 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/randomizer/context.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
@ -10,12 +10,13 @@ extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
void SkipIntro_Register() {
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
void RegisterSkipIntro() {
bool shouldRegister = CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), 0) || IS_RANDO;
COND_VB_SHOULD(VB_PLAY_TRANSITION_CS, shouldRegister, {
// If we're playing rando and if starting age is adult and/or overworld spawns are shuffled we need to skip
// the cutscene regardless of the enhancement being on.
bool adultStart = gSaveContext.linkAge == LINK_AGE_ADULT;
bool shuffleEntrances = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_ENTRANCES).Is(true);
bool shuffleEntrances = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_ENTRANCES).Is(true);
if ((CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) ||
(IS_RANDO && (adultStart || shuffleEntrances))) &&
gSaveContext.cutsceneIndex == 0xFFF1) {
@ -45,3 +46,6 @@ void SkipIntro_Register() {
}
});
}
static RegisterShipInitFunc initFunc(RegisterSkipIntro,
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), "IS_RANDO" });

View file

@ -1,6 +1,7 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/randomizer/context.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "macros.h"
@ -12,12 +13,67 @@ extern "C" {
static bool sEnteredBlueWarp = false;
// Todo: Move item queueing here
/**
* This ensures the Kokiri blocking the forest exit checks if you are eligible to leave the forest
* every frame, instead of only at init. The reason we need to do this is when we skip the blue warp cutscene
* you end up getting the Kokiri Emerald after the actor has init'd, so the actor doesn't know you have it
*/
void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
func_80A995CC(enKo, play);
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) {
if (GameInteractor_Should(VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD))) {
enKo->collider.dim.height -= 200;
Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos);
enKo->actionFunc = func_80A99384;
}
}
}
void SkipBlueWarp_OnActorUpdate(void* actorPtr) {
EnKo* enKo = static_cast<EnKo*>(actorPtr);
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC) {
enKo->actionFunc = EnKo_MoveWhenReady;
}
}
void RegisterSkipBlueWarp() {
COND_ID_HOOK(OnActorUpdate, ACTOR_EN_KO,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO),
SkipBlueWarp_OnActorUpdate);
/**
* This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp
* cutscene. Typically this checks for if you have the medallion, and when skipping the cutscene at this point you
* don't have it yet.
*/
COND_VB_SHOULD(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF1) {
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
}
});
/**
* While we could rely on the Item_Give that's normally called, it's not very clear to the player that they
* received the item when skipping the blue warp cutscene, so we'll prevent that and queue it up to be given
* to the player instead.
*/
COND_VB_SHOULD(VB_GIVE_ITEM_FROM_BLUE_WARP,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), { *should = false; });
}
void RegisterShouldPlayBlueWarp() {
/**
* This will override the transitions into the blue warp cutscenes, set any appropriate flags, and
* set the entrance index to where you would normally end up after the blue warp cutscene. This
* should also account for the difference between your first and following visits to the blue warp.
*/
void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
// Do nothing when in a boss rush
if (IS_BOSS_RUSH) {
return;
@ -28,8 +84,10 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
// Force blue warp skip on when ER needs to place Link somewhere else.
// This is preferred over having story cutscenes play in the overworld and then reloading Link somewhere else after.
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) || overrideBlueWarpDestinations) {
// This is preferred over having story cutscenes play in the overworld and then reloading Link somewhere else
// after.
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) ||
overrideBlueWarpDestinations) {
bool isBlueWarpCutscene = false;
// Deku Tree Blue warp
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
@ -105,78 +163,15 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
}
sEnteredBlueWarp = false;
}
});
/**
/**
* Using this hook to simply observe that Link has entered a bluewarp
* This way we know to allow entrance rando overrides to be processed on the next tranisition hook
*/
void SkipBlueWarp_ShouldPlayBlueWarpCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
sEnteredBlueWarp = true;
REGISTER_VB_SHOULD(VB_PLAY_BLUE_WARP_CS, { sEnteredBlueWarp = true; });
}
/**
* While we could rely on the Item_Give that's normally called, it's not very clear to the player that they
* received the item when skipping the blue warp cutscene, so we'll prevent that and queue it up to be given
* to the player instead.
*/
void SkipBlueWarp_ShouldGiveItem(GIVanillaBehavior _, bool* should, va_list originalArgs) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
*should = false;
}
}
// Todo: Move item queueing here
/**
* This ensures the Kokiri blocking the forest exit checks if you are eligible to leave the forest
* every frame, instead of only at init. The reason we need to do this is when we skip the blue warp cutscene
* you end up getting the Kokiri Emerald after the actor has init'd, so the actor doesn't know you have it
*/
void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
func_80A995CC(enKo, play);
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) {
if (GameInteractor_Should(VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD))) {
enKo->collider.dim.height -= 200;
Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos);
enKo->actionFunc = func_80A99384;
}
}
}
void SkipBlueWarp_OnActorUpdate(void* actorPtr) {
EnKo* enKo = static_cast<EnKo*>(actorPtr);
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
enKo->actionFunc = EnKo_MoveWhenReady;
}
}
/**
* This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene.
* Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it
* yet.
*/
void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, va_list originalArgs) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF1) {
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
}
}
}
void SkipBlueWarp_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO,
SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP,
SkipBlueWarp_ShouldGiveItem);
}
static RegisterShipInitFunc initHooks(RegisterSkipBlueWarp,
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });
static RegisterShipInitFunc initUnconditionalHooks(RegisterShouldPlayBlueWarp);

View file

@ -1,6 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
@ -9,15 +8,17 @@ extern "C" {
/**
* This will skip the Deku Tree intro, and simply open the mouth as you approach it.
*/
void SkipDekuTreeIntro_Register() {
REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
void RegisterSkipDekuTreeIntro() {
COND_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
*should = false;
}
});
}
static RegisterShipInitFunc initFunc(RegisterSkipDekuTreeIntro,
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });

View file

@ -1,6 +1,6 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
@ -9,13 +9,12 @@ extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
void SkipLostWoodsBridge_Register() {
void RegisterSkipLostWoodsBridge() {
/**
* This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy
* Ocarina.
*/
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
COND_VB_SHOULD(VB_PLAY_TRANSITION_CS, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) &&
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
@ -24,7 +23,6 @@ void SkipLostWoodsBridge_Register() {
}
*should = false;
}
}
});
/**
@ -32,11 +30,11 @@ void SkipLostWoodsBridge_Register() {
* player that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given
* instead.
*/
REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
*should = false;
}
});
COND_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), { *should = false; });
// Todo: Move item queueing here
}
static RegisterShipInitFunc initFunc(RegisterSkipLostWoodsBridge,
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });

View file

@ -1,6 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
@ -33,16 +32,17 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
}
void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr);
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0)
return;
enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter;
}
}
void SkipToGivingZeldasLetter_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4,
void RegisterSkipToGivingZeldasLetter() {
COND_ID_HOOK(OnActorInit, ACTOR_EN_ZL4, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO),
SkipToGivingZeldasLetter_OnActorInit);
}
static RegisterShipInitFunc initFunc(RegisterSkipToGivingZeldasLetter,
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });

View file

@ -1,6 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
@ -8,18 +7,6 @@ extern "C" {
extern SaveContext gSaveContext;
}
void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_PAST_BRIDGE_SPAWN && gSaveContext.cutsceneIndex == 0xFFF1) {
// Normally set in the cutscene
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA;
gSaveContext.cutsceneIndex = 0;
*should = false;
}
}
}
/**
* When this cutscene is skipped, walking up to the bridge to castle town triggers a quick fade in/out
* which can be confusing to beginners, because they need to then fetch the Ocarina of Time from the water.
@ -46,7 +33,7 @@ void SkipZeldaFleeingCastle_OnActorUpdate(void* actorPtr) {
void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
Actor* actor = static_cast<Actor*>(actorPtr);
if (actor->params == 3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if (actor->params == 3) {
framesSinceSpawn = 0;
itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>(
(uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate);
@ -59,9 +46,20 @@ void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
}
}
void SkipZeldaFleeingCastle_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA,
void RegisterSkipZeldaFleeingCastle() {
COND_ID_HOOK(OnActorInit, ACTOR_ITEM_OCARINA,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO),
SkipZeldaFleeingCastle_OnActorInit);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS);
COND_VB_SHOULD(VB_PLAY_TRANSITION_CS, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_PAST_BRIDGE_SPAWN && gSaveContext.cutsceneIndex == 0xFFF1) {
// Normally set in the cutscene
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA;
gSaveContext.cutsceneIndex = 0;
*should = false;
}
});
}
static RegisterShipInitFunc initFunc(RegisterSkipZeldaFleeingCastle,
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });

View file

@ -1,28 +1,28 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "src/overlays/actors/ovl_Bg_Bdan_Objects/z_bg_bdan_objects.h"
}
/**
* Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom
*/
void MoveJabuJabuElevator_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(
ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) {
void BdanInit(void* actorRef) {
Player* player = GET_PLAYER(gPlayState);
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return;
}
if (bgBdanObjects->dyna.actor.params == 1) {
if (player->actor.world.pos.y < -500.0f) {
bgBdanObjects->timer = 220;
}
}
});
}
/**
* Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom
*/
void RegisterMoveJabuJabuElevator() {
COND_ID_HOOK(OnActorInit, ACTOR_BG_BDAN_OBJECTS,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), BdanInit);
}
static RegisterShipInitFunc initFunc(RegisterMoveJabuJabuElevator,
{ CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" });

View file

@ -1,6 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
@ -15,10 +14,10 @@ extern SaveContext gSaveContext;
* This simply skips the Mido interaction in Kokiri Forest, once you equip the Kokiri
* Sword and Deku Shield he will move out of the way without you needing to talk to him.
*/
void MoveMidoInKokiriForest_Register() {
REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
void RegisterMoveMidoInKokiriForest() {
COND_VB_SHOULD(
VB_MOVE_MIDO_IN_KOKIRI_FOREST, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
if (!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
@ -26,3 +25,6 @@ void MoveMidoInKokiriForest_Register() {
}
});
}
static RegisterShipInitFunc initFunc(RegisterMoveMidoInKokiriForest,
{ CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" });

View file

@ -1,6 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "overlays/actors/ovl_En_Ru1/z_en_ru1.h"
@ -9,14 +8,23 @@ extern "C" {
Actor* func_80AEB124(PlayState* play);
}
void SkipChildRutoInteractions_Register() {
// Skips the Child Ruto introduction cutscene, where she drops down into the hole in Jabu-Jabu's Belly
REGISTER_VB_SHOULD(VB_PLAY_CHILD_RUTO_INTRO, {
EnRu1* enRu1 = va_arg(args, EnRu1*);
void Ru1Init(void* actorRef) {
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return;
if (enRu1->action == 22) {
enRu1->action = 27;
enRu1->drawConfig = 1;
enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
}
}
void RegisterSkipChildRutoInteractions() {
// Skips the Child Ruto introduction cutscene, where she drops down into the hole in Jabu-Jabu's Belly
COND_VB_SHOULD(
VB_PLAY_CHILD_RUTO_INTRO, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
EnRu1* enRu1 = va_arg(args, EnRu1*);
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO);
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME);
@ -37,11 +45,8 @@ void SkipChildRutoInteractions_Register() {
});
// Skips a short dialogue sequence where Ruto tells you to throw her to the Sapphire
REGISTER_VB_SHOULD(VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE, {
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return;
}
COND_VB_SHOULD(VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
if (*should) {
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE);
*should = false;
@ -50,14 +55,11 @@ void SkipChildRutoInteractions_Register() {
// Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and
// waits for link to get closer
REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, {
COND_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
EnRu1* enRu1 = va_arg(args, EnRu1*);
DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return;
}
if (*should) {
enRu1->unk_28C = (BgBdanObjects*)dynaPolyActor;
Flags_SetInfTable(INFTABLE_145);
@ -84,18 +86,9 @@ void SkipChildRutoInteractions_Register() {
// This overrides the behavior that causes Ruto to get upset at you before sitting back down again when
// INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) {
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return;
}
if (enRu1->action == 22) {
enRu1->action = 27;
enRu1->drawConfig = 1;
enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
}
});
COND_ID_HOOK(OnActorInit, ACTOR_EN_RU1,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), Ru1Init);
}
static RegisterShipInitFunc initFunc(RegisterSkipChildRutoInteractions,
{ CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" });

View file

@ -1,18 +0,0 @@
#include "TimeSavers.h"
void TimeSavers_Register() {
// SkipCutscene
// Story
SkipBlueWarp_Register();
SkipDekuTreeIntro_Register();
SkipLostWoodsBridge_Register();
SkipToGivingZeldasLetter_Register();
SkipZeldaFleeingCastle_Register();
SkipIntro_Register();
// SkipMiscInteractions
MoveJabuJabuElevator_Register();
MoveMidoInKokiriForest_Register();
SkipChildRutoInteractions_Register();
FasterHeavyBlockLift_Register();
FasterRupeeAccumulator_Register();
}

View file

@ -1,21 +0,0 @@
#ifndef TIME_SAVERS_H
#define TIME_SAVERS_H
void TimeSavers_Register();
// SkipCutscene
// Story
void SkipBlueWarp_Register();
void SkipDekuTreeIntro_Register();
void SkipLostWoodsBridge_Register();
void SkipToGivingZeldasLetter_Register();
void SkipZeldaFleeingCastle_Register();
void SkipIntro_Register();
// SkipMiscInteractions
void MoveJabuJabuElevator_Register();
void MoveMidoInKokiriForest_Register();
void SkipChildRutoInteractions_Register();
void FasterHeavyBlockLift_Register();
void FasterRupeeAccumulator_Register();
#endif // TIME_SAVERS_H

View file

@ -0,0 +1,20 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
#include "z64save.h"
extern "C" SaveContext gSaveContext;
static constexpr int32_t CVAR_TIMEFLOWFILESELECT_DEFAULT = 0;
#define CVAR_TIMEFLOWFILESELECT_NAME CVAR_ENHANCEMENT("TimeFlowFileSelect")
#define CVAR_TIMEFLOWFILESELECT_VALUE CVarGetInteger(CVAR_TIMEFLOWFILESELECT_NAME, CVAR_TIMEFLOWFILESELECT_DEFAULT)
void OnFileChooseMainTimeFlowFileSelect(void* gameState) {
gSaveContext.skyboxTime += 0x10;
}
void RegisterTimeFlowFileSelect() {
COND_HOOK(OnFileChooseMain, CVAR_TIMEFLOWFILESELECT_VALUE, OnFileChooseMainTimeFlowFileSelect);
}
static RegisterShipInitFunc initFunc_TimeFlowFileSelect(RegisterTimeFlowFileSelect, { CVAR_TIMEFLOWFILESELECT_NAME });

View file

@ -623,6 +623,29 @@ void CustomMessage::InsertNumber(uint8_t num) {
Replace("[[d]]", std::to_string(num));
}
void CustomMessage::SetSingularPlural() {
for (std::string& str : messages) {
size_t firstBar = str.find('|');
if (firstBar != std::string::npos) {
size_t euroSign = str.find("");
size_t secondBar = str.find('|', firstBar + 1);
if (secondBar != std::string::npos) {
size_t thirdBar = str.find('|', secondBar + 1);
if (thirdBar != std::string::npos) {
if (euroSign == std::string::npos) {
str.erase(secondBar, thirdBar - secondBar);
} else {
str.erase(firstBar, secondBar - firstBar);
}
}
}
}
}
// remove the remaining bar
this->Replace("|", "");
this->Replace("", "");
}
void CustomMessage::Capitalize() {
for (std::string str : messages) {
(str)[0] = std::toupper((str)[0]);

View file

@ -153,6 +153,13 @@ class CustomMessage {
*/
void InsertNumber(uint8_t num);
/**
* @brief A sign at the end of an item name signals that it is plural.
* If a hint text has |singular|plural| forms specified, the unused one get's deleted.
* If no sign is present, the singular form is used.
*/
void SetSingularPlural();
/**
* @brief Replaces various symbols with the control codes necessary to
* display them in OoT's textboxes. i.e. special characters, colors, newlines,

View file

@ -11,6 +11,7 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
#include "soh/Enhancements/audio/AudioEditor.h"
#include "soh/Enhancements/randomizer/logic.h"
#define Path _Path
#define PATH_HACK
@ -1450,6 +1451,55 @@ static bool SfxHandler(std::shared_ptr<Ship::Console> Console, const std::vector
return 0;
}
static bool AvailableChecksProcessUndiscoveredExitsHandler(std::shared_ptr<Ship::Console> Console,
const std::vector<std::string>& args, std::string* output) {
const auto& logic = Rando::Context::GetInstance()->GetLogic();
bool enabled = false;
if (args.size() == 1) {
enabled = !logic->ACProcessUndiscoveredExits;
} else {
try {
enabled = std::stoi(args[1]);
} catch (std::invalid_argument const& ex) {
ERROR_MESSAGE("[SOH] Enable should be 0 or 1");
return 1;
}
}
logic->ACProcessUndiscoveredExits = enabled;
INFO_MESSAGE("[SOH] Available Checks - Process Undiscovered Exits %s",
logic->ACProcessUndiscoveredExits ? "enabled" : "disabled");
if (GameInteractor::IsSaveLoaded(true)) {
CheckTracker::RecalculateAvailableChecks();
}
return 0;
}
static bool AvailableChecksRecalculateHandler(std::shared_ptr<Ship::Console> Console,
const std::vector<std::string>& args, std::string* output) {
RandomizerRegion startingRegion = RR_ROOT;
if (args.size() > 1) {
try {
startingRegion = static_cast<RandomizerRegion>(std::stoi(args[1]));
} catch (std::invalid_argument const& ex) {
ERROR_MESSAGE("[SOH] Region should be a number");
return 1;
}
if (startingRegion <= RR_NONE || startingRegion >= RR_MAX) {
ERROR_MESSAGE("[SOH] Region should be between 1 and %d", RR_MAX - 1);
return 1;
}
}
CheckTracker::RecalculateAvailableChecks(startingRegion);
return 0;
}
void DebugConsole_Init(void) {
// Console
CMD_REGISTER("file_select", { FileSelectHandler, "Returns to the file select." });
@ -1708,5 +1758,15 @@ void DebugConsole_Init(void) {
{ "group_name", Ship::ArgumentType::TEXT, true },
} });
CMD_REGISTER("acpue", { AvailableChecksProcessUndiscoveredExitsHandler,
"Available Checks - Process Undiscovered Exits",
{ { "enable", Ship::ArgumentType::NUMBER, true } } });
CMD_REGISTER("acr", { AvailableChecksRecalculateHandler,
"Available Checks - Recalculate",
{
{ "starting_region", Ship::ArgumentType::NUMBER, true },
} });
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}

View file

@ -11,6 +11,7 @@
extern "C" {
#include <z64.h>
#include "src/overlays/actors/ovl_En_Rr/z_en_rr.h"
}
#define CVAR_ENEMY_RANDOMIZER_NAME CVAR_ENHANCEMENT("RandomizedEnemies")
@ -24,7 +25,7 @@ typedef struct EnemyEntry {
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX);
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed);
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play);
const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"),
@ -298,15 +299,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* po
// Get randomized enemy ID and parameter.
uint32_t seed =
play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
int8_t timesRandomized = 1;
// While randomized enemy isn't allowed in certain situations, randomize again.
while (!IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, randomEnemy)) {
randomEnemy = GetRandomizedEnemyEntry(seed + timesRandomized);
timesRandomized++;
}
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed, play);
*actorId = randomEnemy.id;
*params = randomEnemy.params;
@ -362,19 +355,28 @@ void GetSelectedEnemies() {
}
}
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play) {
std::vector<EnemyEntry> filteredEnemyList = {};
if (selectedEnemyList.size() == 0) {
GetSelectedEnemies();
}
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
for (EnemyEntry enemy : selectedEnemyList) {
if (IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, enemy)) {
filteredEnemyList.push_back(enemy);
}
}
if (filteredEnemyList.size() == 0) {
filteredEnemyList = selectedEnemyList;
}
if (CVAR_ENEMY_RANDOMIZER_VALUE == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
uint32_t finalSeed =
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
uint32_t randomNumber = Random(0, selectedEnemyList.size());
return selectedEnemyList[randomNumber];
uint32_t randomNumber = Random(0, filteredEnemyList.size());
return filteredEnemyList[randomNumber];
} else {
uint32_t randomSelectedEnemy = Random(0, selectedEnemyList.size());
return selectedEnemyList[randomSelectedEnemy];
uint32_t randomSelectedEnemy = Random(0, filteredEnemyList.size());
return filteredEnemyList[randomSelectedEnemy];
}
}
@ -572,6 +574,43 @@ 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*);
if (actor->category != ACTORCAT_PLAYER) {
*should = false;
Actor_Kill(actor);
}
});
// prevent dark link dealing fall damage to the player
COND_VB_SHOULD(VB_RECIEVE_FALL_DAMAGE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
Actor* actor = va_arg(args, Actor*);
if (actor->category != ACTORCAT_PLAYER) {
*should = false;
}
});
// prevent dark link from interfering with HESS/recoil/etc when at more than 100 away from him
COND_VB_SHOULD(VB_TORCH2_HANDLE_CLANKING, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
Actor* darkLink = va_arg(args, Actor*);
if (darkLink->xzDistToPlayer > 100.0f) {
*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*);
if (!(likeLike->collider1.base.oc != NULL && likeLike->collider1.base.oc->category == ACTORCAT_PLAYER) &&
!(likeLike->collider2.base.oc != NULL && likeLike->collider2.base.oc->category == ACTORCAT_PLAYER)) {
*should = false;
}
});
}
static RegisterShipInitFunc initFunc(RegisterEnemyRandomizer, { CVAR_ENEMY_RANDOMIZER_NAME });

View file

@ -1,6 +1,7 @@
#pragma once
#include <libultraship/libultra/types.h>
#include "item-tables/ItemTableTypes.h"
#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 52

View file

@ -65,7 +65,9 @@ DEFINE_HOOK(OnUpdateFileTargetSelection, (uint8_t optionIndex));
DEFINE_HOOK(OnUpdateFileLanguageSelection, (uint8_t optionIndex));
DEFINE_HOOK(OnUpdateFileQuestSelection, (uint8_t questIndex));
DEFINE_HOOK(OnUpdateFileBossRushOptionSelection, (uint8_t optionIndex, uint8_t optionValue));
DEFINE_HOOK(OnUpdateFileRandomizerOptionSelection, (uint8_t optionIndex));
DEFINE_HOOK(OnUpdateFileNameSelection, (int16_t charCode));
DEFINE_HOOK(OnFileChooseMain, (void* gameState));
DEFINE_HOOK(OnSetGameLanguage, ());
DEFINE_HOOK(OnGameStillFrozen, ());

View file

@ -294,10 +294,18 @@ void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionInd
optionValue);
}
void GameInteractor_ExecuteOnUpdateFileRandomizerOptionSelection(uint8_t optionIndex) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileRandomizerOptionSelection>(optionIndex);
}
void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileNameSelection>(charCode);
}
void GameInteractor_ExecuteOnFileChooseMain(void* gameState) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnFileChooseMain>(gameState);
}
// MARK: - Game
void GameInteractor_ExecuteOnSetGameLanguage() {

View file

@ -72,7 +72,9 @@ void GameInteractor_ExecuteOnUpdateFileTargetSelection(uint8_t optionIndex);
void GameInteractor_ExecuteOnUpdateFileLanguageSelection(uint8_t optionIndex);
void GameInteractor_ExecuteOnUpdateFileQuestSelection(uint8_t questIndex);
void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionIndex, uint8_t optionValue);
void GameInteractor_ExecuteOnUpdateFileRandomizerOptionSelection(uint8_t optionIndex);
void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode);
void GameInteractor_ExecuteOnFileChooseMain(void* gameState);
// MARK: - Game
void GameInteractor_ExecuteOnSetGameLanguage();

View file

@ -1111,6 +1111,22 @@ typedef enum {
// - None
VB_GTG_GATE_BE_OPEN,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnCrow`
VB_GUAY_DO_DIVE_ATTACK,
// #### `result`
// ```c
// false
// ```
// #### `args`
// - `*EnCrow`
VB_GUAY_FORCE_FLY_AWAY,
// #### `result`
// ```c
// true
@ -1199,6 +1215,22 @@ typedef enum {
// - None
VB_KALEIDO_UNPAUSE_CLOSE,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnFirefly`
VB_KEESE_DO_DIVE_ATTACK,
// #### `result`
// ```c
// false
// ```
// #### `args`
// - `*EnFirefly`
VB_KEESE_FORCE_FLY_AWAY,
// #### `result`
// ```c
// Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)
@ -1713,6 +1745,14 @@ typedef enum {
// - None
VB_PREVENT_ADULT_STICK,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnRd`
VB_REDEAD_GIBDO_FREEZE_LINK,
// #### `result`
// #### `result`
// ```c
@ -1806,6 +1846,15 @@ typedef enum {
// - `*int16_t` - original next entrance index (`play->setupExitList[exitIndex - 1]`)
VB_SET_VOIDOUT_FROM_SURFACE,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - BgHakaShip*
// - PlayState*
VB_SHADOW_SHIP_SET_SPEED,
// #### `result`
// ```c
// (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) &&
@ -2129,6 +2178,50 @@ typedef enum {
// #### `args`
// - `*EnWonderTalk2`
VB_WONDER_TALK,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*Actor`
VB_TRIGGER_VOIDOUT,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*Actor`
VB_TORCH2_HANDLE_CLANKING,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*Actor`
VB_RECIEVE_FALL_DAMAGE,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnRr`
VB_LIKE_LIKE_GRAB_PLAYER,
// #### `result`
// ```c
// entry != NULL
// ```
// #### `args`
// - `*AnimationEntry`
// - `*LinkAnimationHeader`
// - `s32` frame
// - `s32` limbCount
// - `*Vec3s` frameTable
VB_LOAD_PLAYER_ANIMATION_FRAME,
} GIVanillaBehavior;
#endif

View file

@ -13,7 +13,6 @@
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include <soh/Enhancements/item-tables/ItemTableManager.h>
#include "soh/Enhancements/timesaver_hook_handlers.h"
#include "soh/Enhancements/TimeSavers/TimeSavers.h"
#include "soh/Enhancements/randomizer/hook_handlers.h"
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
@ -98,6 +97,13 @@ void SwitchAge() {
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST;
gPlayState->linkAgeOnLoad ^= 1;
// Discover adult/child spawns
if (gPlayState->linkAgeOnLoad == LINK_AGE_ADULT) {
Entrance_SetEntranceDiscovered(ENTR_HYRULE_FIELD_10, false);
} else {
Entrance_SetEntranceDiscovered(ENTR_LINKS_HOUSE_CHILD_SPAWN, false);
}
static HOOK_ID hookId = 0;
hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, {
*should = false;
@ -954,7 +960,6 @@ void InitMods() {
BossRush_RegisterHooks();
RandomizerRegisterHooks();
TimeSaverRegisterHooks();
TimeSavers_Register();
RegisterTTS();
RegisterOcarinaTimeTravel();
RegisterPermanentHeartLoss();

View file

@ -1,658 +0,0 @@
static u16 n64WeirdFrames[] = {
0x0000, 0x0000, 0x1F40, 0x0AA7, 0x06C8, 0xB3C8, 0xF909, 0xFA3E, 0xED5F,
0x0000, 0x0000, 0x2286, 0xF8F0, 0xF9C3, 0xB101, 0x61C2, 0xFE1D, 0x3AB1,
0xFA11, 0x1FD2, 0x35C8, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA,
0xD928, 0x1D25, 0x3871, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE,
0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D27,
0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598, 0x02DF, 0xBFFD, 0x0000, 0x0000,
0x0000, 0xFF70, 0x0F7C, 0xF0FD, 0x0000, 0x0000, 0x1F19, 0x0AAC, 0x06BF,
0xB3E9, 0xF906, 0xFA42, 0xED71, 0x0000, 0x0000, 0x2260, 0xF8EC, 0xF9C8,
0xB11B, 0x61C2, 0xFE1D, 0x3AB1, 0xF9FD, 0x1FCF, 0x35AC, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000,
0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000, 0x0000,
0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000,
0x0000, 0x0000, 0xFFC7, 0x0D29, 0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598,
0x02DF, 0xBFFD, 0x0000, 0x0000, 0x0000, 0xFF7B, 0x0F7B, 0xF111, 0x0000,
0x0000, 0x1EF3, 0x0AB2, 0x06B7, 0xB409, 0xF902, 0xFA45, 0xED83, 0x0000,
0x0000, 0x223B, 0xF8E8, 0xF9CC, 0xB133, 0x61C2, 0xFE1D, 0x3AB1, 0xF9EA,
0x1FCD, 0x3590, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C,
0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928,
0x1D25, 0x3871, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000,
0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D2B, 0xFCAD,
0x0000, 0x0000, 0x0000, 0x9598, 0x02DF, 0xBFFD, 0x0000, 0x0000, 0x0000,
0xFF86, 0x0F7A, 0xF125, 0x0000, 0x0000, 0x1ECE, 0x0AB7, 0x06AF, 0xB428,
0xF8FF, 0xFA49, 0xED95, 0x0000, 0x0000, 0x2218, 0xF8E4, 0xF9D0, 0xB14B,
0x61C2, 0xFE1D, 0x3AB1, 0xF9D7, 0x1FCA, 0x3576, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8,
0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000, 0x0000, 0x0000,
0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0xFFC7, 0x0D2D, 0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598, 0x02DE,
0xBFFD, 0x0000, 0x0000, 0x0000, 0xFF90, 0x0F78, 0xF137, 0x0000, 0x0000,
0x1EAA, 0x0ABC, 0x06A7, 0xB446, 0xF8FC, 0xFA4D, 0xEDA6, 0x0000, 0x0000,
0x21F6, 0xF8E1, 0xF9D4, 0xB161, 0x61C2, 0xFE1D, 0x3AB1, 0xF9C6, 0x1FC8,
0x355D, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957,
0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25,
0x3871, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D2E, 0xFCAD, 0x0000,
0x0000, 0x0000, 0x9598, 0x02DE, 0xBFFD, 0x0000, 0x0000, 0x0000, 0xFF9A,
0x0F77, 0xF149, 0x0000, 0x0000, 0x1E89, 0x0AC1, 0x06A0, 0xB462, 0xF8F9,
0xFA50, 0xEDB5, 0x0000, 0x0000, 0x21D6, 0xF8DE, 0xF9D7, 0xB177, 0x61C2,
0xFE1D, 0x3AB1, 0xF9B5, 0x1FC5, 0x3545, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1,
0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000, 0x0000, 0x0000, 0xFB23,
0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0xFFC7, 0x0D30, 0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598, 0x02DE, 0xBFFD,
0x0000, 0x0000, 0x0000, 0xFFA3, 0x0F76, 0xF159, 0x0000, 0x0000, 0x1E6A,
0x0AC5, 0x0699, 0xB47B, 0xF8F6, 0xFA53, 0xEDC4, 0x0000, 0x0000, 0x21B9,
0xF8DB, 0xF9DB, 0xB18A, 0x61C2, 0xFE1D, 0x3AB1, 0xF9A6, 0x1FC3, 0x352F,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97,
0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871,
0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D31, 0xFCAD, 0x0000, 0x0000,
0x0000, 0x9598, 0x02DE, 0xBFFD, 0x0000, 0x0000, 0x0000, 0xFFAB, 0x0F75,
0xF168, 0x0000, 0x0000, 0x1E4D, 0x0AC9, 0x0693, 0xB493, 0xF8F4, 0xFA56,
0xEDD1, 0x0000, 0x0000, 0x219D, 0xF8D8, 0xF9DE, 0xB19C, 0x61C2, 0xFE1D,
0x3AB1, 0xF998, 0x1FC1, 0x351B, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0,
0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547,
0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7,
0x0D32, 0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598, 0x02DE, 0xBFFD, 0x0000,
0x0000, 0x0000, 0xFFB3, 0x0F75, 0xF176, 0x0000, 0x0000, 0x1E33, 0x0ACC,
0x068E, 0xB4A8, 0xF8F1, 0xFA58, 0xEDDE, 0x0000, 0x0000, 0x2185, 0xF8D5,
0xF9E1, 0xB1AC, 0x61C2, 0xFE1D, 0x3AB1, 0xF98B, 0x1FBF, 0x3509, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000,
0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000,
0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D33, 0xFCAD, 0x0000, 0x0000, 0x0000,
0x9598, 0x02DE, 0xBFFD, 0x0000, 0x0000, 0x0000, 0xFFB9, 0x0F74, 0xF182,
0x0000, 0x0000, 0x1E1C, 0x0AD0, 0x0689, 0xB4BB, 0xF8F0, 0xFA5A, 0xEDE8,
0x0000, 0x0000, 0x216F, 0xF8D3, 0xF9E3, 0xB1BB, 0x61C2, 0xFE1D, 0x3AB1,
0xF980, 0x1FBE, 0x34FA, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA,
0xD928, 0x1D25, 0x3871, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE,
0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D34,
0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598, 0x02DE, 0xBFFD, 0x0000, 0x0000,
0x0000, 0xFFBF, 0x0F73, 0xF18C, 0x0000, 0x0000, 0x1E09, 0x0AD2, 0x0685,
0xB4CA, 0xF8EE, 0xFA5C, 0xEDF1, 0x0000, 0x0000, 0x215D, 0xF8D1, 0xF9E5,
0xB1C7, 0x61C2, 0xFE1D, 0x3AB1, 0xF977, 0x1FBD, 0x34EC, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000,
0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000, 0x0000,
0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000,
0x0000, 0x0000, 0xFFC7, 0x0D35, 0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598,
0x02DE, 0xBFFD, 0x0000, 0x0000, 0x0000, 0xFFC3, 0x0F73, 0xF194, 0x0000,
0x0000, 0x1DF9, 0x0AD4, 0x0681, 0xB4D7, 0xF8ED, 0xFA5E, 0xEDF9, 0x0000,
0x0000, 0x214E, 0xF8D0, 0xF9E7, 0xB1D0, 0x61C2, 0xFE1D, 0x3AB1, 0xF96F,
0x1FBC, 0x34E2, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C,
0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928,
0x1D25, 0x3871, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000,
0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D35, 0xFCAD,
0x0000, 0x0000, 0x0000, 0x9598, 0x02DE, 0xBFFD, 0x0000, 0x0000, 0x0000,
0xFFC6, 0x0F72, 0xF19A, 0x0000, 0x0000, 0x1DEE, 0x0AD6, 0x067F, 0xB4E0,
0xF8EC, 0xFA5F, 0xEDFE, 0x0000, 0x0000, 0x2143, 0xF8CF, 0xF9E8, 0xB1D7,
0x61C2, 0xFE1D, 0x3AB1, 0xF96A, 0x1FBB, 0x34DA, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8,
0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000, 0x0000, 0x0000,
0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0xFFC7, 0x0D36, 0xFCAD, 0x0000, 0x0000, 0x0000, 0x9598, 0x02DE,
0xBFFD, 0x0000, 0x0000, 0x0000, 0xFFC8, 0x0F72, 0xF19E, 0x0000, 0x0000,
0x1DE7, 0x0AD7, 0x067D, 0xB4E6, 0xF8EB, 0xFA60, 0xEE01, 0x0000, 0x0000,
0x213C, 0xF8CE, 0xF9E9, 0xB1DC, 0x61C2, 0xFE1D, 0x3AB1, 0xF966, 0x1FBA,
0x34D5, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957,
0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25,
0x3871, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFC7, 0x0D36, 0xFCAD, 0x0000,
0x0000, 0x0000, 0x9598, 0x02DE, 0xBFFD, 0x0000, 0x0000, 0x0000, 0xFFC9,
0x0F72, 0xF19F, 0x0000, 0x0000, 0x1DE5, 0x0AD7, 0x067D, 0xB4E8, 0xF8EB,
0xFA60, 0xEE02, 0x0000, 0x0000, 0x213A, 0xF8CE, 0xF9E9, 0xB1DD, 0x61C2,
0xFE1D, 0x3AB1, 0xF965, 0x1FBA, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1,
0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000, 0x0000, 0x0000, 0xFB23,
0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0xFFC7, 0x0D31, 0x0000, 0x0000, 0x0000, 0x0000, 0xC000,
0x02DA, 0xC000, 0x0000, 0x0000, 0x0000, 0x04D3, 0x0A4F, 0xEE9D, 0x0000,
0x0000, 0x2006, 0x0843, 0x075F, 0xB0BC, 0xF9A0, 0xF456, 0xEDD8, 0x0000,
0x0000, 0x2087, 0xF851, 0xF9F1, 0xB1DE, 0x4000, 0xF709, 0x4000, 0xFFE8,
0xFE51, 0x34DC, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x0931,
0xEDA0, 0x7893, 0x0000, 0x0000, 0xE5ED, 0xFFDC, 0xFE09, 0xC0D5, 0xFCE7,
0x136D, 0x8A32, 0x0000, 0x0000, 0xA937, 0x0F64, 0x0AF3, 0xBE0C, 0xC000,
0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFBB, 0x0C34, 0xFFB9,
0x0000, 0x0000, 0x0000, 0xBF85, 0xFE57, 0xBFF8, 0x0000, 0x0000, 0x0000,
0x051E, 0x0D98, 0xEA86, 0x0000, 0x0000, 0x3174, 0x0986, 0x09AB, 0xA6B2,
0xFF8B, 0xF0C4, 0xEC66, 0x0000, 0x0000, 0x3A30, 0xF5E6, 0xF97D, 0xB12A,
0x436E, 0xF3CA, 0x4025, 0xFEC7, 0x01A9, 0x3349, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x0F19, 0xEF22, 0x7252, 0x0000, 0x0000, 0xE073,
0xFFF5, 0x006B, 0xC0AE, 0xF1CB, 0x13A2, 0x7CCB, 0x0000, 0x0000, 0xAE44,
0x0DD9, 0x0B72, 0xC3AA, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0xFFA2, 0x0A07, 0xFF1C, 0x0000, 0x0000, 0x0000, 0xB6A0, 0xF8C4,
0xC0B4, 0x0000, 0x0000, 0x0000, 0x046F, 0x14CD, 0xE515, 0x0000, 0x0000,
0x4B1D, 0x0BDC, 0x0C10, 0x9B28, 0x0FD5, 0xEB60, 0xF04B, 0x0000, 0x0000,
0x4FC3, 0xF095, 0xF87E, 0xAF9D, 0x4AE1, 0xECA4, 0x4080, 0xFC4F, 0x08DD,
0x2FCF, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x1BF1, 0xF27E,
0x64A8, 0x0000, 0x0000, 0xD467, 0x002E, 0x05AA, 0xC058, 0xD95B, 0x1417,
0x5F4D, 0x0000, 0x0000, 0xB961, 0x0A76, 0x0C88, 0xD006, 0xC000, 0x6A68,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF89, 0x07DA, 0xFE80, 0x0000,
0x0000, 0x0000, 0xAA24, 0xFF0F, 0xC009, 0x0000, 0x0000, 0x0000, 0xF90E,
0x1CAF, 0xCEFB, 0x0000, 0x0000, 0x5FFB, 0x0F61, 0x0A4A, 0x9E40, 0x2190,
0xE393, 0xD7FA, 0x0000, 0x0000, 0x5421, 0xEB43, 0xF77F, 0xAE10, 0x522D,
0xE580, 0x40F1, 0xF9E3, 0x0FAD, 0x2C50, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x286A, 0xF5F1, 0x573B, 0x0000, 0x0000, 0xC85C, 0x0066,
0x0AE9, 0xC002, 0xC0EB, 0x148C, 0x41D0, 0x0000, 0x0000, 0xC47E, 0x0713,
0x0D9E, 0xDC63, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0xFF7E, 0x06DC, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2,
0x0000, 0x0000, 0x0000, 0xE8F1, 0x1A2A, 0xB8CB, 0x0000, 0x0000, 0x67A9,
0x11B0, 0x083F, 0xA3A1, 0x232F, 0xE24B, 0xC7CF, 0x0000, 0x0000, 0x5267,
0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF8E4, 0x11DB, 0x2AAB,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE,
0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468,
0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x06DC, 0xFE38, 0x0000,
0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xE8F1,
0x1A2A, 0xB8CB, 0x0000, 0x0000, 0x67A9, 0x11B0, 0x083F, 0xA3A1, 0x232F,
0xE24B, 0xC7CF, 0x0000, 0x0000, 0x5267, 0xE8D8, 0xF70B, 0xAD5B, 0x556C,
0xE241, 0x4131, 0xF8E4, 0x183F, 0x2AAB, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080,
0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589,
0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0xFF7E, 0x06E3, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2,
0x0000, 0x0000, 0x0000, 0xE93D, 0x1A35, 0xB905, 0x0000, 0x0000, 0x677C,
0x11B0, 0x083F, 0xA3A1, 0x22F0, 0xE251, 0xC7F9, 0x0000, 0x0000, 0x524A,
0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF910, 0x1848, 0x2AF9,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE,
0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468,
0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x06E9, 0xFE38, 0x0000, 0x0000,
0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xE987, 0x1A40,
0xB93F, 0x0000, 0x0000, 0x674F, 0x11B0, 0x083F, 0xA3A1, 0x22B2, 0xE256,
0xC823, 0x0000, 0x0000, 0x522C, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241,
0x4131, 0xF93C, 0x1851, 0x2B47, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B,
0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D,
0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E,
0x06F0, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000,
0x0000, 0x0000, 0xE9D2, 0x1A4A, 0xB978, 0x0000, 0x0000, 0x6721, 0x11B0,
0x083F, 0xA3A1, 0x2275, 0xE25B, 0xC84D, 0x0000, 0x0000, 0x520E, 0xE8D8,
0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF969, 0x185A, 0x2B96, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000,
0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000,
0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0xFF7E, 0x06F6, 0xFE38, 0x0000, 0x0000, 0x0000,
0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEA1B, 0x1A54, 0xB9B1,
0x0000, 0x0000, 0x66F4, 0x11B0, 0x083F, 0xA3A1, 0x2237, 0xE261, 0xC876,
0x0000, 0x0000, 0x51F0, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131,
0xF995, 0x1863, 0x2BE4, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB,
0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201,
0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x06FD,
0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000,
0x0000, 0xEA64, 0x1A5E, 0xB9EA, 0x0000, 0x0000, 0x66C6, 0x11B0, 0x083F,
0xA3A1, 0x21FA, 0xE266, 0xC8A0, 0x0000, 0x0000, 0x51D1, 0xE8D8, 0xF70B,
0xAD5B, 0x556C, 0xE241, 0x4131, 0xF9C2, 0x186D, 0x2C32, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000,
0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000,
0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000,
0x0000, 0x0000, 0xFF7E, 0x0703, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A,
0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEAAC, 0x1A68, 0xBA22, 0x0000,
0x0000, 0x6698, 0x11B0, 0x083F, 0xA3A1, 0x21BD, 0xE26C, 0xC8C9, 0x0000,
0x0000, 0x51B2, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF9EE,
0x1876, 0x2C81, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35,
0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0,
0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000,
0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x070A, 0xFE38,
0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000,
0xEAF4, 0x1A71, 0xBA5B, 0x0000, 0x0000, 0x6669, 0x11B0, 0x083F, 0xA3A1,
0x2180, 0xE271, 0xC8F3, 0x0000, 0x0000, 0x5193, 0xE8D8, 0xF70B, 0xAD5B,
0x556C, 0xE241, 0x4131, 0xFA1A, 0x187F, 0x2CCF, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2,
0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B,
0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0xFF7E, 0x0710, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF,
0xBDD2, 0x0000, 0x0000, 0x0000, 0xEB3B, 0x1A7B, 0xBA93, 0x0000, 0x0000,
0x663B, 0x11B0, 0x083F, 0xA3A1, 0x2144, 0xE277, 0xC91C, 0x0000, 0x0000,
0x5174, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xFA47, 0x1888,
0x2D1D, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB,
0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1,
0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x0717, 0xFE38, 0x0000,
0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEB81,
0x1A83, 0xBACA, 0x0000, 0x0000, 0x660C, 0x11B0, 0x083F, 0xA3A1, 0x2107,
0xE27C, 0xC945, 0x0000, 0x0000, 0x5154, 0xE8D8, 0xF70B, 0xAD5B, 0x556C,
0xE241, 0x4131, 0xFA73, 0x1891, 0x2D6C, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080,
0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589,
0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0xFF7E, 0x071D, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2,
0x0000, 0x0000, 0x0000, 0xEBC7, 0x1A8C, 0xBB02, 0x0000, 0x0000, 0x65DD,
0x11B0, 0x083F, 0xA3A1, 0x20CB, 0xE282, 0xC96E, 0x0000, 0x0000, 0x5134,
0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xFAA0, 0x189A, 0x2DBA,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE,
0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468,
0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x0724, 0xFE38, 0x0000, 0x0000,
0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEC0D, 0x1A95,
0xBB3A, 0x0000, 0x0000, 0x65AF, 0x11B0, 0x083F, 0xA3A1, 0x2090, 0xE287,
0xC997, 0x0000, 0x0000, 0x5114, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241,
0x4131, 0xFACC, 0x18A3, 0x2E08, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B,
0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D,
0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E,
0x072A, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000,
0x0000, 0x0000, 0xEC51, 0x1A9D, 0xBB71, 0x0000, 0x0000, 0x657F, 0x11B0,
0x083F, 0xA3A1, 0x2054, 0xE28D, 0xC9C0, 0x0000, 0x0000, 0x50F4, 0xE8D8,
0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xFAF8, 0x18AD, 0x2E57, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000,
0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000,
0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0xFF7E, 0x0731, 0xFE38, 0x0000, 0x0000, 0x0000,
0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEC95, 0x1AA5, 0xBBA8,
0x0000, 0x0000, 0x6550, 0x11B0, 0x083F, 0xA3A1, 0x2019, 0xE293, 0xC9E9,
0x0000, 0x0000, 0x50D4, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131,
0xFB25, 0x18B6, 0x2EA5, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB,
0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201,
0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x0737,
0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000,
0x0000, 0xECD9, 0x1AAD, 0xBBDF, 0x0000, 0x0000, 0x6521, 0x11B0, 0x083F,
0xA3A1, 0x1FDE, 0xE298, 0xCA12, 0x0000, 0x0000, 0x50B3, 0xE8D8, 0xF70B,
0xAD5B, 0x556C, 0xE241, 0x4131, 0xFB51, 0x18BF, 0x2EF3, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000,
0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000,
0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000,
0x0000, 0x0000, 0xFF7E, 0x0732, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A,
0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEC9E, 0x1AA6, 0xBBAF, 0x0000,
0x0000, 0x654A, 0x11B0, 0x083F, 0xA3A1, 0x2011, 0xE293, 0xC9EE, 0x0000,
0x0000, 0x50D0, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xFB7E,
0x18C8, 0x2F42, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35,
0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0,
0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000,
0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x072C, 0xFE38,
0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000,
0xEC62, 0x1A9F, 0xBB7F, 0x0000, 0x0000, 0x6574, 0x11B0, 0x083F, 0xA3A1,
0x2045, 0xE28E, 0xC9CA, 0x0000, 0x0000, 0x50EC, 0xE8D8, 0xF70B, 0xAD5B,
0x556C, 0xE241, 0x4131, 0xFBAA, 0x18D1, 0x2F90, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2,
0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B,
0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0xFF7E, 0x0726, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF,
0xBDD2, 0x0000, 0x0000, 0x0000, 0xEC26, 0x1A98, 0xBB4E, 0x0000, 0x0000,
0x659D, 0x11B0, 0x083F, 0xA3A1, 0x2079, 0xE289, 0xC9A7, 0x0000, 0x0000,
0x5108, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xFBA0, 0x18CF,
0x2F7E, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB,
0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1,
0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x0721, 0xFE38, 0x0000,
0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEBEA,
0x1A90, 0xBB1E, 0x0000, 0x0000, 0x65C6, 0x11B0, 0x083F, 0xA3A1, 0x20AD,
0xE284, 0xC983, 0x0000, 0x0000, 0x5125, 0xE8D8, 0xF70B, 0xAD5B, 0x556C,
0xE241, 0x4131, 0xFB83, 0x18C9, 0x2F4B, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080,
0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589,
0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0xFF7E, 0x071B, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2,
0x0000, 0x0000, 0x0000, 0xEBAD, 0x1A89, 0xBAED, 0x0000, 0x0000, 0x65EF,
0x11B0, 0x083F, 0xA3A1, 0x20E2, 0xE280, 0xC95F, 0x0000, 0x0000, 0x5140,
0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xFB56, 0x18C0, 0x2EFC,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE,
0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468,
0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x0715, 0xFE38, 0x0000, 0x0000,
0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEB70, 0x1A81,
0xBABD, 0x0000, 0x0000, 0x6618, 0x11B0, 0x083F, 0xA3A1, 0x2117, 0xE27B,
0xC93B, 0x0000, 0x0000, 0x515C, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241,
0x4131, 0xFB1D, 0x18B4, 0x2E98, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B,
0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D,
0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E,
0x0710, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000,
0x0000, 0x0000, 0xEB32, 0x1A79, 0xBA8C, 0x0000, 0x0000, 0x6641, 0x11B0,
0x083F, 0xA3A1, 0x214B, 0xE276, 0xC917, 0x0000, 0x0000, 0x5178, 0xE8D8,
0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xFADB, 0x18A7, 0x2E23, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000,
0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000,
0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0xFF7E, 0x070A, 0xFE38, 0x0000, 0x0000, 0x0000,
0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEAF4, 0x1A71, 0xBA5B,
0x0000, 0x0000, 0x6669, 0x11B0, 0x083F, 0xA3A1, 0x2180, 0xE271, 0xC8F3,
0x0000, 0x0000, 0x5193, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131,
0xFA92, 0x1898, 0x2DA3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB,
0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201,
0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x0704,
0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000,
0x0000, 0xEAB5, 0x1A69, 0xBA29, 0x0000, 0x0000, 0x6692, 0x11B0, 0x083F,
0xA3A1, 0x21B5, 0xE26C, 0xC8CE, 0x0000, 0x0000, 0x51AE, 0xE8D8, 0xF70B,
0xAD5B, 0x556C, 0xE241, 0x4131, 0xFA47, 0x1888, 0x2D1D, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000,
0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000,
0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000,
0x0000, 0x0000, 0xFF7E, 0x06FF, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A,
0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xEA76, 0x1A61, 0xB9F8, 0x0000,
0x0000, 0x66BA, 0x11B0, 0x083F, 0xA3A1, 0x21EB, 0xE268, 0xC8AA, 0x0000,
0x0000, 0x51C9, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF9FB,
0x1878, 0x2C98, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35,
0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0,
0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000,
0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x06F9, 0xFE38,
0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000,
0xEA36, 0x1A58, 0xB9C6, 0x0000, 0x0000, 0x66E2, 0x11B0, 0x083F, 0xA3A1,
0x2220, 0xE263, 0xC886, 0x0000, 0x0000, 0x51E4, 0xE8D8, 0xF70B, 0xAD5B,
0x556C, 0xE241, 0x4131, 0xF9B3, 0x186A, 0x2C18, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2,
0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B,
0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0xFF7E, 0x06F3, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF,
0xBDD2, 0x0000, 0x0000, 0x0000, 0xE9F6, 0x1A4F, 0xB994, 0x0000, 0x0000,
0x670A, 0x11B0, 0x083F, 0xA3A1, 0x2256, 0xE25E, 0xC862, 0x0000, 0x0000,
0x51FF, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF970, 0x185C,
0x2BA3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB,
0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1,
0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x06EE, 0xFE38, 0x0000,
0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xE9B6,
0x1A46, 0xB962, 0x0000, 0x0000, 0x6732, 0x11B0, 0x083F, 0xA3A1, 0x228C,
0xE259, 0xC83D, 0x0000, 0x0000, 0x5219, 0xE8D8, 0xF70B, 0xAD5B, 0x556C,
0xE241, 0x4131, 0xF937, 0x1850, 0x2B3F, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080,
0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589,
0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0xFF7E, 0x06E8, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2,
0x0000, 0x0000, 0x0000, 0xE975, 0x1A3D, 0xB930, 0x0000, 0x0000, 0x675A,
0x11B0, 0x083F, 0xA3A1, 0x22C2, 0xE255, 0xC819, 0x0000, 0x0000, 0x5233,
0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF90B, 0x1847, 0x2AF0,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE,
0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468,
0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E, 0x06E2, 0xFE38, 0x0000, 0x0000,
0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000, 0x0000, 0x0000, 0xE933, 0x1A34,
0xB8FE, 0x0000, 0x0000, 0x6782, 0x11B0, 0x083F, 0xA3A1, 0x22F8, 0xE250,
0xC7F4, 0x0000, 0x0000, 0x524D, 0xE8D8, 0xF70B, 0xAD5B, 0x556C, 0xE241,
0x4131, 0xF8EE, 0x1841, 0x2ABD, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000, 0x0000, 0xC2E2, 0x0080, 0x0D4B,
0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000, 0x0000, 0xC98B, 0x0589, 0x0E1D,
0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF7E,
0x06DC, 0xFE38, 0x0000, 0x0000, 0x0000, 0xA61A, 0x05CF, 0xBDD2, 0x0000,
0x0000, 0x0000, 0xE8F1, 0x1A2A, 0xB8CB, 0x0000, 0x0000, 0x67A9, 0x11B0,
0x083F, 0xA3A1, 0x232F, 0xE24B, 0xC7CF, 0x0000, 0x0000, 0x5267, 0xE8D8,
0xF70B, 0xAD5B, 0x556C, 0xE241, 0x4131, 0xF8E4, 0x183F, 0x2AAB, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x2D35, 0xF7BB, 0x51AE, 0x0000,
0x0000, 0xC2E2, 0x0080, 0x0D4B, 0xBFDB, 0xB5D0, 0x14C1, 0x3468, 0x0000,
0x0000, 0xC98B, 0x0589, 0x0E1D, 0xE201, 0xC000, 0x6A68, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00F7, 0x0CAE, 0xFD93,
0x0000, 0x0000, 0x0000, 0x9953, 0x02B3, 0xC0ED, 0x0000, 0x0000, 0x0000,
0x087B, 0xFFC0, 0xE175, 0x0000, 0x0000, 0x21F0, 0xF6DE, 0x077F, 0xB7DB,
0xF4E5, 0x0606, 0x05E6, 0x0000, 0x0000, 0x20F1, 0xF94E, 0xF7A2, 0xA326,
0x61C2, 0xFE1D, 0x37D7, 0xF95E, 0x1FDD, 0x34D3, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x4557, 0xF959, 0x2A44, 0x0000, 0x0000, 0xAABB,
0xF8B0, 0x8BB6, 0xD4CC, 0xD92F, 0x1D54, 0x3848, 0x0000, 0x0000, 0x0000,
0xFB26, 0x0549, 0xC9CC, 0xC000, 0x6A5E, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0x0116, 0x0CC0, 0xFD9A, 0x0000, 0x0000, 0x0000, 0x9887, 0x0329,
0xC09E, 0x0000, 0x0000, 0x0000, 0x0799, 0x00ED, 0xE1D3, 0x0000, 0x0000,
0x22E2, 0xF7D8, 0x0726, 0xB67D, 0xF49C, 0x03DB, 0x005E, 0x0000, 0x0000,
0x2B3C, 0xF915, 0xF7F1, 0xA454, 0x62C0, 0xFE54, 0x3797, 0xF92C, 0x20DE,
0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x4621, 0xF96D,
0x27EA, 0x0000, 0x0000, 0xA9E6, 0xF91F, 0x8B69, 0xD466, 0xD95F, 0x1EAC,
0x371C, 0x0000, 0x0000, 0x0000, 0xFB3D, 0x055A, 0xC9C2, 0xC000, 0x69B8,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0CE8, 0xFD9C, 0x0000,
0x0000, 0x0000, 0x97EA, 0x0386, 0xC05E, 0x0000, 0x0000, 0x0000, 0x0626,
0x032D, 0xE3FB, 0x0000, 0x0000, 0x2426, 0xFAD2, 0x0685, 0xB38C, 0xF57E,
0xFFB5, 0xF6A9, 0x0000, 0x0000, 0x387B, 0xF8D1, 0xF858, 0xA605, 0x6384,
0xFE7E, 0x3766, 0xF906, 0x21A4, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x46BC, 0xF97C, 0x261B, 0x0000, 0x0000, 0xA942, 0xF975,
0x8B2E, 0xD418, 0xD984, 0x1FB4, 0x3636, 0x0000, 0x0000, 0x0000, 0xFB4E,
0x0566, 0xC9BA, 0xC000, 0x68B8, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0x0122, 0x0D15, 0xFD9C, 0x0000, 0x0000, 0x0000, 0x9777, 0x03CA, 0xC02D,
0x0000, 0x0000, 0x0000, 0x046D, 0x05D9, 0xE7E4, 0x0000, 0x0000, 0x2423,
0xFEA9, 0x05BE, 0xB001, 0xF807, 0xFB50, 0xEC3D, 0x0000, 0x0000, 0x41C4,
0xF886, 0xF8D0, 0xA815, 0x63DC, 0xFE9D, 0x3742, 0xF8EA, 0x2233, 0x34D3,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x472C, 0xF987, 0x24CA,
0x0000, 0x0000, 0xA8CB, 0xF9B3, 0x8B03, 0xD3DF, 0xD99F, 0x2074, 0x358F,
0x0000, 0x0000, 0x0000, 0xFB5B, 0x0570, 0xC9B4, 0xC000, 0x67AE, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0x011D, 0x0D3B, 0xFD9B, 0x0000, 0x0000,
0x0000, 0x972A, 0x03F9, 0xC00C, 0x0000, 0x0000, 0x0000, 0x02CD, 0x0871,
0xECF0, 0x0000, 0x0000, 0x2282, 0x0237, 0x04F5, 0xACD1, 0xFAB6, 0xF82C,
0xE46E, 0x0000, 0x0000, 0x441A, 0xF838, 0xF952, 0xAA60, 0x63D8, 0xFEB2,
0x372A, 0xF8E4, 0x2293, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x4777, 0xF98E, 0x23EB, 0x0000, 0x0000, 0xA87C, 0xF9DC, 0x8AE6,
0xD3B9, 0xD9B1, 0x20F3, 0x3520, 0x0000, 0x0000, 0x0000, 0xFB63, 0x0576,
0xC9B0, 0xC000, 0x66EA, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0119,
0x0D48, 0xFD9B, 0x0000, 0x0000, 0x0000, 0x9700, 0x0413, 0xBFF9, 0x0000,
0x0000, 0x0000, 0x0166, 0x0A9F, 0xF199, 0x0000, 0x0000, 0x20E8, 0x05CA,
0x03DE, 0xAA10, 0xFC09, 0xF67D, 0xE107, 0x0000, 0x0000, 0x3F53, 0xF7EC,
0xF9D9, 0xACBF, 0x63D6, 0xFEBD, 0x371C, 0xF8E4, 0x22C7, 0x34D3, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x47A0, 0xF992, 0x2370, 0x0000,
0x0000, 0xA851, 0xF9F3, 0x8AD7, 0xD3A4, 0xD9BB, 0x2139, 0x34E3, 0x0000,
0x0000, 0x0000, 0xFB68, 0x0579, 0xC9AE, 0xC000, 0x66BD, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0x0115, 0x0D1A, 0xFD9A, 0x0000, 0x0000, 0x0000,
0x96F2, 0x041B, 0xBFF3, 0x0000, 0x0000, 0x0000, 0xFF60, 0x0D4F, 0xF565,
0x0000, 0x0000, 0x22E9, 0x0918, 0x0309, 0xA7C3, 0xFC6B, 0xF55C, 0xE057,
0x0000, 0x0000, 0x36FF, 0xF7A5, 0xFA5C, 0xAF0E, 0x63D5, 0xFEC1, 0x3718,
0xF8E4, 0x22D5, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x47AB, 0xF993, 0x234F, 0x0000, 0x0000, 0xA845, 0xF9F9, 0x8AD2, 0xD39F,
0xD9BE, 0x214C, 0x34D2, 0x0000, 0x0000, 0x0000, 0xFB69, 0x057A, 0xC9AE,
0xC000, 0x67B5, 0xFD27, 0x0000, 0x0000, 0x0000, 0x0000, 0x010A, 0x0CC6,
0xFD97, 0x0000, 0x0000, 0x0000, 0x96FE, 0x0414, 0xBFF9, 0x0000, 0x0000,
0x0000, 0xFD19, 0x1014, 0xF9A5, 0x0000, 0x0000, 0x2559, 0x0C01, 0x0311,
0xA5B2, 0xFC12, 0xF4B0, 0xE1B0, 0x0000, 0x0000, 0x2D81, 0xF767, 0xFAD6,
0xB129, 0x63D6, 0xFEBE, 0x371C, 0xF8E4, 0x22C3, 0x34D3, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x479D, 0xF992, 0x2378, 0x0000, 0x0000,
0xA853, 0xF9F1, 0x8AD8, 0xD3A6, 0xD9BA, 0x2135, 0x34E7, 0x0000, 0x0000,
0x0000, 0xFB67, 0x0579, 0xC9AF, 0xC000, 0x6992, 0xFD28, 0x0000, 0x0000,
0x0000, 0x0000, 0x00FF, 0x0C98, 0xFD95, 0x0000, 0x0000, 0x0000, 0x971F,
0x0400, 0xC007, 0x0000, 0x0000, 0x0000, 0xFB52, 0x1123, 0xFA0F, 0x0000,
0x0000, 0x2963, 0x0E7F, 0x036D, 0xA3F8, 0xFB18, 0xF4A7, 0xE4FB, 0x0000,
0x0000, 0x238E, 0xF736, 0xFB41, 0xB2EA, 0x63D7, 0xFEB5, 0x3726, 0xF8E4,
0x2297, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x477A,
0xF98F, 0x23E1, 0x0000, 0x0000, 0xA878, 0xF9DE, 0x8AE5, 0xD3B8, 0xD9B2,
0x20F9, 0x351B, 0x0000, 0x0000, 0x0000, 0xFB63, 0x0576, 0xC9B0, 0xC000,
0x6B72, 0xFD27, 0x0000, 0x0000, 0x0000, 0x0000, 0x00F7, 0x0CAA, 0xFD93,
0x0000, 0x0000, 0x0000, 0x9751, 0x03E1, 0xC01D, 0x0000, 0x0000, 0x0000,
0xFA1E, 0x1043, 0xF463, 0x0000, 0x0000, 0x3152, 0x0EB9, 0x03DB, 0xA3FA,
0xFA58, 0xF5A9, 0xE7CE, 0x0000, 0x0000, 0x21A2, 0xF716, 0xFB95, 0xB42C,
0x63DA, 0xFEA7, 0x3736, 0xF8E4, 0x2254, 0x34D3, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x4746, 0xF98A, 0x247C, 0x0000, 0x0000, 0xA8AF,
0xF9C1, 0x8AF9, 0xD3D2, 0xD9A6, 0x20A0, 0x3568, 0x0000, 0x0000, 0x0000,
0xFB5E, 0x0572, 0xC9B3, 0xC000, 0x6C75, 0xFD26, 0x0000, 0x0000, 0x0000,
0x0000, 0x00F4, 0x0CD4, 0xFD92, 0x0000, 0x0000, 0x0000, 0x9790, 0x03BC,
0xC038, 0x0000, 0x0000, 0x0000, 0xF9E3, 0x0E84, 0xEC75, 0x0000, 0x0000,
0x3A01, 0x0CB5, 0x0446, 0xA5B7, 0xF9B9, 0xF749, 0xEA3F, 0x0000, 0x0000,
0x24A0, 0xF79E, 0xFB49, 0xB1AD, 0x63DD, 0xFE96, 0x3749, 0xF8F3, 0x2202,
0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x4706, 0xF983,
0x253D, 0x0000, 0x0000, 0xA8F4, 0xF99E, 0x8B11, 0xD3F2, 0xD996, 0x2033,
0x35C8, 0x0000, 0x0000, 0x0000, 0xFB56, 0x056C, 0xC9B6, 0xC000, 0x6C9C,
0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0x00F3, 0x0D0A, 0xFD92, 0x0000,
0x0000, 0x0000, 0x97D7, 0x0391, 0xC056, 0x0000, 0x0000, 0x0000, 0xFB3A,
0x0C31, 0xE450, 0x0000, 0x0000, 0x408E, 0x09E0, 0x04C3, 0xA81B, 0xF8D4,
0xF91B, 0xEDE4, 0x0000, 0x0000, 0x2489, 0xF85F, 0xFAAF, 0xADC3, 0x639C,
0xFE83, 0x3760, 0xF905, 0x21A6, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x46BD, 0xF97C, 0x2616, 0x0000, 0x0000, 0xA941, 0xF976,
0x8B2D, 0xD417, 0xD985, 0x1FB6, 0x3634, 0x0000, 0x0000, 0x0000, 0xFB4E,
0x0567, 0xC9BA, 0xC000, 0x6C8A, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000,
0x00F3, 0x0D3F, 0xFD92, 0x0000, 0x0000, 0x0000, 0x9822, 0x0364, 0xC075,
0x0000, 0x0000, 0x0000, 0xFDE4, 0x09B2, 0xDDC3, 0x0000, 0x0000, 0x435A,
0x0683, 0x054B, 0xAAEB, 0xF7D0, 0xFB63, 0xF278, 0x0000, 0x0000, 0x235F,
0xF8A5, 0xFA74, 0xAC83, 0x633E, 0xFE6F, 0x3777, 0xF918, 0x2144, 0x34D3,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x4670, 0xF975, 0x26FC,
0x0000, 0x0000, 0xA992, 0xF94B, 0x8B4A, 0xD43E, 0xD972, 0x1F33, 0x36A6,
0x0000, 0x0000, 0x0000, 0xFB46, 0x0560, 0xC9BE, 0xC000, 0x6C4D, 0xFD26,
0x0000, 0x0000, 0x0000, 0x0000, 0x00F3, 0x0D69, 0xFD92, 0x0000, 0x0000,
0x0000, 0x986D, 0x0338, 0xC094, 0x0000, 0x0000, 0x0000, 0x00CB, 0x079B,
0xDA49, 0x0000, 0x0000, 0x4227, 0x02E6, 0x05D5, 0xADEC, 0xF6E0, 0xFDF9,
0xF7A1, 0x0000, 0x0000, 0x211C, 0xF8CB, 0xFA47, 0xABDD, 0x62E0, 0xFE5B,
0x378F, 0xF92B, 0x20E2, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x4624, 0xF96D, 0x27E1, 0x0000, 0x0000, 0xA9E3, 0xF921, 0x8B68,
0xD465, 0xD960, 0x1EB1, 0x3718, 0x0000, 0x0000, 0x0000, 0xFB3D, 0x055A,
0xC9C2, 0xC000, 0x6BF3, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0x00F4,
0x0D7B, 0xFD92, 0x0000, 0x0000, 0x0000, 0x98B5, 0x030E, 0xC0B0, 0x0000,
0x0000, 0x0000, 0x037C, 0x05C8, 0xDA0F, 0x0000, 0x0000, 0x3CBF, 0xFF51,
0x0658, 0xB0E4, 0xF62F, 0x009C, 0xFCD9, 0x0000, 0x0000, 0x1E4D, 0xF8EA,
0xF9F8, 0xAAD9, 0x6287, 0xFE48, 0x37A5, 0xF93D, 0x2086, 0x34D3, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x45DC, 0xF966, 0x28B9, 0x0000,
0x0000, 0xAA2F, 0xF8F9, 0x8B83, 0xD489, 0xD94F, 0x1E36, 0x3783, 0x0000,
0x0000, 0x0000, 0xFB35, 0x0554, 0xC9C5, 0xC000, 0x6B8A, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0x00F4, 0x0D5C, 0xFD92, 0x0000, 0x0000, 0x0000,
0x98F4, 0x02E9, 0xC0C9, 0x0000, 0x0000, 0x0000, 0x05C7, 0x03CA, 0xDBA1,
0x0000, 0x0000, 0x34B7, 0xFC0A, 0x06CD, 0xB399, 0xF5B8, 0x02DC, 0x00ED,
0x0000, 0x0000, 0x1D69, 0xF90D, 0xF95C, 0xA8CB, 0x6239, 0xFE37, 0x37B9,
0xF94D, 0x2035, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x459C, 0xF960, 0x2977, 0x0000, 0x0000, 0xAA73, 0xF8D6, 0x8B9C, 0xD4AA,
0xD93F, 0x1DC9, 0x37E2, 0x0000, 0x0000, 0x0000, 0xFB2E, 0x054F, 0xC9C9,
0xC000, 0x6B20, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0x00F5, 0x0D15,
0xFD93, 0x0000, 0x0000, 0x0000, 0x9926, 0x02CD, 0xC0DC, 0x0000, 0x0000,
0x0000, 0x075C, 0x01E0, 0xDDF8, 0x0000, 0x0000, 0x2C46, 0xF95A, 0x072A,
0xB5D0, 0xF554, 0x0489, 0x039F, 0x0000, 0x0000, 0x1EA1, 0xF92D, 0xF895,
0xA63E, 0x61FA, 0xFE29, 0x37C9, 0xF95A, 0x1FF4, 0x34D3, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x4569, 0xF95B, 0x2A0E, 0x0000, 0x0000,
0xAAA8, 0xF8BA, 0x8BAF, 0xD4C3, 0xD933, 0x1D73, 0x382D, 0x0000, 0x0000,
0x0000, 0xFB28, 0x054B, 0xC9CB, 0xC000, 0x6AC3, 0xFD26, 0x0000, 0x0000,
0x0000, 0x0000, 0x00F6, 0x0CCE, 0xFD93, 0x0000, 0x0000, 0x0000, 0x9947,
0x02BA, 0xC0E8, 0x0000, 0x0000, 0x0000, 0x0838, 0x005F, 0xE057, 0x0000,
0x0000, 0x2512, 0xF789, 0x0768, 0xB74F, 0xF506, 0x05A2, 0x054F, 0x0000,
0x0000, 0x202D, 0xF945, 0xF7EA, 0xA411, 0x61D1, 0xFE20, 0x37D3, 0xF962,
0x1FCA, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x4548,
0xF958, 0x2A72, 0x0000, 0x0000, 0xAACC, 0xF8A7, 0x8BBC, 0xD4D4, 0xD92B,
0x1D3A, 0x385F, 0x0000, 0x0000, 0x0000, 0xFB24, 0x0548, 0xC9CD, 0xC000,
0x6A81, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD57,
0x0C75, 0xFD93, 0x0000, 0x0000, 0x0000, 0x95A0, 0x02DA, 0xC000, 0x0000,
0x0000, 0x0000, 0x0244, 0x0D14, 0xE896, 0x0000, 0x0000, 0x2E92, 0x08FA,
0x0919, 0xAA50, 0xFC76, 0xF14F, 0xE452, 0x0000, 0x0000, 0x2291, 0xF851,
0xF9F1, 0xB1DE, 0x61C2, 0xFE1D, 0x35CD, 0xF95B, 0x1FEF, 0x34D3, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000,
0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD92F, 0x1D54, 0x3848, 0x0000,
0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC006, 0x6A68, 0xFD32, 0x0000,
0x0000, 0x0000, 0x0000, 0xFD54, 0x0C77, 0xFD9E, 0x0000, 0x0000, 0x0000,
0x94AD, 0x0356, 0xBF9C, 0x0000, 0x0000, 0x0000, 0x0259, 0x0CB4, 0xE74A,
0x0000, 0x0000, 0x2EEA, 0x0809, 0x08E4, 0xAAB8, 0xFE17, 0xF127, 0xDF5D,
0x0000, 0x0000, 0x2B98, 0xF8F7, 0xF9E2, 0xB095, 0x61B8, 0xFE53, 0x357E,
0xF916, 0x212E, 0x34CB, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA,
0xD95F, 0x1EAA, 0x371E, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE,
0xC04E, 0x6A68, 0xFDC0, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD53, 0x0C8C,
0xFDA3, 0x0000, 0x0000, 0x0000, 0x93F0, 0x03B8, 0xBF4B, 0x0000, 0x0000,
0x0000, 0x02C7, 0x0BD5, 0xE5AA, 0x0000, 0x0000, 0x2E30, 0x0652, 0x0865,
0xABEB, 0xFFCD, 0xF110, 0xDABC, 0x0000, 0x0000, 0x34F5, 0xF9DB, 0xF9BC,
0xAEBB, 0x61AF, 0xFE7D, 0x3540, 0xF8EF, 0x21B7, 0x34B9, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000,
0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD984, 0x1FB1, 0x3639, 0x0000, 0x0000,
0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC0B7, 0x6A6B, 0xFE8E, 0x0000, 0x0000,
0x0000, 0x0000, 0xFD51, 0x0CAA, 0xFDA5, 0x0000, 0x0000, 0x0000, 0x9366,
0x0400, 0xBF0D, 0x0000, 0x0000, 0x0000, 0x0364, 0x0A9D, 0xE3F4, 0x0000,
0x0000, 0x2C91, 0x047C, 0x07C5, 0xADB1, 0x00D9, 0xF153, 0xD839, 0x0000,
0x0000, 0x3C47, 0xFAE5, 0xF986, 0xAC76, 0x61A8, 0xFE9C, 0x3513, 0xF8E4,
0x21B6, 0x34A5, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C,
0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD99F,
0x2070, 0x3592, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC133,
0x6A70, 0xFF83, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD50, 0x0CC4, 0xFDA5,
0x0000, 0x0000, 0x0000, 0x930A, 0x0432, 0xBEE3, 0x0000, 0x0000, 0x0000,
0x040C, 0x0932, 0xE254, 0x0000, 0x0000, 0x2A5B, 0x032F, 0x072C, 0xAFD6,
0x007B, 0xF22A, 0xD940, 0x0000, 0x0000, 0x3FC3, 0xFC00, 0xF947, 0xA9EC,
0x61A4, 0xFEB0, 0x34F5, 0xF8E4, 0x2157, 0x3493, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8,
0xF8A1, 0x8BC0, 0xD4DA, 0xD9B1, 0x20EF, 0x3524, 0x0000, 0x0000, 0x0000,
0xFB23, 0x0547, 0xC9CE, 0xC1B6, 0x6A78, 0x0088, 0x0000, 0x0000, 0x0000,
0x0000, 0xFD50, 0x0CCF, 0xFDA6, 0x0000, 0x0000, 0x0000, 0x92D5, 0x044D,
0xBECA, 0x0000, 0x0000, 0x0000, 0x049D, 0x07BC, 0xE0C0, 0x0000, 0x0000,
0x2834, 0x0288, 0x067C, 0xB323, 0xFE75, 0xF3EA, 0xDE7B, 0x0000, 0x0000,
0x3F06, 0xFD16, 0xF905, 0xA741, 0x61A1, 0xFEBC, 0x34E4, 0xF8F8, 0x20C9,
0x3489, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957,
0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD9BA, 0x2134,
0x34E7, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC235, 0x6A82,
0x0184, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD4F, 0x0CC6, 0xFDA6, 0x0000,
0x0000, 0x0000, 0x92C4, 0x0457, 0xBEC2, 0x0000, 0x0000, 0x0000, 0x0547,
0x05B8, 0xDF1F, 0x0000, 0x0000, 0x24E0, 0x0233, 0x05AE, 0xB76D, 0xFBC0,
0xF679, 0xE64F, 0x0000, 0x0000, 0x3AF5, 0xFE10, 0xF8C7, 0xA49B, 0x61A1,
0xFEBF, 0x34DF, 0xF917, 0x2036, 0x348C, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1,
0x8BC0, 0xD4DA, 0xD9BD, 0x2148, 0x34D6, 0x0000, 0x0000, 0x0000, 0xFB23,
0x0547, 0xC9CE, 0xC2A3, 0x6A8D, 0x0260, 0x0000, 0x0000, 0x0000, 0x0000,
0xFD4F, 0x0CAE, 0xFDA6, 0x0000, 0x0000, 0x0000, 0x92D1, 0x0450, 0xBEC8,
0x0000, 0x0000, 0x0000, 0x05F3, 0x030D, 0xDE5A, 0x0000, 0x0000, 0x1E9D,
0x022D, 0x050A, 0xBB0D, 0xF963, 0xF95F, 0xEEBA, 0x0000, 0x0000, 0x33EA,
0xFEDA, 0xF893, 0xA21E, 0x61A1, 0xFEBC, 0x34E4, 0xF93D, 0x1FCD, 0x34A3,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97,
0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD9BA, 0x2130, 0x34EB,
0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC2F5, 0x6A97, 0x0304,
0x0000, 0x0000, 0x0000, 0x0000, 0xFD4E, 0x0C90, 0xFDA6, 0x0000, 0x0000,
0x0000, 0x92F8, 0x043B, 0xBEDA, 0x0000, 0x0000, 0x0000, 0x063A, 0x009D,
0xDE80, 0x0000, 0x0000, 0x17CA, 0x0272, 0x04DA, 0xBC5D, 0xF7F1, 0xFBE8,
0xF5E9, 0x0000, 0x0000, 0x2BD5, 0xFF5C, 0xF86F, 0x9FF1, 0x61A3, 0xFEB3,
0x34F1, 0xF965, 0x1FBA, 0x34D3, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0,
0xD4DA, 0xD9B1, 0x20F4, 0x351F, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547,
0xC9CE, 0xC320, 0x6A9D, 0x0359, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD4E,
0x0C75, 0xFDA5, 0x0000, 0x0000, 0x0000, 0x9332, 0x041C, 0xBEF5, 0x0000,
0x0000, 0x0000, 0x0643, 0xFF9C, 0xDC98, 0x0000, 0x0000, 0x1859, 0x02F7,
0x0515, 0xBB8A, 0xF76E, 0xFD33, 0xF9B4, 0x0000, 0x0000, 0x26AE, 0xFF80,
0xF863, 0x9E38, 0x61A6, 0xFEA6, 0x3504, 0xF9C6, 0x2019, 0x356D, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000,
0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD9A5, 0x209C, 0x356C, 0x0000,
0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC317, 0x6A9B, 0x0346, 0x0000,
0x0000, 0x0000, 0x0000, 0xFD4D, 0x0C58, 0xFDA3, 0x0000, 0x0000, 0x0000,
0x937C, 0x03F5, 0xBF17, 0x0000, 0x0000, 0x0000, 0x0645, 0x0057, 0xD6D7,
0x0000, 0x0000, 0x23BD, 0x03A8, 0x0578, 0xB9FB, 0xF78A, 0xFCE7, 0xF92C,
0x0000, 0x0000, 0x26FA, 0xFD92, 0xF8C4, 0x9DB0, 0x61AA, 0xFE95, 0x351D,
0xFA67, 0x20B7, 0x366D, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000,
0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA,
0xD996, 0x202F, 0x35CB, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE,
0xC249, 0x6A84, 0x01AB, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD4D, 0x0C3A,
0xFDA2, 0x0000, 0x0000, 0x0000, 0x93D1, 0x03C8, 0xBF3D, 0x0000, 0x0000,
0x0000, 0x05EF, 0x01C8, 0xD0E9, 0x0000, 0x0000, 0x3122, 0x0477, 0x05F9,
0xB7E3, 0xF80A, 0xFBA8, 0xF635, 0x0000, 0x0000, 0x29F3, 0xF9E9, 0xF981,
0x9EA1, 0x61AE, 0xFE82, 0x3539, 0xFAFF, 0x214C, 0x375D, 0x0000, 0x0000,
0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000,
0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD984, 0x1FB3, 0x3637, 0x0000, 0x0000,
0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC0AA, 0x6A6A, 0xFE71, 0x0000, 0x0000,
0x0000, 0x0000, 0xFD4D, 0x0C2C, 0xFDA0, 0x0000, 0x0000, 0x0000, 0x942B,
0x0399, 0xBF64, 0x0000, 0x0000, 0x0000, 0x050D, 0x039A, 0xCCEF, 0x0000,
0x0000, 0x3C88, 0x0557, 0x068B, 0xB571, 0xF8DE, 0xF9EF, 0xF23F, 0x0000,
0x0000, 0x2CE0, 0xF780, 0xF9FF, 0xA080, 0x61B2, 0xFE6E, 0x3556, 0xFB42,
0x218E, 0x37C8, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C,
0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD972,
0x1F31, 0x36A8, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xBEF9,
0x6A6D, 0xFB18, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD4C, 0x0C31, 0xFD9E,
0x0000, 0x0000, 0x0000, 0x9485, 0x036B, 0xBF8B, 0x0000, 0x0000, 0x0000,
0x03A2, 0x059C, 0xCBA5, 0x0000, 0x0000, 0x4487, 0x063A, 0x0725, 0xB2D8,
0xF9DF, 0xF818, 0xEE47, 0x0000, 0x0000, 0x2E5B, 0xF701, 0xFA1D, 0xA340,
0x61B6, 0xFE5A, 0x3574, 0xFB1E, 0x216B, 0x3790, 0x0000, 0x0000, 0x4DBE,
0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8,
0xF8A1, 0x8BC0, 0xD4DA, 0xD960, 0x1EAF, 0x371A, 0x0000, 0x0000, 0x0000,
0xFB23, 0x0547, 0xC9CE, 0xBDFA, 0x6A7E, 0xF923, 0x0000, 0x0000, 0x0000,
0x0000, 0xFD4D, 0x0C3F, 0xFD9B, 0x0000, 0x0000, 0x0000, 0x94DB, 0x033F,
0xBFAF, 0x0000, 0x0000, 0x0000, 0x021E, 0x0783, 0xCD13, 0x0000, 0x0000,
0x4842, 0x0713, 0x07BC, 0xB04A, 0xFAD8, 0xF65E, 0xEADE, 0x0000, 0x0000,
0x2E4B, 0xF6FD, 0xFA23, 0xA6CE, 0x61BA, 0xFE47, 0x358F, 0xFAC6, 0x2115,
0x3704, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957,
0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD94E, 0x1E34,
0x3784, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xBE13, 0x6A7C,
0xF955, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD4D, 0x0C50, 0xFD98, 0x0000,
0x0000, 0x0000, 0x9527, 0x0318, 0xBFCF, 0x0000, 0x0000, 0x0000, 0x00F9,
0x098E, 0xD2CD, 0x0000, 0x0000, 0x45FA, 0x07D4, 0x0844, 0xADF7, 0xFB87,
0xF4FB, 0xE893, 0x0000, 0x0000, 0x2CAA, 0xF748, 0xFA1B, 0xAA9C, 0x61BD,
0xFE37, 0x35A8, 0xFA53, 0x20A4, 0x364E, 0x0000, 0x0000, 0x4DBE, 0x0000,
0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1,
0x8BC0, 0xD4DA, 0xD93F, 0x1DC8, 0x37E2, 0x0000, 0x0000, 0x0000, 0xFB23,
0x0547, 0xC9CE, 0xBECB, 0x6A70, 0xFAC2, 0x0000, 0x0000, 0x0000, 0x0000,
0xFD4D, 0x0C62, 0xFD95, 0x0000, 0x0000, 0x0000, 0x9565, 0x02F8, 0xBFE8,
0x0000, 0x0000, 0x0000, 0x00C4, 0x0B84, 0xDBCB, 0x0000, 0x0000, 0x3E09,
0x086E, 0x08B3, 0xAC11, 0xFC24, 0xF370, 0xE65E, 0x0000, 0x0000, 0x299C,
0xF7B6, 0xFA0A, 0xAE18, 0x61C0, 0xFE29, 0x35BC, 0xF9E1, 0x2033, 0x3597,
0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97,
0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD933, 0x1D72, 0x382D,
0x0000, 0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xBF9C, 0x6A69, 0xFC60,
0x0000, 0x0000, 0x0000, 0x0000, 0xFD4D, 0x0C70, 0xFD93, 0x0000, 0x0000,
0x0000, 0x958F, 0x02E3, 0xBFF9, 0x0000, 0x0000, 0x0000, 0x019D, 0x0CAF,
0xE462, 0x0000, 0x0000, 0x3400, 0x08D5, 0x08FE, 0xAAC9, 0xFC7A, 0xF1EA,
0xE4AD, 0x0000, 0x0000, 0x251B, 0xF81D, 0xF9FA, 0xB0B2, 0x61C1, 0xFE20,
0x35C9, 0xF988, 0x1FDD, 0x350B, 0x0000, 0x0000, 0x4DBE, 0x0000, 0x0000,
0x0000, 0x453C, 0xF957, 0x2A97, 0x0000, 0x0000, 0xAAD8, 0xF8A1, 0x8BC0,
0xD4DA, 0xD92B, 0x1D3A, 0x385F, 0x0000, 0x0000, 0x0000, 0xFB23, 0x0547,
0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000, 0x0000, 0x0000, 0x0000, 0xFD4D,
0x0C75, 0xFD93, 0x0000, 0x0000, 0x0000, 0x95A0, 0x02DA, 0xC000, 0x0000,
0x0000, 0x0000, 0x024A, 0x0D01, 0xE869, 0x0000, 0x0000, 0x2EA2, 0x08FA,
0x0919, 0xAA50, 0xFC74, 0xF144, 0xE44B, 0x0000, 0x0000, 0x2254, 0xF850,
0xF9F2, 0xB1DA, 0x61C2, 0xFE1D, 0x35CD, 0xF965, 0x1FBA, 0x34D3, 0x0000,
0x0000, 0x4DBE, 0x0000, 0x0000, 0x0000, 0x453C, 0xF957, 0x2A97, 0x0000,
0x0000, 0xAAD8, 0xF8A1, 0x8BC0, 0xD4DA, 0xD928, 0x1D25, 0x3871, 0x0000,
0x0000, 0x0000, 0xFB23, 0x0547, 0xC9CE, 0xC000, 0x6A68, 0xFD26, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000,
};

View file

@ -201,6 +201,13 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
bool stopOnBeatable = false, bool addToPlaythrough = false) {
auto ctx = Rando::Context::GetInstance();
for (auto& exit : region->exits) {
int16_t entranceIndex = exit.GetIndex();
if (!logic->ACProcessUndiscoveredExits && logic->CalculatingAvailableChecks &&
ctx->GetOption(RSK_SHUFFLE_ENTRANCES).Get() && exit.IsShuffled() && entranceIndex != -1 &&
!Entrance_GetIsEntranceDiscovered(entranceIndex)) {
continue;
}
Region* exitRegion = exit.GetConnectedRegion();
// Update Time of Day Access for the exit
if (UpdateToDAccess(&exit, exitRegion)) {
@ -412,18 +419,13 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals
Rando::ItemLocation* location = ctx->GetItemLocation(loc);
RandomizerGet locItem = location->GetPlacedRandomizerGet();
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, gals.calculatingAvailableChecks)) {
if (gals.calculatingAvailableChecks) {
gals.accessibleLocations.push_back(loc);
StopPerformanceTimer(PT_LOCATION_LOGIC);
return false;
}
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, logic->CalculatingAvailableChecks)) {
location->AddToPool();
if (locItem == RG_NONE) {
if (locItem == RG_NONE || logic->CalculatingAvailableChecks) {
gals.accessibleLocations.push_back(loc); // Empty location, consider for placement
} else {
}
if (locItem != RG_NONE) {
// If ignore has a value, we want to check if the item location should be considered or not
// This is necessary due to the below preprocessing for playthrough generation
if (ignore != RG_NONE) {
@ -476,7 +478,7 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
// without the aid of TimePass. During this mode, TimePass won't update ToD access
// in any region.
// RANDOTODO can probably be removed after a ToD rework that accounts for having Dampe time access
if (region->timePass) {
if (region->TimePass()) {
if (region->childDay) {
gals.timePassChildDay = true;
}
@ -519,11 +521,32 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
// Return any of the targetLocations that are accessible in logic
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& targetLocations,
RandomizerGet ignore /* = RG_NONE*/,
bool calculatingAvailableChecks /* = false */) {
bool calculatingAvailableChecks /* = false */,
RandomizerRegion startingRegion /* = RR_ROOT */) {
auto ctx = Rando::Context::GetInstance();
GetAccessibleLocationsStruct gals(0);
gals.calculatingAvailableChecks = calculatingAvailableChecks;
ResetLogic(ctx, gals, !calculatingAvailableChecks);
if (startingRegion != RR_ROOT) {
gals.regionPool.insert(gals.regionPool.begin(), startingRegion);
const auto& region = RegionTable(startingRegion);
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
region->childDay = true;
} else {
region->adultDay = true;
}
if (region->timePass) {
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
region->childNight = true;
} else {
region->adultNight = true;
}
}
}
if (calculatingAvailableChecks) {
logic->Reset(false);
logic->CalculatingAvailableChecks = true;
}
do {
gals.InitLoop();
for (size_t i = 0; i < gals.regionPool.size(); i++) {

View file

@ -58,6 +58,7 @@ struct GetAccessibleLocationsStruct {
void ClearProgress();
void VanillaFill();
int Fill();
void SetAreas();
std::vector<RandomizerCheck> GetEmptyLocations(std::vector<RandomizerCheck> allowedLocations);
@ -65,8 +66,8 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
bool stopOnBeatable = false, bool addToPlaythrough = false);
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& allowedLocations,
RandomizerGet ignore = RG_NONE,
bool calculatingAvailableChecks = false);
RandomizerGet ignore = RG_NONE, bool calculatingAvailableChecks = false,
RandomizerRegion startingRegion = RR_ROOT);
void GeneratePlaythrough();

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,6 @@
#include "soh/Enhancements/debugger/performanceTimer.h"
#include <spdlog/spdlog.h>
#include "../../randomizer/randomizerTypes.h"
#include <boost_custom/container_hash/hash_32.hpp>
namespace {
bool seedChanged;
@ -30,7 +29,7 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
srand(static_cast<uint32_t>(time(NULL)));
// if a blank seed was entered, make a random one
if (seedInput.empty()) {
seedInput = std::to_string(rand() % 0xFFFFFFFF);
seedInput = std::to_string(rand());
} else if (seedInput.rfind("seed_testing_count", 0) == 0 && seedInput.length() > 18) {
int count;
try {
@ -43,8 +42,8 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
}
ctx->SetSeedString(seedInput);
uint32_t seedHash = boost::hash_32<std::string>{}(ctx->GetSeedString());
ctx->SetSeed(seedHash & 0xFFFFFFFF);
uint32_t seedHash = SohUtils::Hash(ctx->GetSeedString());
ctx->SetSeed(seedHash);
ctx->ClearItemLocations();
int ret = Playthrough::Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);

View file

@ -1,7 +1,6 @@
#include "playthrough.hpp"
#include <libultraship/libultraship.h>
#include <boost_custom/container_hash/hash_32.hpp>
#include "fill.hpp"
#include "../location_access.h"
#include "random.hpp"
@ -62,7 +61,7 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
settingsStr += (char*)gBuildVersion;
}
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(ctx->GetSeed()) + settingsStr);
uint32_t finalHash = SohUtils::Hash(std::to_string(ctx->GetSeed()) + settingsStr);
Random_Init(finalHash);
ctx->SetHash(std::to_string(finalHash));
@ -104,9 +103,9 @@ int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<Ran
auto ctx = Rando::Context::GetInstance();
uint32_t repeatedSeed = 0;
for (int i = 0; i < count; i++) {
ctx->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
repeatedSeed = boost::hash_32<std::string>{}(ctx->GetSeedString());
ctx->SetSeed(repeatedSeed % 0xFFFFFFFF);
ctx->SetSeedString(std::to_string(rand()));
repeatedSeed = SohUtils::Hash(ctx->GetSeedString());
ctx->SetSeed(repeatedSeed);
SPDLOG_DEBUG("testing seed: %d", repeatedSeed);
ClearProgress();
Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);

View file

@ -1,40 +1,55 @@
#include "random.hpp"
#include <bit>
#include <random>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <cassert>
static bool init = false;
static boost::random::mt19937 generator;
static uint64_t state = 0;
const uint64_t multiplier = 6364136223846793005ULL;
const uint64_t increment = 11634580027462260723ULL;
// Initialize with seed specified
void Random_Init(uint32_t seed) {
void Random_Init(uint64_t seed) {
init = true;
generator = boost::random::mt19937{ seed };
state = seed;
}
void Random_InitSeed() {
uint32_t next32() {
if (!init) {
// No seed given, get a random number from device to seed
#if !defined(__SWITCH__) && !defined(__WIIU__)
const auto seed = static_cast<uint32_t>(std::random_device{}());
uint64_t seed = static_cast<uint64_t>(std::random_device{}());
#else
uint32_t seed = static_cast<uint32_t>(std::hash<std::string>{}(std::to_string(rand())));
uint64_t seed = static_cast<uint64_t>(std::hash<std::string>{}(std::to_string(rand())));
#endif
Random_Init(seed);
}
state = state * multiplier + increment;
uint32_t xorshifted = static_cast<uint32_t>(((state >> 18) ^ state) >> 27);
uint32_t rot = static_cast<int>(state >> 59);
return std::rotr(xorshifted, rot);
}
// Returns a random unsigned integer in range [min, max-1]
// Returns a random integer in range [min, max-1]
uint32_t Random(uint32_t min, uint32_t max) {
Random_InitSeed();
boost::random::uniform_int_distribution<uint32_t> distribution(min, max - 1);
return distribution(generator);
if (min == max) {
return min;
}
assert(max > min);
uint32_t n = max - min;
uint32_t cutoff = UINT32_MAX - UINT32_MAX % static_cast<uint32_t>(n);
for (;;) {
uint32_t r = next32();
if (r <= cutoff) {
return min + r % n;
}
}
}
// Returns a random floating point number in [0.0, 1.0)
double RandomDouble() {
boost::random::uniform_real_distribution<double> distribution(0.0, 1.0);
return distribution(generator);
return ldexp(next32(), -32);
}

View file

@ -7,7 +7,7 @@
#include <vector>
#include <set>
void Random_Init(uint32_t seed);
void Random_Init(uint64_t seed);
uint32_t Random(uint32_t min, uint32_t max);
double RandomDouble();

File diff suppressed because it is too large Load diff

View file

@ -79,6 +79,9 @@ static void WriteLocation(std::string sphere, const RandomizerCheck locationKey,
default:
jsonData["playthrough"][sphere][location->GetName()] = itemLocation->GetPlacedItemName().GetEnglish();
break;
case LANGUAGE_GER:
jsonData["playthrough"][sphere][location->GetName()] = itemLocation->GetPlacedItemName().GetGerman();
break;
case LANGUAGE_FRA:
jsonData["playthrough"][sphere][location->GetName()] = itemLocation->GetPlacedItemName().GetFrench();
break;
@ -128,6 +131,7 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
switch (gSaveContext.language) {
case LANGUAGE_ENG:
case LANGUAGE_GER:
case LANGUAGE_FRA:
default:
jsonData["entrancesMap"][sphereString][name] = text;
@ -269,6 +273,9 @@ static void WriteAllLocations() {
default:
placedItemName = location->GetPlacedItemName().GetEnglish();
break;
case 1:
placedItemName = location->GetPlacedItemName().GetGerman();
break;
case 2:
placedItemName = location->GetPlacedItemName().GetFrench();
break;
@ -307,6 +314,15 @@ static void WriteAllLocations() {
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]
["trickName"] = ctx->overrides[location->GetRandomizerCheck()].GetTrickName().GetEnglish();
break;
case 1:
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]
["model"] = Rando::StaticData::RetrieveItem(
ctx->overrides[location->GetRandomizerCheck()].LooksLike())
.GetName()
.GetGerman();
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]
["trickName"] = ctx->overrides[location->GetRandomizerCheck()].GetTrickName().GetGerman();
break;
case 2:
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]
["model"] = Rando::StaticData::RetrieveItem(

View file

@ -9,18 +9,16 @@
class Text {
public:
Text() = default;
Text(std::string english_, std::string french_, std::string spanish_)
: english(std::move(english_)), french(std::move(french_)), spanish(std::move(spanish_)),
german(std::move("")) {
// german defaults to english text until a translation is provided.
german = english;
Text(std::string english_, std::string french_, std::string german_)
: english(std::move(english_)), french(std::move(french_)), german(std::move(german_)), spanish(std::move("")) {
// spanish defaults to english text until a translation is provided.
spanish = english;
}
Text(std::string english_, std::string french_, std::string spanish_, std::string german_)
: english(std::move(english_)), french(std::move(french_)), spanish(std::move(spanish_)),
german(std::move(german_)) {
Text(std::string english_, std::string french_, std::string german_, std::string spanish_)
: english(std::move(english_)), french(std::move(french_)), german(std::move(german_)), spanish(std::move("")) {
}
Text(std::string english_)
: english(std::move(english_)), french(std::move("")), spanish(std::move("")), german(std::move("")) {
: english(std::move(english_)), french(std::move("")), german(std::move("")), spanish(std::move("")) {
// default unprovided languages to english text
french = spanish = german = english;
}
@ -36,19 +34,18 @@ class Text {
return english;
}
const std::string& GetSpanish() const {
if (spanish.length() > 0) {
return spanish;
}
return english;
}
const std::string& GetGerman() const {
if (german.length() > 0) {
return german;
}
return english;
}
const std::string& GetSpanish() const {
if (spanish.length() > 0) {
return spanish;
}
return english;
}
const std::string& GetForLanguage(uint8_t language) const {
switch (language) {
@ -64,12 +61,21 @@ class Text {
}
Text operator+(const Text& right) const {
return Text{ english + right.GetEnglish(), french + right.GetFrench(), spanish + right.GetSpanish(),
german + right.GetGerman() };
return Text{
english + right.GetEnglish(),
french + right.GetFrench(),
german + right.GetGerman(),
spanish + right.GetSpanish(),
};
}
Text operator+(const std::string& right) const {
return Text{ english + right, french + right, spanish + right, german + right };
return Text{
english + right,
french + right,
german + right,
spanish + right,
};
}
bool operator==(const Text& right) const {
@ -77,7 +83,7 @@ class Text {
}
bool operator==(const std::string& right) const {
return english == right || french == right || spanish == right || german == right;
return english == right || french == right || german == right || spanish == right;
}
bool operator!=(const Text& right) const {
@ -86,7 +92,7 @@ class Text {
void Replace(std::string oldStr, std::string newStr) {
for (std::string* str : { &english, &french, &spanish, &german }) {
for (std::string* str : { &english, &french, &german, &spanish }) {
size_t position = str->find(oldStr);
while (position != std::string::npos) {
str->replace(position, oldStr.length(), newStr);
@ -106,22 +112,22 @@ class Text {
french.replace(position, oldStr.length(), newText.GetFrench());
position = french.find(oldStr);
}
position = spanish.find(oldStr);
while (position != std::string::npos) {
spanish.replace(position, oldStr.length(), newText.GetSpanish());
position = spanish.find(oldStr);
}
position = german.find(oldStr);
while (position != std::string::npos) {
german.replace(position, oldStr.length(), newText.GetGerman());
position = german.find(oldStr);
}
position = spanish.find(oldStr);
while (position != std::string::npos) {
spanish.replace(position, oldStr.length(), newText.GetSpanish());
position = spanish.find(oldStr);
}
}
// Convert first char to upper case
Text Capitalize(void) const {
Text cap = *this + "";
for (std::string* str : { &cap.english, &cap.french, &cap.spanish, &cap.german }) {
for (std::string* str : { &cap.english, &cap.french, &cap.german, &cap.spanish }) {
(*str)[0] = std::toupper((*str)[0]);
}
return cap;
@ -129,7 +135,7 @@ class Text {
// find the appropriate bars that separate singular from plural
void SetForm(int form) {
for (std::string* str : { &english, &french, &spanish, &german }) {
for (std::string* str : { &english, &french, &german, &spanish }) {
size_t firstBar = str->find('|');
if (firstBar != std::string::npos) {
@ -155,6 +161,6 @@ class Text {
std::string english = "";
std::string french = "";
std::string spanish = "";
std::string german = "";
std::string spanish = "";
};

View file

@ -360,7 +360,7 @@ void Rando::StaticData::RegisterCrateLocations() {
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1518), "Near Impas House Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1));
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1470), "Near Impas House Adult Crate 2", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2));
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-433, -401), "Near Bazaar Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_1));
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-489, -424), "Near Bazaar Adult Crate 2`", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_2));
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-489, -424), "Near Bazaar Adult Crate 2", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_2));
locationTable[RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE] = Location::Crate(RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-724, 871), "Behind GS House Adult Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_BEHIND_GS_HOUSE_ADULT_CRATE));
locationTable[RC_KAK_NEAR_GY_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_GY_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1732, 1366), "Near Graveyard Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GY_CHILD_CRATE));
locationTable[RC_KAK_NEAR_WINDMILL_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_WINDMILL_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1170, 601), "Near Windmill Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_WINDMILL_CHILD_CRATE));

View file

@ -1,18 +1,19 @@
#include "ShuffleFairies.h"
#include "randomizer_grotto.h"
#include "draw.h"
#include "src/overlays/actors/ovl_En_Elf/z_en_elf.h"
#include "src/overlays/actors/ovl_Obj_Bean/z_obj_bean.h"
#include "src/overlays/actors/ovl_En_Gs/z_en_gs.h"
#include "src/overlays/actors/ovl_Shot_Sun/z_shot_sun.h"
#include "../../OTRGlobals.h"
#include "../../cvar_prefixes.h"
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include "static_data.h"
#define FAIRY_FLAG_TIMED (1 << 8)
void ShuffleFairies_DrawRandomizedItem(EnElf* enElf, PlayState* play) {
GetItemEntry randoGetItem = enElf->sohFairyIdentity.itemEntry;
GetItemEntry randoGetItem =
Rando::Context::GetInstance()->GetFinalGIEntry(enElf->sohFairyIdentity.randomizerCheck, true, GI_FAIRY);
if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) {
randoGetItem = GET_ITEM_MYSTERY;
}
@ -60,18 +61,17 @@ FairyIdentity ShuffleFairies_GetFairyIdentity(int32_t params) {
assert(false);
} else {
fairyIdentity.randomizerInf = static_cast<RandomizerInf>(location->GetCollectionCheck().flag);
fairyIdentity.itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(location->GetRandomizerCheck(), true, GI_FAIRY);
fairyIdentity.randomizerCheck = location->GetRandomizerCheck();
}
return fairyIdentity;
}
bool ShuffleFairies_SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params) {
static bool SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params, FairyType fairyType) {
FairyIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params);
if (!Flags_GetRandomizerInf(fairyIdentity.randomizerInf)) {
EnElf* fairy = (EnElf*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ELF, posX, posY - 30.0f, posZ, 0,
0, 0, FAIRY_HEAL, true);
0, 0, fairyType, true);
fairy->sohFairyIdentity = fairyIdentity;
fairy->actor.draw = (ActorFunc)ShuffleFairies_DrawRandomizedItem;
return true;
@ -79,58 +79,62 @@ bool ShuffleFairies_SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params) {
return false;
}
void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) {
va_list args;
va_copy(args, originalArgs);
Actor* actor = va_arg(args, Actor*);
va_end(args);
void RegisterShuffleFairies() {
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_FAIRIES);
// Grant item when picking up fairy.
if (id == VB_FAIRY_HEAL) {
EnElf* enElf = (EnElf*)(actor);
COND_VB_SHOULD(VB_FAIRY_HEAL, shouldRegister, {
EnElf* enElf = va_arg(args, EnElf*);
if (enElf->sohFairyIdentity.randomizerInf && enElf->sohFairyIdentity.randomizerInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(enElf->sohFairyIdentity.randomizerInf);
}
});
// Spawn fairies in fairy fountains
} else if (id == VB_SPAWN_FOUNTAIN_FAIRIES) {
COND_VB_SHOULD(VB_SPAWN_FOUNTAIN_FAIRIES, shouldRegister, {
Actor* actor = va_arg(args, Actor*);
bool fairySpawned = false;
s16 grottoId = (gPlayState->sceneNum == SCENE_FAIRYS_FOUNTAIN) ? Grotto_CurrentGrotto() : 0;
for (s16 index = 0; index < 8; index++) {
int32_t params = (grottoId << 8) | index;
if (ShuffleFairies_SpawnFairy(actor->world.pos.x, actor->world.pos.y, actor->world.pos.z, params)) {
if (SpawnFairy(actor->world.pos.x, actor->world.pos.y, actor->world.pos.z, params, FAIRY_HEAL)) {
fairySpawned = true;
}
}
if (fairySpawned) {
*should = false;
}
});
// Spawn 3 fairies when playing Song of Storms next to a planted bean
} else if (id == VB_SPAWN_BEAN_STALK_FAIRIES) {
ObjBean* objBean = (ObjBean*)(actor);
COND_VB_SHOULD(VB_SPAWN_BEAN_STALK_FAIRIES, shouldRegister, {
ObjBean* objBean = va_arg(args, ObjBean*);
bool fairySpawned = false;
for (s16 index = 0; index < 3; index++) {
int32_t params = ((objBean->dyna.actor.params & 0x3F) << 8) | index;
if (ShuffleFairies_SpawnFairy(objBean->dyna.actor.world.pos.x, objBean->dyna.actor.world.pos.y,
objBean->dyna.actor.world.pos.z, params)) {
if (SpawnFairy(objBean->dyna.actor.world.pos.x, objBean->dyna.actor.world.pos.y,
objBean->dyna.actor.world.pos.z, params, FAIRY_HEAL)) {
fairySpawned = true;
}
}
if (fairySpawned) {
*should = false;
}
});
// Spawn a fairy from a ShotSun when playing the right song near it
} else if (id == VB_SPAWN_SONG_FAIRY) {
ShotSun* shotSun = (ShotSun*)(actor);
if (ShuffleFairies_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))) {
COND_VB_SHOULD(VB_SPAWN_SONG_FAIRY, shouldRegister, {
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)) {
*should = false;
}
});
// Handle playing both misc songs and song of storms in front of a gossip stone.
} else if (id == VB_SPAWN_GOSSIP_STONE_FAIRY) {
EnGs* gossipStone = (EnGs*)(actor);
COND_VB_SHOULD(VB_SPAWN_GOSSIP_STONE_FAIRY, shouldRegister, {
EnGs* gossipStone = va_arg(args, EnGs*);
FairyType fairyType = FAIRY_HEAL;
// Mimic vanilla behaviour, only go into this path if song played is one of the ones normally spawning a fairy.
// Otherwise fall back to vanilla behaviour.
@ -144,6 +148,7 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
// Distinguish storms fairies from the normal song fairies
if (gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS) {
params |= 0x1000;
fairyType = FAIRY_HEAL_BIG;
}
// Combine actor + song params with position to get the right randomizer check
@ -156,8 +161,8 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
// collected, the vanilla code will handle that part automatically.
FairyIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params);
if (!ShuffleFairies_FairyExists(fairyIdentity)) {
if (ShuffleFairies_SpawnFairy(gossipStone->actor.world.pos.x, gossipStone->actor.world.pos.y,
gossipStone->actor.world.pos.z, params)) {
if (SpawnFairy(gossipStone->actor.world.pos.x, gossipStone->actor.world.pos.y,
gossipStone->actor.world.pos.z, params, fairyType)) {
Audio_PlayActorSound2(&gossipStone->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY);
// Set vanilla check for fairy spawned so it doesn't spawn the vanilla fairy afterwards as well.
gossipStone->unk_19D = 0;
@ -167,20 +172,7 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
*should = false;
}
}
}
}
uint32_t onVanillaBehaviorHook = 0;
void ShuffleFairies_RegisterHooks() {
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(
ShuffleFairies_OnVanillaBehaviorHandler);
}
void ShuffleFairies_UnregisterHooks() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(onVanillaBehaviorHook);
onVanillaBehaviorHook = 0;
});
}
void Rando::StaticData::RegisterFairyLocations() {
@ -412,4 +404,5 @@ void Rando::StaticData::RegisterFairyLocations() {
// clang-format on
}
static RegisterShipInitFunc initFunc(Rando::StaticData::RegisterFairyLocations);
static RegisterShipInitFunc registerShuffleFairies(RegisterShuffleFairies, { "IS_RANDO" });
static RegisterShipInitFunc registerShuffleFairiesLocations(Rando::StaticData::RegisterFairyLocations);

View file

@ -1,13 +0,0 @@
#pragma once
#include <z64.h>
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include "randomizerTypes.h"
typedef struct FairyIdentity {
RandomizerInf randomizerInf;
GetItemEntry itemEntry;
} FairyIdentity;
void ShuffleFairies_RegisterHooks();
void ShuffleFairies_UnregisterHooks();

View file

@ -1,17 +1,17 @@
#include "ShuffleFreestanding.h"
#include <soh/OTRGlobals.h>
extern "C" {
#include "variables.h"
#include "functions.h"
extern PlayState* gPlayState;
}
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) {
va_list args;
va_copy(args, originalArgs);
void RegisterShuffleFreestanding() {
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_FREESTANDING);
if (id == VB_ITEM00_DESPAWN) {
COND_VB_SHOULD(VB_ITEM00_DESPAWN, shouldRegister, {
EnItem00* item00 = va_arg(args, EnItem00*);
// Heart pieces and small keys are handled by default non-freestanding shuffles.
@ -22,14 +22,16 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
uint32_t params = TWO_ACTOR_PARAMS((int32_t)item00->actor.world.pos.x, (int32_t)item00->actor.world.pos.z);
Rando::Location* loc =
OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
if (Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained()) {
return;
}
uint8_t isDungeon = loc->IsDungeon();
uint8_t freestandingSetting = RAND_GET_OPTION(RSK_SHUFFLE_FREESTANDING);
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained();
// Don't change to randomized item if current freestanding item isn't shuffled or already obtained.
if ((freestandingSetting == RO_SHUFFLE_FREESTANDING_OVERWORLD && isDungeon) ||
(freestandingSetting == RO_SHUFFLE_FREESTANDING_DUNGEONS && !isDungeon) || checkObtained ||
(freestandingSetting == RO_SHUFFLE_FREESTANDING_DUNGEONS && !isDungeon) ||
randomizerCheck == RC_UNKNOWN_CHECK) {
return;
}
@ -41,7 +43,7 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
*should = false;
}
});
}
void Rando::StaticData::RegisterFreestandingLocations() {
@ -284,4 +286,5 @@ void Rando::StaticData::RegisterFreestandingLocations() {
// clang-format on
}
static RegisterShipInitFunc initFunc(Rando::StaticData::RegisterFreestandingLocations);
static RegisterShipInitFunc registerShuffleFreestanding(RegisterShuffleFreestanding, { "IS_RANDO" });
static RegisterShipInitFunc registerShuffleFreestandingLocations(Rando::StaticData::RegisterFreestandingLocations);

View file

@ -1,9 +0,0 @@
#ifndef SHUFFLE_FREESTANDING_H
#define SHUFFLE_FREESTANDING_H
#include <z64.h>
#include <soh/OTRGlobals.h>
void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs);
#endif

View file

@ -1,4 +1,4 @@
#include "ShufflePots.h"
#include "soh/OTRGlobals.h"
#include "soh_assets.h"
#include "static_data.h"
@ -51,48 +51,44 @@ void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor, PlayState* play) {
item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
}
void ObjTsubo_RandomizerInit(void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef);
void RegisterShufflePots() {
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_POTS);
COND_ID_HOOK(OnActorInit, ACTOR_OBJ_TSUBO, shouldRegister, [](void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef);
ObjTsubo* potActor = static_cast<ObjTsubo*>(actorRef);
potActor->potIdentity = OTRGlobals::Instance->gRandomizer->IdentifyPot(
gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z);
}
void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) {
va_list args;
va_copy(args, originalArgs);
});
// Draw custom model for pot to indicate it holding a randomized item.
if (id == VB_POT_SETUP_DRAW) {
COND_VB_SHOULD(VB_POT_SETUP_DRAW, shouldRegister, {
ObjTsubo* potActor = va_arg(args, ObjTsubo*);
if (ObjTsubo_RandomizerHoldsItem(potActor, gPlayState)) {
potActor->actor.draw = (ActorFunc)ObjTsubo_RandomizerDraw;
*should = false;
}
}
});
// Do not spawn vanilla item from pot, instead spawn the ranomized item.
if (id == VB_POT_DROP_ITEM) {
COND_VB_SHOULD(VB_POT_DROP_ITEM, shouldRegister, {
ObjTsubo* potActor = va_arg(args, ObjTsubo*);
if (ObjTsubo_RandomizerHoldsItem(potActor, gPlayState)) {
ObjTsubo_RandomizerSpawnCollectible(potActor, gPlayState);
*should = false;
}
}
});
// Unlock early Ganon's Boss Key doors to allow access to the pots there when pots are shuffled in dungeon
if (id == VB_LOCK_BOSS_DOOR) {
COND_VB_SHOULD(VB_LOCK_BOSS_DOOR, shouldRegister, {
DoorShutter* doorActor = va_arg(args, DoorShutter*);
uint8_t shufflePotSetting = RAND_GET_OPTION(RSK_SHUFFLE_POTS);
if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 &&
(shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) {
*should = false;
}
}
va_end(args);
});
}
void Rando::StaticData::RegisterPotLocations() {
@ -545,7 +541,7 @@ void Rando::StaticData::RegisterPotLocations() {
locationTable[RC_BOTTOM_OF_THE_WELL_MQ_OUTER_LOBBY_POT] = Location::Pot(RC_BOTTOM_OF_THE_WELL_MQ_OUTER_LOBBY_POT, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(421, -174), "MQ Outer Lobby Pot", RHT_POT_BOTTOM_OF_THE_WELL, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_OUTER_LOBBY_POT));
locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_1] = Location::Pot(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_1, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(288, -1240), "MQ East Inner Pot 1", RHT_POT_BOTTOM_OF_THE_WELL, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_SOUTH_KEY_POT_1));
locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_2] = Location::Pot(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_2, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(438, -1234), "MQ East Inner Pot 2", RHT_POT_BOTTOM_OF_THE_WELL, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_SOUTH_KEY_POT_2));
locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_3] = Location::Pot(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_3, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(443, -1114), "MQ East Inner Pot 3", RHT_POT_BOTTOM_OF_THE_WELL, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_SOUTH_KEY_POT_3));
locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_3] = Location::Pot(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_3, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(444, -1114), "MQ East Inner Pot 3", RHT_POT_BOTTOM_OF_THE_WELL, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_MQ_SOUTH_KEY_POT_3));
locationTable[RC_FIRE_TEMPLE_MQ_ENTRANCE_POT_1] = Location::Pot(RC_FIRE_TEMPLE_MQ_ENTRANCE_POT_1, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, TWO_ACTOR_PARAMS(-357, 957), "MQ Entrance Pot 1", RHT_POT_FIRE_TEMPLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TEMPLE_MQ_ENTRANCE_POT_1));
locationTable[RC_FIRE_TEMPLE_MQ_ENTRANCE_POT_2] = Location::Pot(RC_FIRE_TEMPLE_MQ_ENTRANCE_POT_2, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, TWO_ACTOR_PARAMS(356, 959), "MQ Entrance Pot 2", RHT_POT_FIRE_TEMPLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TEMPLE_MQ_ENTRANCE_POT_2));
locationTable[RC_FIRE_TEMPLE_MQ_BEFORE_MINI_BOSS_POT_1] = Location::Pot(RC_FIRE_TEMPLE_MQ_BEFORE_MINI_BOSS_POT_1, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, TWO_ACTOR_PARAMS(187, -1449), "MQ Before Mini Boss Pot 1", RHT_POT_FIRE_TEMPLE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TEMPLE_MQ_BEFORE_MINI_BOSS_POT_1));
@ -653,4 +649,5 @@ void Rando::StaticData::RegisterPotLocations() {
// clang-format on
}
static RegisterShipInitFunc initFunc(Rando::StaticData::RegisterPotLocations);
static RegisterShipInitFunc registerShufflePots(RegisterShufflePots, { "IS_RANDO" });
static RegisterShipInitFunc registerShufflePotLocations(Rando::StaticData::RegisterPotLocations);

View file

@ -1,17 +0,0 @@
#ifndef SHUFFLEPOTS_H
#define SHUFFLEPOTS_H
#include <z64.h>
#include <soh/OTRGlobals.h>
#ifdef __cplusplus
extern "C" {
#endif
void ObjTsubo_RandomizerInit(void* actorRef);
#ifdef __cplusplus
};
#endif
void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs);
#endif // SHUFFLEPOTS_H

View file

@ -11,6 +11,7 @@
#include "fishsanity.h"
#include "macros.h"
#include "3drando/hints.hpp"
#include "soh/util.h"
#include "../kaleido.h"
#include <fstream>
@ -370,25 +371,8 @@ GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool check
return giEntry;
}
std::string sanitize(std::string stringValue) {
// Add backslashes.
for (auto i = stringValue.begin();;) {
auto const pos =
std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; });
if (pos == stringValue.end()) {
break;
}
i = std::next(stringValue.insert(pos, '\\'), 2);
}
// Removes others.
std::erase_if(stringValue, [](char const c) { return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; });
return stringValue;
}
void Context::ParseSpoiler(const char* spoilerFileName) {
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
if (!spoilerFileStream) {
return;
}
@ -397,11 +381,13 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
try {
nlohmann::json spoilerFileJson;
spoilerFileStream >> spoilerFileJson;
spoilerFileStream.close();
ParseHashIconIndexesJson(spoilerFileJson);
Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
ParseItemLocationsJson(spoilerFileJson);
ParseHintJson(spoilerFileJson);
ParseTricksJson(spoilerFileJson);
mEntranceShuffler->ParseJson(spoilerFileJson);
ParseHintJson(spoilerFileJson);
mDungeons->ParseJson(spoilerFileJson);
mTrials->ParseJson(spoilerFileJson);
mSpoilerLoaded = true;
@ -469,6 +455,17 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
CreateStaticHints();
}
void Context::ParseTricksJson(nlohmann::json spoilerFileJson) {
nlohmann::json enabledTricksJson = spoilerFileJson["enabledTricks"];
const auto& settings = Rando::Settings::GetInstance();
for (auto it : enabledTricksJson) {
int rt = settings->GetRandomizerTrickByName(it);
if (rt != -1) {
mTrickOptions[rt].Set(RO_GENERIC_ON);
}
}
}
std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
return mEntranceShuffler;
}
@ -524,6 +521,10 @@ RandoOptionLACSCondition Context::LACSCondition() const {
return mLACSCondition;
}
void Context::LACSCondition(RandoOptionLACSCondition lacsCondition) {
mLACSCondition = lacsCondition;
}
std::shared_ptr<Kaleido> Context::GetKaleido() {
if (mKaleido == nullptr) {
mKaleido = std::make_shared<Kaleido>();

View file

@ -106,12 +106,22 @@ class Context {
* @return RandoOptionLACSCondition
*/
RandoOptionLACSCondition LACSCondition() const;
/**
* @brief Sets the resolved Light Arrow CutScene check condition.
* There is no direct option for this, it is inferred based on the value of a few other options.
*
* @param lacsCondition
*/
void LACSCondition(RandoOptionLACSCondition lacsCondition);
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
void ParseSpoiler(const char* spoilerFileName);
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
void ParseItemLocationsJson(nlohmann::json spoilerFileJson);
void WriteHintJson(nlohmann::ordered_json& spoilerFileJson);
void ParseHintJson(nlohmann::json spoilerFileJson);
void ParseTricksJson(nlohmann::json spoilerFileJson);
std::map<RandomizerCheck, ItemOverride> overrides = {};
std::vector<std::vector<RandomizerCheck>> playthroughLocations = {};
std::vector<RandomizerCheck> everyPossibleLocation = {};

View file

@ -250,7 +250,319 @@ std::string EntranceNameByRegions(RandomizerRegion parentRegion, RandomizerRegio
return RegionTable(parentRegion)->regionName + " -> " + RegionTable(connectedRegion)->regionName;
}
void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
std::unordered_map<int16_t, Entrance*> entranceMap;
void SetAllEntrancesData() {
std::vector<EntranceInfoPair> entranceShuffleTable = {
// clang-format off
// Type Parent Region Connected Region Index
{ { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, ENTR_DEKU_TREE_ENTRANCE },
{ EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE } },
{ { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, ENTR_DODONGOS_CAVERN_ENTRANCE },
{ EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN } },
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, ENTR_JABU_JABU_ENTRANCE },
{ EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } },
{ { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_LH_FROM_WATER_TEMPLE, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, ENTR_SHADOW_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE },
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } },
{ { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE },
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } },
{ { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE },
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } },
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE },
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, ENTR_TWINS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, ENTR_KOKIRI_SHOP_0 },
{ EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP } },
{ { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, ENTR_LAKESIDE_LABORATORY_0 },
{ EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_LAB } },
{ { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_POND, ENTR_FISHING_POND_0 },
{ EntranceType::Interior, RR_LH_FISHING_POND, RR_LH_FISHING_ISLAND, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND } },
{ { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, ENTR_CARPENTERS_TENT_0 },
{ EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_OUTSIDE_TENT } },
{ { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0 },
{ EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0 },
{ EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0 },
{ EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0 },
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, ENTR_TREASURE_BOX_SHOP_0 },
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1 },
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE },
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0 },
{ EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, ENTR_HOUSE_OF_SKULLTULA_0 },
{ EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, ENTR_IMPAS_HOUSE_FRONT },
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT } },
{ { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK },
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK } },
{ { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, ENTR_POTION_SHOP_GRANNY_0 },
{ EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY } },
{ { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, ENTR_GRAVEKEEPERS_HUT_0 },
{ EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT } },
{ { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, ENTR_GORON_SHOP_0 },
{ EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, ENTR_GORON_CITY_OUTSIDE_SHOP } },
{ { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, ENTR_ZORA_SHOP_0 },
{ EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE },
{ EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, ENTR_STABLE_0 },
{ EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_STABLES } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, ENTR_LON_LON_BUILDINGS_TOWER },
{ EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TOWER } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, ENTR_BAZAAR_1 },
{ EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BAZAAR } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1 },
{ EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, ENTR_BAZAAR_0 },
{ EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0 },
{ EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY } },
{ { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS },
{ EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC },
{ EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD },
// 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy
// fountain exits (normally they both use 0x340)
{ EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_POTION_SHOP_KAKARIKO_1 } },
{ { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC },
{ EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT },
{ EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF },
{ EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY } },
{ { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 },
{ EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } },
{ { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_ENTRANCE },
{ EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE } },
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL },
{ EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL } },
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT },
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT } },
{ { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK },
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK } },
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
{ { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET) },
{ EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET) },
{ EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET) },
{ EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) },
{ EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) },
{ EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET) },
{ EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET) },
{ EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) },
{ EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET) },
{ EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) },
{ EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN_ISLAND, RR_ZD_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN_ISLAND, ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET) },
{ EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET) },
{ EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET) } },
// Graves have their own specified entrance indices
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0 },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, ENTR_REDEAD_GRAVE_0 },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, ENTR_ROYAL_FAMILYS_TOMB_0 },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT } },
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT },
{ EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_LOWER_EXIT } },
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT },
{ EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_UPPER_EXIT } },
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, ENTR_GORON_CITY_TUNNEL_SHORTCUT },
{ EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_TUNNEL_SHORTCUT } },
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZR_FROM_SHORTCUT, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT },
{ EntranceType::Overworld, RR_ZR_FROM_SHORTCUT, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT } },
{ { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT },
{ EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, ENTR_LOST_WOODS_NORTH_EXIT } },
{ { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_WOODED_EXIT },
{ EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT },
{ EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_FENCE_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, ENTR_GERUDO_VALLEY_EAST_EXIT },
{ EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ROCKY_PATH } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT },
{ EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_FRONT_GATE },
{ EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_STAIRS_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, ENTR_ZORAS_RIVER_WEST_EXIT },
{ EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_RIVER_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_ENTRANCE },
{ EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_CENTER_EXIT } },
{ { EntranceType::Overworld, RR_LH_FROM_SHORTCUT, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT },
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LH_FROM_SHORTCUT, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT } },
{ { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_EAST_EXIT },
{ EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_WEST_EXIT } },
{ { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, ENTR_HAUNTED_WASTELAND_EAST_EXIT },
{ EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, ENTR_GERUDOS_FORTRESS_GATE_EXIT } },
{ { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_EAST_EXIT },
{ EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, ENTR_HAUNTED_WASTELAND_WEST_EXIT } },
{ { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_SOUTH_EXIT },
{ EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NORTH_EXIT } },
{ { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_SOUTH_EXIT },
{ EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, ENTR_MARKET_DAY_CASTLE_EXIT } },
{ { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT },
{ EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_DAY_TEMPLE_EXIT } },
{ { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ENTRANCE },
{ EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT } },
{ { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT },
{ EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, ENTR_KAKARIKO_VILLAGE_GUARD_GATE } },
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, ENTR_GORON_CITY_UPPER_EXIT },
{ EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT } },
{ { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT },
{ EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } },
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT },
{ EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } },
{ { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_ENTRANCE },
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, ENTR_ZORAS_RIVER_WATERFALL_EXIT } },
{ { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT },
{ EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT } },
{ { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_RIVER_EXIT },
NO_RETURN_ENTRANCE },
{ { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_OWL_DROP },
NO_RETURN_ENTRANCE },
{ { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, ENTR_KAKARIKO_VILLAGE_OWL_DROP },
NO_RETURN_ENTRANCE },
{ { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_CHILD_SPAWN },
NO_RETURN_ENTRANCE },
{ { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, ENTR_HYRULE_FIELD_10 },
NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between
// Adult Spawn and prelude of light (normally they both use 0x5F4)
{ { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, ENTR_DEKU_TREE_BOSS_ENTRANCE },
{ EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT, ENTR_DEKU_TREE_BOSS_DOOR } },
{ { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE },
{ EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT, ENTR_DODONGOS_CAVERN_BOSS_DOOR } },
{ { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, ENTR_JABU_JABU_BOSS_ENTRANCE },
{ EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT, ENTR_JABU_JABU_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, ENTR_FOREST_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, ENTR_FIRE_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, ENTR_WATER_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, ENTR_WATER_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, ENTR_SPIRIT_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, ENTR_SHADOW_TEMPLE_BOSS_DOOR } },
{ { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
// clang-format on
};
auto ctx = Rando::Context::GetInstance();
for (auto& entrancePair : entranceShuffleTable) {
@ -262,6 +574,7 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
forwardEntrance->SetIndex(forwardEntry.index);
forwardEntrance->SetType(forwardEntry.type);
forwardEntrance->SetAsPrimary();
entranceMap[forwardEntry.index] = forwardEntrance;
// When decouple entrances is on, mark the forward entrance
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
@ -273,6 +586,7 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
returnEntrance->SetIndex(returnEntry.index);
returnEntrance->SetType(returnEntry.type);
forwardEntrance->BindTwoWay(returnEntrance);
entranceMap[returnEntry.index] = returnEntrance;
// Mark reverse entrance as decoupled
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
@ -352,8 +666,21 @@ std::vector<Entrance*> EntranceShuffler::AssumeEntrancePool(std::vector<Entrance
static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::vector<EntrancePair>& rollbacks) {
// Entrances shouldn't connect to their own scene, fail in this situation
if (entrance->GetParentRegion()->scene != "" &&
entrance->GetParentRegion()->scene == target->GetConnectedRegion()->scene) {
if (
// allow "special" areas to connect to eachother
entrance->GetParentRegion()->scene != SCENE_ID_MAX &&
// allow grottos and fairy fountains to connect to eachother
entrance->GetParentRegion()->scene != SCENE_GROTTOS &&
entrance->GetParentRegion()->scene != SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC &&
entrance->GetParentRegion()->scene != SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS &&
(entrance->GetParentRegion()->scene == target->GetConnectedRegion()->scene ||
// prevent SCENE_HYRULE_CASTLE & SCENE_OUTSIDE_GANONS_CASTLE from connecting to eachother
(entrance->GetParentRegion()->scene == SCENE_HYRULE_CASTLE &&
target->GetConnectedRegion()->scene == SCENE_OUTSIDE_GANONS_CASTLE) ||
(entrance->GetParentRegion()->scene == SCENE_OUTSIDE_GANONS_CASTLE &&
target->GetConnectedRegion()->scene == SCENE_HYRULE_CASTLE))) {
auto message = "Entrance " + entrance->GetName() + " attempted to connect with own scene target " +
target->to_string() + ". Connection failed.\n";
SPDLOG_DEBUG(message);
@ -842,316 +1169,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
mTotalRandomizableEntrances = 0;
mCurNumRandomizedEntrances = 0;
std::vector<EntranceInfoPair> entranceShuffleTable = {
// clang-format off
// Type Parent Region Connected Region Index
{ { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, ENTR_DEKU_TREE_ENTRANCE },
{ EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE } },
{ { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, ENTR_DODONGOS_CAVERN_ENTRANCE },
{ EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN } },
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, ENTR_JABU_JABU_ENTRANCE },
{ EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } },
{ { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, ENTR_SHADOW_TEMPLE_ENTRANCE },
{ EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_OUTSIDE_TEMPLE } },
{ { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE },
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } },
{ { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE },
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } },
{ { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE },
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } },
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE },
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, ENTR_TWINS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0 },
{ EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, ENTR_KOKIRI_SHOP_0 },
{ EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP } },
{ { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, ENTR_LAKESIDE_LABORATORY_0 },
{ EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_LAB } },
{ { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_POND, ENTR_FISHING_POND_0 },
{ EntranceType::Interior, RR_LH_FISHING_POND, RR_LH_FISHING_ISLAND, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND } },
{ { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, ENTR_CARPENTERS_TENT_0 },
{ EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_OUTSIDE_TENT } },
{ { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0 },
{ EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0 },
{ EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0 },
{ EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0 },
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, ENTR_TREASURE_BOX_SHOP_0 },
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1 },
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE },
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0 },
{ EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, ENTR_HOUSE_OF_SKULLTULA_0 },
{ EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, ENTR_IMPAS_HOUSE_FRONT },
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT } },
{ { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK },
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK } },
{ { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, ENTR_POTION_SHOP_GRANNY_0 },
{ EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY } },
{ { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, ENTR_GRAVEKEEPERS_HUT_0 },
{ EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT } },
{ { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, ENTR_GORON_SHOP_0 },
{ EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, ENTR_GORON_CITY_OUTSIDE_SHOP } },
{ { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, ENTR_ZORA_SHOP_0 },
{ EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE },
{ EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, ENTR_STABLE_0 },
{ EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_STABLES } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, ENTR_LON_LON_BUILDINGS_TOWER },
{ EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TOWER } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, ENTR_BAZAAR_1 },
{ EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BAZAAR } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1 },
{ EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, ENTR_BAZAAR_0 },
{ EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0 },
{ EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY } },
{ { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS },
{ EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC },
{ EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD },
// 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy
// fountain exits (normally they both use 0x340)
{ EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_POTION_SHOP_KAKARIKO_1 } },
{ { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC },
{ EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT },
{ EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT } },
{ { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF },
{ EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY } },
{ { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 },
{ EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } },
{ { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_ENTRANCE },
{ EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE } },
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL },
{ EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL } },
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT },
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT } },
{ { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK },
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK } },
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
{ { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET) },
{ EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET) },
{ EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET) },
{ EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) },
{ EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) },
{ EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) },
{ EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET) },
{ EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET) },
{ EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET) },
{ EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) },
{ EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET) },
{ EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) },
{ EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN_ISLAND, RR_ZD_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN_ISLAND, ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET) },
{ EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET) },
{ EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET) } },
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET) },
{ EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET) } },
// Graves have their own specified entrance indices
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0 },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, ENTR_REDEAD_GRAVE_0 },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, ENTR_ROYAL_FAMILYS_TOMB_0 },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT } },
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT },
{ EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_LOWER_EXIT } },
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT },
{ EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_UPPER_EXIT } },
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, ENTR_GORON_CITY_TUNNEL_SHORTCUT },
{ EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_TUNNEL_SHORTCUT } },
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZORAS_RIVER, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT },
{ EntranceType::Overworld, RR_ZORAS_RIVER, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT } },
{ { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT },
{ EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, ENTR_LOST_WOODS_NORTH_EXIT } },
{ { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_WOODED_EXIT },
{ EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT },
{ EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_FENCE_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, ENTR_GERUDO_VALLEY_EAST_EXIT },
{ EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ROCKY_PATH } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT },
{ EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_FRONT_GATE },
{ EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_STAIRS_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, ENTR_ZORAS_RIVER_WEST_EXIT },
{ EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_RIVER_EXIT } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_ENTRANCE },
{ EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_CENTER_EXIT } },
{ { EntranceType::Overworld, RR_LAKE_HYLIA, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT },
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT } },
{ { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_EAST_EXIT },
{ EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_WEST_EXIT } },
{ { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, ENTR_HAUNTED_WASTELAND_EAST_EXIT },
{ EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, ENTR_GERUDOS_FORTRESS_GATE_EXIT } },
{ { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_EAST_EXIT },
{ EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, ENTR_HAUNTED_WASTELAND_WEST_EXIT } },
{ { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_SOUTH_EXIT },
{ EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NORTH_EXIT } },
{ { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_SOUTH_EXIT },
{ EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, ENTR_MARKET_DAY_CASTLE_EXIT } },
{ { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT },
{ EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_DAY_TEMPLE_EXIT } },
{ { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ENTRANCE },
{ EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT } },
{ { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT },
{ EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, ENTR_KAKARIKO_VILLAGE_GUARD_GATE } },
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, ENTR_GORON_CITY_UPPER_EXIT },
{ EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT } },
{ { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT },
{ EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } },
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT },
{ EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } },
{ { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_ENTRANCE },
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, ENTR_ZORAS_RIVER_WATERFALL_EXIT } },
{ { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT },
{ EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT } },
{ { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_RIVER_EXIT },
NO_RETURN_ENTRANCE },
{ { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_OWL_DROP },
NO_RETURN_ENTRANCE },
{ { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, ENTR_KAKARIKO_VILLAGE_OWL_DROP },
NO_RETURN_ENTRANCE },
{ { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_CHILD_SPAWN },
NO_RETURN_ENTRANCE },
{ { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, ENTR_HYRULE_FIELD_10 },
NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between
// Adult Spawn and prelude of light (normally they both use 0x5F4)
{ { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_WARP_PAD },
NO_RETURN_ENTRANCE },
{ { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, ENTR_DEKU_TREE_BOSS_ENTRANCE },
{ EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY, ENTR_DEKU_TREE_BOSS_DOOR } },
{ { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE },
{ EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, ENTR_DODONGOS_CAVERN_BOSS_DOOR } },
{ { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, ENTR_JABU_JABU_BOSS_ENTRANCE },
{ EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, ENTR_JABU_JABU_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, ENTR_FOREST_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, ENTR_FIRE_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, ENTR_WATER_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, ENTR_WATER_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, ENTR_SPIRIT_TEMPLE_BOSS_DOOR } },
{ { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE },
{ EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, ENTR_SHADOW_TEMPLE_BOSS_DOOR } },
{ { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
{ { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP },
NO_RETURN_ENTRANCE },
// clang-format on
};
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
{ "Bolero", { { RR_DMC_CENTRAL_LOCAL }, { EntranceType::OwlDrop, EntranceType::WarpSong } } },
{ "Nocturne",
@ -1163,7 +1180,7 @@ int EntranceShuffler::ShuffleAllEntrances() {
};
mEntranceShuffleFailure = false;
SetAllEntrancesData(entranceShuffleTable);
SetAllEntrancesData();
EntrancePools oneWayEntrancePools = {};
EntrancePools entrancePools = {};
@ -1473,18 +1490,18 @@ int EntranceShuffler::ShuffleAllEntrances() {
if (true /* ctx->GetOption(RSK_SHUFFLE_BLUEWARP_ENTRANCES).Is(RO_BLUEWARP_ENTRANCE_SHUFFLE_DUNGEON) */) {
// If a boss room is inside a boss door, make the blue warp go outside the dungeon's entrance
std::map<std::string, Entrance*> bossExits = {
{ EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY),
{ EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT),
GetEntrance(RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE) },
{ EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY),
{ EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT),
GetEntrance(RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL) },
{ EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY),
{ EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT),
GetEntrance(RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN) },
{ EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY),
GetEntrance(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW) },
{ EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY),
GetEntrance(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL) },
{ EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY),
GetEntrance(RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA) },
GetEntrance(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE) },
{ EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY),
GetEntrance(RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE) },
{ EntranceNameByRegions(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY),
@ -1504,7 +1521,7 @@ int EntranceShuffler::ShuffleAllEntrances() {
GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW) },
{ EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL),
GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL) },
{ EntranceNameByRegions(RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA),
{ EntranceNameByRegions(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE),
GetEntrance(RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA) },
{ EntranceNameByRegions(RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE),
GetEntrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS) },
@ -1515,11 +1532,11 @@ int EntranceShuffler::ShuffleAllEntrances() {
// Pair <BlueWarp exit, BossRoom reverse exit>
std::vector<EntrancePair> bossRoomExitPairs = {
{ GetEntrance(RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE),
GetEntrance(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY) },
GetEntrance(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT) },
{ GetEntrance(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL),
GetEntrance(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY) },
GetEntrance(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT) },
{ GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN),
GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY) },
GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT) },
{ GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW),
GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY) },
{ GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL),
@ -1647,6 +1664,30 @@ void EntranceShuffler::ParseJson(nlohmann::json spoilerFileJson) {
}
}
} catch (const std::exception& e) { throw e; }
// We may need to reset more things here or elsewhere in spoiler loading
RegionTable_Init();
ApplyEntranceOverrides();
SetAreas();
}
void EntranceShuffler::ApplyEntranceOverrides() {
SetAllEntrancesData();
for (size_t i = 0; i < entranceOverrides.size(); i++) {
EntranceOverride entranceOverride = entranceOverrides[i];
if (entranceOverride.index == 0 && entranceOverride.destination == 0 && entranceOverride.override == 0 &&
entranceOverride.overrideDestination == 0) {
continue;
}
Entrance* entrance = entranceMap[entranceOverride.index];
Entrance* overrideEntrance = entranceMap[entranceOverride.override];
entrance->Disconnect();
entrance->Connect(overrideEntrance->GetOriginalConnectedRegionKey());
entrance->SetAsShuffled();
}
}
} // namespace Rando

View file

@ -128,6 +128,7 @@ class EntranceShuffler {
void CreateEntranceOverrides();
void UnshuffleAllEntrances();
void ParseJson(nlohmann::json spoilerFileJson);
void ApplyEntranceOverrides();
private:
std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool);

View file

@ -358,6 +358,7 @@ const CustomMessage Hint::GetHintMessage(MessageFormat format, size_t id) const
}
hintText.InsertNames(toInsert);
hintText.SetSingularPlural();
if (num != 0) {
hintText.InsertNumber(num);

Some files were not shown because too many files have changed in this diff Show more