Merge branch 'develop' into split_gerudo_fortress

This commit is contained in:
Pepe20129 2025-03-22 23:07:33 +01:00
commit a1246f4ef7
139 changed files with 10811 additions and 7073 deletions

View file

@ -6,42 +6,44 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
generate-soh-otr:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Git Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.14
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
save: ${{ github.ref_name == github.event.repository.default_branch }}
key: ${{ runner.os }}-otr-ccache-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-otr-ccache-${{ github.ref }}
${{ runner.os }}-otr-ccache-
${{ runner.os }}-otr-ccache
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) libzip-dev zipcmp zipmerge ziptool
- name: Cache build folders
uses: actions/cache@v4
- name: Restore Cached deps folder
uses: actions/cache/restore@v4
with:
key: ${{ runner.os }}-otr-build-${{ github.ref }}-${{ github.sha }}
key: ${{ runner.os }}-deps-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-otr-build-${{ github.ref }}
${{ runner.os }}-otr-build-
path: |
build-cmake
SDL2-2.30.3
tinyxml2-10.0.0
${{ runner.os }}-deps-${{ github.ref }}-
${{ runner.os }}-deps-
path: deps
- name: Create deps folder
run: mkdir -p deps
- name: Install latest SDL
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "SDL2-2.30.3" ]; then
wget https://www.libsdl.org/release/SDL2-2.30.3.tar.gz
tar -xzf SDL2-2.30.3.tar.gz
if [ ! -d "deps/SDL2-2.30.3" ]; then
wget https://github.com/libsdl-org/SDL/releases/download/release-2.30.3/SDL2-2.30.3.tar.gz
tar -xzf SDL2-2.30.3.tar.gz -C deps
fi
cd SDL2-2.30.3
cd deps/SDL2-2.30.3
./configure --enable-hidapi-libusb
make -j 10
sudo make install
@ -50,11 +52,11 @@ jobs:
run: |
sudo apt-get remove libtinyxml2-dev
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "tinyxml2-10.0.0" ]; then
if [ ! -d "deps/tinyxml2-10.0.0" ]; then
wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz
tar -xzf 10.0.0.tar.gz
tar -xzf 10.0.0.tar.gz -C deps
fi
cd tinyxml2-10.0.0
cd deps/tinyxml2-10.0.0
mkdir -p build
cd build
cmake ..
@ -64,49 +66,57 @@ jobs:
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
- uses: actions/upload-artifact@v4
cmake --build build-cmake --config Release --target GenerateSohOtr -j3
- name: Upload soh.otr
uses: actions/upload-artifact@v4
with:
name: soh.otr
path: soh.otr
retention-days: 1
retention-days: 3
build-macos:
needs: generate-soh-otr
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Git Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.14
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
create-symlink: true
save: ${{ github.ref_name == github.event.repository.default_branch }}
key: ${{ runner.os }}-14-ccache-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-14-ccache-${{ github.ref }}
${{ runner.os }}-14-ccache-
${{ runner.os }}-14-ccache
# Needed to apply sudo for macports cache restore
- name: Install gtar wrapper
run: |
sudo mv /opt/homebrew/bin/gtar /opt/homebrew/bin/gtar.orig
sudo cp .github/workflows//gtar /opt/homebrew/bin/gtar
sudo cp .github/workflows/gtar /opt/homebrew/bin/gtar
sudo chmod +x /opt/homebrew/bin/gtar
- name: Cache MacPorts
id: cache-macports
uses: actions/cache@v4
- name: Restore Cached MacPorts
id: restore-cache-macports
uses: actions/cache/restore@v4
with:
path: /opt/local/
key: ${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}
key: ${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}-
${{ runner.os }}-14-macports-
path: /opt/local/
# Updated PATH applies to the next step and onwards
- name: Install MacPorts (if necessary)
run: |
if [ -d /opt/local/ ]; then
if command -v /opt/local/bin/port 2>&1 >/dev/null; then
echo "MacPorts already installed"
else
echo "Installing MacPorts"
wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-14-Sonoma.pkg
sudo installer -pkg ./MacPorts-2.9.3-14-Sonoma.pkg -target /
fi
echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH
echo "/opt/local/bin:/opt/local/sbin" >> "$GITHUB_PATH"
- name: Install dependencies
run: |
brew uninstall --ignore-dependencies libpng
@ -116,11 +126,12 @@ jobs:
uses: actions/download-artifact@v4
with:
name: soh.otr
path: build-cmake/soh
- name: Build SoH
run: |
export PATH="/usr/lib/ccache:/opt/homebrew/opt/ccache/libexec:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DBUILD_REMOTE_CONTROL=1
cmake --build build-cmake --config Release --parallel 10
mv soh.otr build-cmake/soh
(cd build-cmake && cpack)
mv _packages/*.dmg SoH.dmg
@ -132,44 +143,52 @@ jobs:
path: |
SoH.dmg
readme.txt
- name: Save Cache MacPorts
if: ${{ github.ref_name == github.event.repository.default_branch }}
uses: actions/cache/save@v4
with:
key: ${{ steps.restore-cache-macports.outputs.cache-primary-key }}
path: /opt/local/
build-linux:
needs: generate-soh-otr
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Git Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt)
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.14
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: linux-ccache-${{ github.ref }}-${{ github.sha }}
save: ${{ github.ref_name == github.event.repository.default_branch }}
key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }}
restore-keys: |
linux-ccache-${{ github.ref }}
linux-ccache-
- name: Cache build folders
uses: actions/cache@v4
${{ runner.os }}-ccache-${{ github.ref }}
${{ runner.os }}-ccache
- name: Restore Cached deps folder
id: restore-cache-deps
uses: actions/cache/restore@v4
with:
key: linux-build-${{ github.ref }}-${{ github.sha }}
key: ${{ runner.os }}-deps-${{ github.ref }}-${{ github.sha }}
restore-keys: |
linux-build-${{ github.ref }}
linux-build-
path: |
SDL2-2.30.3
SDL2_net-2.2.0
tinyxml2-10.0.0
libzip-1.10.1
${{ runner.os }}-deps-${{ github.ref }}-
${{ runner.os }}-deps-
path: deps
- name: Create deps folder
run: mkdir -p deps
- name: Install latest SDL
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "SDL2-2.30.3" ]; then
wget https://www.libsdl.org/release/SDL2-2.30.3.tar.gz
tar -xzf SDL2-2.30.3.tar.gz
if [ ! -d "deps/SDL2-2.30.3" ]; then
wget https://github.com/libsdl-org/SDL/releases/download/release-2.30.3/SDL2-2.30.3.tar.gz
tar -xzf SDL2-2.30.3.tar.gz -C deps
fi
cd SDL2-2.30.3
cd deps/SDL2-2.30.3
./configure --enable-hidapi-libusb
make -j 10
sudo make install
@ -177,11 +196,11 @@ jobs:
- name: Install latest SDL_net
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "SDL2_net-2.2.0" ]; then
if [ ! -d "deps/SDL2_net-2.2.0" ]; then
wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz
tar -xzf SDL2_net-2.2.0.tar.gz
tar -xzf SDL2_net-2.2.0.tar.gz -C deps
fi
cd SDL2_net-2.2.0
cd deps/SDL2_net-2.2.0
./configure
make -j 10
sudo make install
@ -190,11 +209,11 @@ jobs:
run: |
sudo apt-get remove libtinyxml2-dev
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "tinyxml2-10.0.0" ]; then
if [ ! -d "deps/tinyxml2-10.0.0" ]; then
wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz
tar -xzf 10.0.0.tar.gz
tar -xzf 10.0.0.tar.gz -C deps
fi
cd tinyxml2-10.0.0
cd deps/tinyxml2-10.0.0
mkdir -p build
cd build
cmake ..
@ -203,11 +222,11 @@ jobs:
- name: Install libzip without crypto
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "libzip-1.10.1" ]; then
if [ ! -d "deps/libzip-1.10.1" ]; then
wget https://github.com/nih-at/libzip/releases/download/v1.10.1/libzip-1.10.1.tar.gz
tar -xzf libzip-1.10.1.tar.gz
tar -xzf libzip-1.10.1.tar.gz -C deps
fi
cd libzip-1.10.1
cd deps/libzip-1.10.1
mkdir -p build
cd build
cmake .. -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_MBEDTLS=OFF -DENABLE_OPENSSL=OFF
@ -218,6 +237,7 @@ jobs:
uses: actions/download-artifact@v4
with:
name: soh.otr
path: build-cmake/soh
- name: Build SoH
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
@ -237,39 +257,52 @@ jobs:
path: |
soh.appimage
readme.txt
- name: Save Cache deps folder
if: ${{ github.ref_name == github.event.repository.default_branch }}
uses: actions/cache/save@v4
with:
key: ${{ steps.restore-cache-deps.outputs.cache-primary-key }}
path: deps
build-windows:
needs: generate-soh-otr
runs-on: ${{ (vars.WINDOWS_RUNNER && fromJSON(vars.WINDOWS_RUNNER)) || 'windows-latest' }}
runs-on: windows-latest
steps:
- name: Install dependencies
if: ${{ !vars.WINDOWS_RUNNER }}
run: |
choco install ninja
choco install ninja -y
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force -ErrorAction SilentlyContinue
- uses: actions/checkout@v4
- name: Git Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.14
- name: Configure sccache
uses: hendrikmuhs/ccache-action@v1.2
with:
variant: sccache
max-size: "1G"
max-size: "2G"
evict-old-files: job
save: ${{ github.ref_name == github.event.repository.default_branch }}
key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-ccache-${{ github.ref }}
${{ runner.os }}-ccache-
- name: Cache build folder
uses: actions/cache@v4
${{ runner.os }}-ccache
- name: Restore Cached VCPKG folder
id: restore-cache-vcpkg
uses: actions/cache/restore@v4
with:
key: ${{ runner.os }}-build-${{ github.ref }}-${{ github.sha }}
key: ${{ runner.os }}-vcpkg-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-build-${{ github.ref }}
${{ runner.os }}-build-
path: |
build-windows
vcpkg
${{ runner.os }}-vcpkg-${{ github.ref }}-
${{ runner.os }}-vcpkg-
path: vcpkg
- name: Configure Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
- name: Download soh.otr
uses: actions/download-artifact@v4
with:
name: soh.otr
path: build-windows/soh
- name: Build SoH
env:
VCPKG_ROOT: ${{github.workspace}}/vcpkg
@ -278,22 +311,19 @@ jobs:
cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DBUILD_REMOTE_CONTROL=1
cmake --build build-windows --config Release --parallel 10
mkdir soh-windows
mv ./x64/Release/soh.exe ./soh-windows/soh.exe
mkdir soh-windows/debug
mkdir soh-windows/mods
New-Item soh-windows/mods/custom_otr_files_go_here.txt -type file
mv ./x64/Release/soh.pdb ./soh-windows/debug/soh.pdb
mv ./README.md ./soh-windows/readme.txt
mv ./build-windows/gamecontrollerdb.txt ./soh-windows/gamecontrollerdb.txt
mv ./x64/Release/assets ./soh-windows
- name: Download soh.otr
uses: actions/download-artifact@v4
with:
name: soh.otr
path: soh-windows
(cd build-windows && cpack)
cd ..
mv _packages/*.zip _packages/soh-windows.zip
- name: Unzip package
run: Expand-Archive -Path _packages/soh-windows.zip -DestinationPath soh-windows
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: soh-windows
path: soh-windows
- name: Save Cache VCPKG folder
if: ${{ github.ref_name == github.event.repository.default_branch }}
uses: actions/cache/save@v4
with:
key: ${{ steps.restore-cache-vcpkg.outputs.cache-primary-key }}
path: vcpkg

View file

@ -1,9 +1,9 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY 0)
set(CPACK_COMPONENTS_ALL "ship" "extractor" "appimage")
set(CPACK_COMPONENTS_ALL "ship")
if (NOT CPACK_GENERATOR STREQUAL "External")
list(REMOVE_ITEM CPACK_COMPONENTS_ALL "appimage")
if (CPACK_GENERATOR STREQUAL "External")
list(APPEND CPACK_COMPONENTS_ALL "extractor" "appimage")
endif()
if (CPACK_GENERATOR MATCHES "DEB|RPM")

View file

@ -53,7 +53,10 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(CMAKE_PROJECT_GIT_COMMIT_HASH "${GIT_COMMIT_HASH}" CACHE STRING "Git commit hash" FORCE)
# Get only the first 7 characters of the hash
string(SUBSTRING "${GIT_COMMIT_HASH}" 0 7 SHORT_COMMIT_HASH)
set(CMAKE_PROJECT_GIT_COMMIT_HASH "${SHORT_COMMIT_HASH}" CACHE STRING "Git commit hash" FORCE)
execute_process(
COMMAND git describe --tags --abbrev=0 --exact-match HEAD
@ -171,7 +174,7 @@ set_property(TARGET soh PROPERTY APPIMAGE_ICON_FILE "${CMAKE_BINARY_DIR}/sohIcon
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
install(PROGRAMS "${CMAKE_BINARY_DIR}/linux/soh.sh" DESTINATION . COMPONENT appimage)
install(FILES "${CMAKE_SOURCE_DIR}/soh.otr" DESTINATION . COMPONENT ship)
install(FILES "${CMAKE_BINARY_DIR}/soh/soh.otr" 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)

View file

@ -440,6 +440,7 @@ if(MSVC)
/Gy;
/W3
>
/bigobj;
/sdl-;
/permissive-;
/MP;

Binary file not shown.

Binary file not shown.

View file

@ -1,11 +1,10 @@
<DisplayList Version="0">
<ClearGeometryMode G_LIGHTING="1" />
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_cull" VertexBufferIndex="0" VertexOffset="0" Count="8"/>
<SetGeometryMode G_LIGHTING="1" />
<CullDisplayList Start="0" End="7"/>
<CallDisplayList Path="objects/object_keyring/mat_gKeyringIconGerudoFortressDL_f3dlite_IconMetal_GerudoFortress"/>
<CallDisplayList Path="objects/object_keyring/gKeyringIconGerudoFortressDL_tri_0"/>
<PipeSync/>
<SetGeometryMode G_LIGHTING="1" />
<ClearGeometryMode G_TEXTURE_GEN="1" />
<SetCombineLERP A0="G_CCMUX_0" B0="G_CCMUX_0" C0="G_CCMUX_0" D0="G_CCMUX_SHADE" Aa0="G_ACMUX_0" Ab0="G_ACMUX_0" Ac0="G_ACMUX_0" Ad0="G_ACMUX_ENVIRONMENT" A1="G_CCMUX_0" B1="G_CCMUX_0" C1="G_CCMUX_0" D1="G_CCMUX_SHADE" Aa1="G_ACMUX_0" Ab1="G_ACMUX_0" Ac1="G_ACMUX_0" Ad1="G_ACMUX_ENVIRONMENT"/>
<Texture S="65535" T="65535" Level="0" Tile="0" On="0"/>
<EndDisplayList/>
</DisplayList>

View file

@ -1,213 +1,110 @@
<DisplayList Version="0">
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="0" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="4" V02="5"/>
<Triangle1 V00="6" V01="2" V02="4"/>
<Triangle1 V00="7" V01="8" V02="9"/>
<Triangle1 V00="10" V01="9" V02="11"/>
<Triangle1 V00="12" V01="13" V02="14"/>
<Triangle1 V00="12" V01="14" V02="15"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="16" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="0" V01="2" V02="3"/>
<Triangle1 V00="3" V01="2" V02="4"/>
<Triangle1 V00="3" V01="4" V02="5"/>
<Triangle1 V00="6" V01="3" V02="5"/>
<Triangle1 V00="6" V01="5" V02="7"/>
<Triangle1 V00="8" V01="6" V02="7"/>
<Triangle1 V00="8" V01="7" V02="9"/>
<Triangle1 V00="10" V01="8" V02="9"/>
<Triangle1 V00="10" V01="9" V02="11"/>
<Triangle1 V00="12" V01="10" V02="11"/>
<Triangle1 V00="12" V01="11" V02="13"/>
<Triangle1 V00="14" V01="12" V02="13"/>
<Triangle1 V00="14" V01="13" V02="15"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="32" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="0" V01="3" V02="1"/>
<Triangle1 V00="4" V01="3" V02="0"/>
<Triangle1 V00="4" V01="5" V02="3"/>
<Triangle1 V00="5" V01="6" V02="3"/>
<Triangle1 V00="5" V01="7" V02="6"/>
<Triangle1 V00="7" V01="8" V02="6"/>
<Triangle1 V00="7" V01="9" V02="8"/>
<Triangle1 V00="9" V01="10" V02="8"/>
<Triangle1 V00="9" V01="11" V02="10"/>
<Triangle1 V00="11" V01="12" V02="10"/>
<Triangle1 V00="11" V01="13" V02="12"/>
<Triangle1 V00="10" V01="12" V02="14"/>
<Triangle1 V00="10" V01="14" V02="15"/>
<Triangle1 V00="8" V01="10" V02="15"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="48" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="0" V02="2"/>
<Triangle1 V00="3" V01="2" V02="4"/>
<Triangle1 V00="5" V01="3" V02="4"/>
<Triangle1 V00="5" V01="4" V02="6"/>
<Triangle1 V00="7" V01="8" V02="9"/>
<Triangle1 V00="7" V01="9" V02="10"/>
<Triangle1 V00="10" V01="9" V02="11"/>
<Triangle1 V00="10" V01="11" V02="12"/>
<Triangle1 V00="12" V01="11" V02="13"/>
<Triangle1 V00="12" V01="13" V02="14"/>
<Triangle1 V00="15" V01="12" V02="14"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="64" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="0" V02="2"/>
<Triangle1 V00="3" V01="2" V02="4"/>
<Triangle1 V00="5" V01="0" V02="3"/>
<Triangle1 V00="5" V01="6" V02="0"/>
<Triangle1 V00="7" V01="6" V02="5"/>
<Triangle1 V00="7" V01="8" V02="6"/>
<Triangle1 V00="8" V01="9" V02="6"/>
<Triangle1 V00="8" V01="10" V02="9"/>
<Triangle1 V00="6" V01="9" V02="11"/>
<Triangle1 V00="6" V01="11" V02="0"/>
<Triangle1 V00="12" V01="13" V02="14"/>
<Triangle1 V00="15" V01="12" V02="14"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="80" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="4" V02="5"/>
<Triangle1 V00="3" V01="6" V02="4"/>
<Triangle1 V00="3" V01="7" V02="6"/>
<Triangle1 V00="3" V01="8" V02="7"/>
<Triangle1 V00="9" V01="6" V02="7"/>
<Triangle1 V00="6" V01="9" V02="10"/>
<Triangle1 V00="10" V01="9" V02="11"/>
<Triangle1 V00="12" V01="11" V02="9"/>
<Triangle1 V00="9" V01="13" V02="12"/>
<Triangle1 V00="13" V01="9" V02="7"/>
<Triangle1 V00="13" V01="7" V02="14"/>
<Triangle1 V00="15" V01="12" V02="13"/>
<Triangle1 V00="12" V01="15" V02="11"/>
<Triangle1 V00="10" V01="11" V02="15"/>
<Triangle1 V00="6" V01="10" V02="15"/>
<Triangle1 V00="15" V01="4" V02="6"/>
<Triangle1 V00="13" V01="4" V02="15"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="96" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="1" V02="0"/>
<Triangle1 V00="3" V01="0" V02="4"/>
<Triangle1 V00="5" V01="6" V02="7"/>
<Triangle1 V00="5" V01="7" V02="8"/>
<Triangle1 V00="9" V01="8" V02="7"/>
<Triangle1 V00="9" V01="7" V02="10"/>
<Triangle1 V00="11" V01="8" V02="9"/>
<Triangle1 V00="11" V01="5" V02="8"/>
<Triangle1 V00="11" V01="12" V02="5"/>
<Triangle1 V00="13" V01="12" V02="11"/>
<Triangle1 V00="13" V01="11" V02="14"/>
<Triangle1 V00="15" V01="14" V02="11"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="112" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="1" V01="3" V02="2"/>
<Triangle1 V00="2" V01="3" V02="4"/>
<Triangle1 V00="2" V01="4" V02="5"/>
<Triangle1 V00="5" V01="4" V02="6"/>
<Triangle1 V00="5" V01="6" V02="7"/>
<Triangle1 V00="8" V01="7" V02="6"/>
<Triangle1 V00="8" V01="6" V02="9"/>
<Triangle1 V00="10" V01="8" V02="9"/>
<Triangle1 V00="10" V01="9" V02="11"/>
<Triangle1 V00="12" V01="8" V02="10"/>
<Triangle1 V00="13" V01="8" V02="12"/>
<Triangle1 V00="13" V01="7" V02="8"/>
<Triangle1 V00="13" V01="5" V02="7"/>
<Triangle1 V00="13" V01="14" V02="5"/>
<Triangle1 V00="14" V01="2" V02="5"/>
<Triangle1 V00="14" V01="0" V02="2"/>
<Triangle1 V00="12" V01="10" V02="15"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="128" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="2" V02="1"/>
<Triangle1 V00="4" V01="5" V02="6"/>
<Triangle1 V00="7" V01="5" V02="4"/>
<Triangle1 V00="8" V01="5" V02="7"/>
<Triangle1 V00="8" V01="7" V02="9"/>
<Triangle1 V00="7" V01="10" V02="9"/>
<Triangle1 V00="10" V01="6" V02="9"/>
<Triangle1 V00="8" V01="9" V02="11"/>
<Triangle1 V00="5" V01="8" V02="11"/>
<Triangle1 V00="12" V01="13" V02="14"/>
<Triangle1 V00="14" V01="13" V02="15"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="144" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="0" V01="2" V02="3"/>
<Triangle1 V00="4" V01="5" V02="6"/>
<Triangle1 V00="5" V01="4" V02="7"/>
<Triangle1 V00="5" V01="7" V02="8"/>
<Triangle1 V00="8" V01="7" V02="9"/>
<Triangle1 V00="9" V01="7" V02="10"/>
<Triangle1 V00="9" V01="10" V02="11"/>
<Triangle1 V00="9" V01="12" V02="8"/>
<Triangle1 V00="9" V01="13" V02="12"/>
<Triangle1 V00="13" V01="9" V02="14"/>
<Triangle1 V00="15" V01="14" V02="9"/>
<Triangle1 V00="5" V01="13" V02="14"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="160" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="2" V02="1"/>
<Triangle1 V00="2" V01="3" V02="4"/>
<Triangle1 V00="5" V01="4" V02="3"/>
<Triangle1 V00="5" V01="0" V02="4"/>
<Triangle1 V00="2" V01="4" V02="0"/>
<Triangle1 V00="1" V01="6" V02="7"/>
<Triangle1 V00="8" V01="7" V02="6"/>
<Triangle1 V00="1" V01="7" V02="9"/>
<Triangle1 V00="10" V01="11" V02="12"/>
<Triangle1 V00="10" V01="12" V02="13"/>
<Triangle1 V00="14" V01="13" V02="12"/>
<Triangle1 V00="14" V01="12" V02="15"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="176" Count="16"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="0" V01="3" V02="1"/>
<Triangle1 V00="0" V01="4" V02="3"/>
<Triangle1 V00="5" V01="4" V02="0"/>
<Triangle1 V00="5" V01="0" V02="6"/>
<Triangle1 V00="7" V01="6" V02="0"/>
<Triangle1 V00="7" V01="0" V02="8"/>
<Triangle1 V00="0" V01="2" V02="8"/>
<Triangle1 V00="8" V01="2" V02="9"/>
<Triangle1 V00="8" V01="9" V02="10"/>
<Triangle1 V00="10" V01="9" V02="11"/>
<Triangle1 V00="10" V01="11" V02="12"/>
<Triangle1 V00="13" V01="12" V02="11"/>
<Triangle1 V00="13" V01="11" V02="14"/>
<Triangle1 V00="4" V01="13" V02="14"/>
<Triangle1 V00="4" V01="14" V02="3"/>
<Triangle1 V00="15" V01="13" V02="4"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="192" Count="14"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="0" V01="3" V02="1"/>
<Triangle1 V00="0" V01="4" V02="3"/>
<Triangle1 V00="0" V01="5" V02="4"/>
<Triangle1 V00="5" V01="6" V02="4"/>
<Triangle1 V00="5" V01="7" V02="6"/>
<Triangle1 V00="2" V01="8" V02="9"/>
<Triangle1 V00="10" V01="11" V02="12"/>
<Triangle1 V00="13" V01="12" V02="11"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="206" Count="15"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="3" V01="0" V02="2"/>
<Triangle1 V00="3" V01="4" V02="0"/>
<Triangle1 V00="3" V01="5" V02="4"/>
<Triangle1 V00="3" V01="6" V02="5"/>
<Triangle1 V00="5" V01="6" V02="1"/>
<Triangle1 V00="4" V01="5" V02="7"/>
<Triangle1 V00="4" V01="7" V02="0"/>
<Triangle1 V00="8" V01="9" V02="10"/>
<Triangle1 V00="8" V01="10" V02="11"/>
<Triangle1 V00="12" V01="10" V02="13"/>
<Triangle1 V00="12" V01="13" V02="14"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="221" Count="10"/>
<Triangle1 V00="0" V01="1" V02="2"/>
<Triangle1 V00="1" V01="0" V02="3"/>
<Triangle1 V00="1" V01="3" V02="4"/>
<Triangle1 V00="4" V01="2" V02="1"/>
<Triangle1 V00="5" V01="6" V02="7"/>
<Triangle1 V00="6" V01="5" V02="8"/>
<Triangle1 V00="6" V01="8" V02="9"/>
<Triangle1 V00="9" V01="7" V02="6"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="0" Count="32"/>
<Triangles2 V00="0" V01="1" V02="2" Flag0="0" V10="3" V11="4" V12="5" Flag1="0"/>
<Triangles2 V00="6" V01="2" V02="4" Flag0="0" V10="7" V11="8" V12="9" Flag1="0"/>
<Triangles2 V00="10" V01="9" V02="11" Flag0="0" V10="12" V11="13" V12="14" Flag1="0"/>
<Triangles2 V00="12" V01="14" V02="15" Flag0="0" V10="15" V11="14" V12="16" Flag1="0"/>
<Triangles2 V00="15" V01="16" V02="17" Flag0="0" V10="17" V11="16" V12="18" Flag1="0"/>
<Triangles2 V00="17" V01="18" V02="19" Flag0="0" V10="20" V11="17" V12="19" Flag1="0"/>
<Triangles2 V00="20" V01="19" V02="21" Flag0="0" V10="22" V11="20" V12="21" Flag1="0"/>
<Triangles2 V00="22" V01="21" V02="23" Flag0="0" V10="24" V11="22" V12="23" Flag1="0"/>
<Triangles2 V00="24" V01="23" V02="25" Flag0="0" V10="26" V11="24" V12="25" Flag1="0"/>
<Triangles2 V00="26" V01="25" V02="27" Flag0="0" V10="28" V11="26" V12="27" Flag1="0"/>
<Triangles2 V00="28" V01="27" V02="29" Flag0="0" V10="30" V11="26" V12="28" Flag1="0"/>
<Triangle1 V00="30" V01="31" V02="26"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="32" Count="32"/>
<Triangles2 V00="0" V01="1" V02="2" Flag0="0" V10="0" V11="3" V12="1" Flag1="0"/>
<Triangles2 V00="3" V01="4" V02="1" Flag0="0" V10="3" V11="5" V12="4" Flag1="0"/>
<Triangles2 V00="5" V01="6" V02="4" Flag0="0" V10="5" V11="7" V12="6" Flag1="0"/>
<Triangles2 V00="7" V01="8" V02="6" Flag0="0" V10="7" V11="9" V12="8" Flag1="0"/>
<Triangles2 V00="9" V01="10" V02="8" Flag0="0" V10="9" V11="11" V12="10" Flag1="0"/>
<Triangles2 V00="8" V01="10" V02="12" Flag0="0" V10="8" V11="12" V12="13" Flag1="0"/>
<Triangles2 V00="6" V01="8" V02="13" Flag0="0" V10="6" V11="13" V12="14" Flag1="0"/>
<Triangles2 V00="4" V01="6" V02="14" Flag0="0" V10="4" V11="14" V12="15" Flag1="0"/>
<Triangles2 V00="1" V01="4" V02="15" Flag0="0" V10="1" V11="15" V12="16" Flag1="0"/>
<Triangles2 V00="17" V01="18" V02="19" Flag0="0" V10="17" V11="19" V12="20" Flag1="0"/>
<Triangles2 V00="20" V01="19" V02="21" Flag0="0" V10="20" V11="21" V12="22" Flag1="0"/>
<Triangles2 V00="22" V01="21" V02="23" Flag0="0" V10="22" V11="23" V12="24" Flag1="0"/>
<Triangles2 V00="25" V01="22" V02="24" Flag0="0" V10="25" V11="24" V12="26" Flag1="0"/>
<Triangles2 V00="27" V01="25" V02="26" Flag0="0" V10="27" V11="26" V12="28" Flag1="0"/>
<Triangles2 V00="29" V01="25" V02="27" Flag0="0" V10="29" V11="30" V12="25" Flag1="0"/>
<Triangle1 V00="31" V01="30" V02="29"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="64" Count="32"/>
<Triangles2 V00="0" V01="1" V02="2" Flag0="0" V10="1" V11="3" V12="2" Flag1="0"/>
<Triangles2 V00="1" V01="4" V02="3" Flag0="0" V10="2" V11="3" V12="5" Flag1="0"/>
<Triangles2 V00="2" V01="5" V02="6" Flag0="0" V10="7" V11="8" V12="9" Flag1="0"/>
<Triangles2 V00="10" V01="7" V02="9" Flag0="0" V10="10" V11="11" V12="7" Flag1="0"/>
<Triangles2 V00="12" V01="13" V02="14" Flag0="0" V10="12" V11="15" V12="13" Flag1="0"/>
<Triangles2 V00="12" V01="16" V02="15" Flag0="0" V10="12" V11="17" V12="16" Flag1="0"/>
<Triangles2 V00="18" V01="15" V02="16" Flag0="0" V10="15" V11="18" V12="19" Flag1="0"/>
<Triangles2 V00="19" V01="18" V02="20" Flag0="0" V10="21" V11="20" V12="18" Flag1="0"/>
<Triangles2 V00="18" V01="22" V02="21" Flag0="0" V10="22" V11="18" V12="16" Flag1="0"/>
<Triangles2 V00="22" V01="16" V02="23" Flag0="0" V10="24" V11="21" V12="22" Flag1="0"/>
<Triangles2 V00="21" V01="24" V02="20" Flag0="0" V10="19" V11="20" V12="24" Flag1="0"/>
<Triangles2 V00="15" V01="19" V02="24" Flag0="0" V10="24" V11="13" V12="15" Flag1="0"/>
<Triangles2 V00="22" V01="13" V02="24" Flag0="0" V10="22" V11="25" V12="13" Flag1="0"/>
<Triangles2 V00="26" V01="25" V02="22" Flag0="0" V10="26" V11="22" V12="27" Flag1="0"/>
<Triangles2 V00="28" V01="29" V02="30" Flag0="0" V10="28" V11="30" V12="31" Flag1="0"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="96" Count="32"/>
<Triangles2 V00="0" V01="1" V02="2" Flag0="0" V10="0" V11="2" V12="3" Flag1="0"/>
<Triangles2 V00="4" V01="1" V02="0" Flag0="0" V10="4" V11="5" V12="1" Flag1="0"/>
<Triangles2 V00="4" V01="6" V02="5" Flag0="0" V10="7" V11="6" V12="4" Flag1="0"/>
<Triangles2 V00="7" V01="4" V02="8" Flag0="0" V10="9" V11="8" V12="4" Flag1="0"/>
<Triangles2 V00="9" V01="4" V02="10" Flag0="0" V10="4" V11="0" V12="10" Flag1="0"/>
<Triangles2 V00="10" V01="0" V02="11" Flag0="0" V10="10" V11="11" V12="12" Flag1="0"/>
<Triangles2 V00="12" V01="11" V02="13" Flag0="0" V10="12" V11="13" V12="14" Flag1="0"/>
<Triangles2 V00="15" V01="14" V02="13" Flag0="0" V10="15" V11="13" V12="16" Flag1="0"/>
<Triangles2 V00="6" V01="15" V02="16" Flag0="0" V10="6" V11="16" V12="5" Flag1="0"/>
<Triangles2 V00="17" V01="15" V02="6" Flag0="0" V10="18" V11="15" V12="17" Flag1="0"/>
<Triangles2 V00="18" V01="14" V02="15" Flag0="0" V10="18" V11="12" V12="14" Flag1="0"/>
<Triangles2 V00="18" V01="19" V02="12" Flag0="0" V10="19" V11="10" V12="12" Flag1="0"/>
<Triangles2 V00="19" V01="9" V02="10" Flag0="0" V10="17" V11="6" V12="7" Flag1="0"/>
<Triangles2 V00="20" V01="21" V02="22" Flag0="0" V10="23" V11="22" V12="21" Flag1="0"/>
<Triangles2 V00="24" V01="25" V02="26" Flag0="0" V10="27" V11="25" V12="24" Flag1="0"/>
<Triangles2 V00="28" V01="25" V02="27" Flag0="0" V10="28" V11="27" V12="29" Flag1="0"/>
<Triangles2 V00="27" V01="30" V02="29" Flag0="0" V10="30" V11="26" V12="29" Flag1="0"/>
<Triangles2 V00="28" V01="29" V02="31" Flag0="0" V10="25" V11="28" V12="31" Flag1="0"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="128" Count="32"/>
<Triangles2 V00="0" V01="1" V02="2" Flag0="0" V10="2" V11="1" V12="3" Flag1="0"/>
<Triangles2 V00="4" V01="5" V02="6" Flag0="0" V10="4" V11="6" V12="7" Flag1="0"/>
<Triangles2 V00="8" V01="9" V02="10" Flag0="0" V10="9" V11="8" V12="11" Flag1="0"/>
<Triangles2 V00="9" V01="11" V02="12" Flag0="0" V10="12" V11="11" V12="13" Flag1="0"/>
<Triangles2 V00="13" V01="11" V02="14" Flag0="0" V10="13" V11="14" V12="15" Flag1="0"/>
<Triangles2 V00="13" V01="16" V02="12" Flag0="0" V10="13" V11="17" V12="16" Flag1="0"/>
<Triangles2 V00="17" V01="13" V02="18" Flag0="0" V10="19" V11="18" V12="13" Flag1="0"/>
<Triangles2 V00="9" V01="17" V02="18" Flag0="0" V10="17" V11="9" V12="20" Flag1="0"/>
<Triangles2 V00="12" V01="20" V02="9" Flag0="0" V10="20" V11="12" V12="21" Flag1="0"/>
<Triangles2 V00="16" V01="21" V02="12" Flag0="0" V10="16" V11="17" V12="21" Flag1="0"/>
<Triangles2 V00="20" V01="21" V02="17" Flag0="0" V10="9" V11="18" V12="22" Flag1="0"/>
<Triangles2 V00="23" V01="22" V02="18" Flag0="0" V10="9" V11="22" V12="24" Flag1="0"/>
<Triangles2 V00="25" V01="26" V02="27" Flag0="0" V10="25" V11="27" V12="28" Flag1="0"/>
<Triangles2 V00="29" V01="28" V02="27" Flag0="0" V10="29" V11="27" V12="30" Flag1="0"/>
<Triangles2 V00="31" V01="28" V02="29" Flag0="0" V10="31" V11="25" V12="28" Flag1="0"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="160" Count="32"/>
<Triangles2 V00="0" V01="1" V02="2" Flag0="0" V10="3" V11="1" V12="0" Flag1="0"/>
<Triangles2 V00="3" V01="0" V02="4" Flag0="0" V10="5" V11="4" V12="0" Flag1="0"/>
<Triangles2 V00="5" V01="0" V02="6" Flag0="0" V10="0" V11="7" V12="6" Flag1="0"/>
<Triangles2 V00="6" V01="7" V02="8" Flag0="0" V10="6" V11="8" V12="9" Flag1="0"/>
<Triangles2 V00="9" V01="8" V02="10" Flag0="0" V10="9" V11="10" V12="11" Flag1="0"/>
<Triangles2 V00="12" V01="11" V02="10" Flag0="0" V10="12" V11="10" V12="13" Flag1="0"/>
<Triangles2 V00="1" V01="12" V02="13" Flag0="0" V10="1" V11="13" V12="2" Flag1="0"/>
<Triangles2 V00="14" V01="12" V02="1" Flag0="0" V10="15" V11="12" V12="14" Flag1="0"/>
<Triangles2 V00="15" V01="11" V02="12" Flag0="0" V10="15" V11="9" V12="11" Flag1="0"/>
<Triangles2 V00="15" V01="16" V02="9" Flag0="0" V10="16" V11="6" V12="9" Flag1="0"/>
<Triangles2 V00="16" V01="5" V02="6" Flag0="0" V10="14" V11="1" V12="3" Flag1="0"/>
<Triangles2 V00="17" V01="18" V02="19" Flag0="0" V10="20" V11="19" V12="18" Flag1="0"/>
<Triangles2 V00="21" V01="22" V02="23" Flag0="0" V10="24" V11="21" V12="23" Flag1="0"/>
<Triangles2 V00="24" V01="25" V02="21" Flag0="0" V10="24" V11="26" V12="25" Flag1="0"/>
<Triangles2 V00="24" V01="27" V02="26" Flag0="0" V10="26" V11="27" V12="22" Flag1="0"/>
<Triangles2 V00="25" V01="26" V02="28" Flag0="0" V10="25" V11="28" V12="21" Flag1="0"/>
<Triangle1 V00="29" V01="30" V02="31"/>
<LoadVertices Path="objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0" VertexBufferIndex="0" VertexOffset="192" Count="16"/>
<Triangles2 V00="0" V01="1" V02="2" Flag0="0" V10="3" V11="1" V12="4" Flag1="0"/>
<Triangles2 V00="3" V01="4" V02="5" Flag0="0" V10="6" V11="7" V12="8" Flag1="0"/>
<Triangles2 V00="7" V01="6" V02="9" Flag0="0" V10="7" V11="9" V12="10" Flag1="0"/>
<Triangles2 V00="10" V01="8" V02="7" Flag0="0" V10="11" V11="12" V12="13" Flag1="0"/>
<Triangles2 V00="12" V01="11" V02="14" Flag0="0" V10="12" V11="14" V12="15" Flag1="0"/>
<Triangle1 V00="15" V01="13" V02="12"/>
<EndDisplayList/>
</DisplayList>

View file

@ -1,233 +1,210 @@
<Vertex Version="0">
<Vtx X="-21" Y="-11" Z="13" S="-175" T="-1122" R="234" G="7" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-175" T="-1122" R="233" G="7" B="125" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-161" T="-1207" R="227" G="123" B="244" A="254"/>
<Vtx X="-29" Y="-12" Z="12" S="-70" T="-1316" R="235" G="11" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-184" T="-1036" R="234" G="7" B="125" A="254"/>
<Vtx X="-28" Y="-14" Z="11" S="-5" T="-1276" R="2" G="129" B="8" A="254"/>
<Vtx X="-22" Y="-15" Z="12" S="-52" T="-1033" R="246" G="130" B="6" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-215" T="-994" R="234" G="7" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-215" T="-994" R="21" G="245" B="131" A="254"/>
<Vtx X="-15" Y="-16" Z="13" S="-70" T="-1316" R="22" G="249" B="131" A="254"/>
<Vtx X="-29" Y="-12" Z="12" S="-70" T="-1316" R="234" G="11" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-184" T="-1036" R="233" G="7" B="125" A="254"/>
<Vtx X="-28" Y="-14" Z="11" S="-5" T="-1276" R="2" G="129" B="9" A="254"/>
<Vtx X="-22" Y="-15" Z="12" S="-52" T="-1033" R="245" G="130" B="7" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-215" T="-994" R="233" G="7" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-215" T="-994" R="21" G="244" B="131" A="254"/>
<Vtx X="-15" Y="-16" Z="13" S="-70" T="-1316" R="23" G="248" B="131" A="254"/>
<Vtx X="-16" Y="-18" Z="13" S="-5" T="-1276" R="191" G="147" B="254" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-184" T="-1036" R="21" G="245" B="131" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-184" T="-1036" R="21" G="244" B="131" A="254"/>
<Vtx X="-22" Y="-15" Z="12" S="-52" T="-1033" R="202" G="141" B="0" A="254"/>
<Vtx X="-14" Y="16" Z="15" S="-666" T="-580" R="231" G="237" B="123" A="255"/>
<Vtx X="-14" Y="16" Z="15" S="-666" T="-580" R="231" G="236" B="123" A="255"/>
<Vtx X="-36" Y="10" Z="12" S="-580" T="-580" R="2" G="244" B="126" A="255"/>
<Vtx X="-35" Y="10" Z="6" S="-580" T="-751" R="38" G="228" B="138" A="255"/>
<Vtx X="-13" Y="16" Z="8" S="-666" T="-751" R="10" G="220" B="135" A="255"/>
<Vtx X="-13" Y="16" Z="8" S="-666" T="-751" R="10" G="220" B="135" A="255"/>
<Vtx X="-35" Y="10" Z="6" S="-580" T="-751" R="38" G="228" B="138" A="255"/>
<Vtx X="-13" Y="16" Z="8" S="-666" T="-751" R="11" G="220" B="135" A="255"/>
<Vtx X="-39" Y="14" Z="8" S="-580" T="-922" R="167" G="89" B="237" A="255"/>
<Vtx X="-12" Y="21" Z="11" S="-666" T="-922" R="33" G="123" B="253" A="255"/>
<Vtx X="-36" Y="10" Z="12" S="-580" T="-1092" R="2" G="244" B="126" A="255"/>
<Vtx X="-14" Y="16" Z="15" S="-666" T="-1092" R="231" G="237" B="123" A="255"/>
<Vtx X="8" Y="1" Z="16" S="-751" T="-922" R="122" G="33" B="15" A="255"/>
<Vtx X="2" Y="0" Z="18" S="-751" T="-1092" R="211" G="0" B="119" A="255"/>
<Vtx X="-14" Y="16" Z="15" S="-666" T="-1092" R="231" G="236" B="123" A="255"/>
<Vtx X="8" Y="1" Z="16" S="-751" T="-922" R="121" G="34" B="16" A="255"/>
<Vtx X="2" Y="0" Z="18" S="-751" T="-1092" R="210" G="1" B="119" A="255"/>
<Vtx X="0" Y="-26" Z="16" S="-836" T="-922" R="89" G="167" B="19" A="255"/>
<Vtx X="-4" Y="-22" Z="19" S="-836" T="-1092" R="218" G="28" B="118" A="255"/>
<Vtx X="-27" Y="-34" Z="13" S="-922" T="-922" R="223" G="133" B="3" A="255"/>
<Vtx X="-26" Y="-29" Z="16" S="-922" T="-1092" R="246" G="36" B="121" A="255"/>
<Vtx X="-47" Y="-14" Z="9" S="-1007" T="-922" R="134" G="223" B="241" A="255"/>
<Vtx X="-42" Y="-12" Z="12" S="-1007" T="-1092" R="9" G="15" B="126" A="255"/>
<Vtx X="-26" Y="-29" Z="16" S="-922" T="-1092" R="245" G="36" B="121" A="255"/>
<Vtx X="-47" Y="-14" Z="9" S="-1007" T="-922" R="135" G="222" B="240" A="255"/>
<Vtx X="-42" Y="-12" Z="12" S="-1007" T="-1092" R="10" G="16" B="126" A="255"/>
<Vtx X="-39" Y="14" Z="8" S="-1092" T="-922" R="167" G="89" B="237" A="255"/>
<Vtx X="-36" Y="10" Z="12" S="-1092" T="-1092" R="2" G="244" B="126" A="255"/>
<Vtx X="-35" Y="10" Z="6" S="-1092" T="-751" R="38" G="228" B="138" A="255"/>
<Vtx X="-47" Y="-14" Z="9" S="-1007" T="-922" R="134" G="223" B="241" A="255"/>
<Vtx X="-39" Y="14" Z="8" S="-1092" T="-922" R="167" G="89" B="237" A="255"/>
<Vtx X="-41" Y="-13" Z="6" S="-1007" T="-751" R="45" G="0" B="137" A="255"/>
<Vtx X="-41" Y="-13" Z="6" S="-1007" T="-751" R="46" G="255" B="137" A="255"/>
<Vtx X="-36" Y="10" Z="12" S="-1092" T="-580" R="2" G="244" B="126" A="255"/>
<Vtx X="-42" Y="-12" Z="12" S="-1007" T="-580" R="9" G="15" B="126" A="255"/>
<Vtx X="-25" Y="-29" Z="10" S="-922" T="-751" R="25" G="19" B="133" A="255"/>
<Vtx X="-26" Y="-29" Z="16" S="-922" T="-580" R="246" G="36" B="121" A="255"/>
<Vtx X="-41" Y="-13" Z="6" S="-1007" T="-751" R="46" G="255" B="137" A="255"/>
<Vtx X="-35" Y="10" Z="6" S="-1092" T="-751" R="38" G="228" B="138" A="255"/>
<Vtx X="-42" Y="-12" Z="12" S="-1007" T="-580" R="10" G="16" B="126" A="255"/>
<Vtx X="-25" Y="-29" Z="10" S="-922" T="-751" R="25" G="20" B="133" A="255"/>
<Vtx X="-26" Y="-29" Z="16" S="-922" T="-580" R="245" G="36" B="121" A="255"/>
<Vtx X="-3" Y="-23" Z="13" S="-836" T="-751" R="254" G="12" B="130" A="255"/>
<Vtx X="-4" Y="-22" Z="19" S="-836" T="-580" R="218" G="28" B="118" A="255"/>
<Vtx X="3" Y="0" Z="12" S="-751" T="-751" R="247" G="241" B="130" A="255"/>
<Vtx X="2" Y="0" Z="18" S="-751" T="-580" R="211" G="0" B="119" A="255"/>
<Vtx X="-13" Y="16" Z="8" S="-666" T="-751" R="10" G="220" B="135" A="255"/>
<Vtx X="-14" Y="16" Z="15" S="-666" T="-580" R="231" G="237" B="123" A="255"/>
<Vtx X="3" Y="0" Z="12" S="-751" T="-751" R="246" G="240" B="130" A="255"/>
<Vtx X="2" Y="0" Z="18" S="-751" T="-580" R="210" G="1" B="119" A="255"/>
<Vtx X="-13" Y="16" Z="8" S="-666" T="-751" R="11" G="220" B="135" A="255"/>
<Vtx X="-14" Y="16" Z="15" S="-666" T="-580" R="231" G="236" B="123" A="255"/>
<Vtx X="-12" Y="21" Z="11" S="-666" T="-922" R="33" G="123" B="253" A="255"/>
<Vtx X="8" Y="1" Z="16" S="-751" T="-922" R="122" G="33" B="15" A="255"/>
<Vtx X="-3" Y="-23" Z="13" S="-836" T="-751" R="254" G="12" B="130" A="255"/>
<Vtx X="8" Y="1" Z="16" S="-751" T="-922" R="122" G="33" B="15" A="255"/>
<Vtx X="8" Y="1" Z="16" S="-751" T="-922" R="121" G="34" B="16" A="255"/>
<Vtx X="0" Y="-26" Z="16" S="-836" T="-922" R="89" G="167" B="19" A="255"/>
<Vtx X="-25" Y="-29" Z="10" S="-922" T="-751" R="25" G="19" B="133" A="255"/>
<Vtx X="-27" Y="-34" Z="13" S="-922" T="-922" R="223" G="133" B="3" A="255"/>
<Vtx X="-41" Y="-13" Z="6" S="-1007" T="-751" R="45" G="0" B="137" A="255"/>
<Vtx X="-47" Y="-14" Z="9" S="-1007" T="-922" R="134" G="223" B="241" A="255"/>
<Vtx X="-47" Y="-14" Z="9" S="-1007" T="-922" R="135" G="222" B="240" A="255"/>
<Vtx X="-15" Y="27" Z="12" S="-708" T="-580" R="242" G="1" B="126" A="255"/>
<Vtx X="-18" Y="17" Z="12" S="-580" T="-580" R="255" G="3" B="127" A="255"/>
<Vtx X="-17" Y="17" Z="9" S="-580" T="-751" R="35" G="244" B="134" A="255"/>
<Vtx X="-15" Y="27" Z="9" S="-708" T="-751" R="22" G="241" B="132" A="255"/>
<Vtx X="-18" Y="17" Z="12" S="-580" T="-580" R="255" G="4" B="127" A="255"/>
<Vtx X="-17" Y="17" Z="9" S="-580" T="-751" R="35" G="243" B="135" A="255"/>
<Vtx X="-15" Y="27" Z="9" S="-708" T="-751" R="23" G="241" B="132" A="255"/>
<Vtx X="-20" Y="16" Z="11" S="-580" T="-922" R="135" G="32" B="236" A="255"/>
<Vtx X="-16" Y="29" Z="10" S="-708" T="-922" R="194" G="110" B="240" A="255"/>
<Vtx X="-18" Y="17" Z="12" S="-580" T="-1092" R="255" G="3" B="127" A="255"/>
<Vtx X="-16" Y="29" Z="10" S="-708" T="-922" R="194" G="109" B="240" A="255"/>
<Vtx X="-18" Y="17" Z="12" S="-580" T="-1092" R="255" G="4" B="127" A="255"/>
<Vtx X="-15" Y="27" Z="12" S="-708" T="-1092" R="242" G="1" B="126" A="255"/>
<Vtx X="-5" Y="26" Z="12" S="-836" T="-922" R="109" G="64" B="11" A="255"/>
<Vtx X="-5" Y="26" Z="12" S="-836" T="-922" R="109" G="64" B="11" A="255"/>
<Vtx X="-15" Y="27" Z="12" S="-708" T="-1092" R="242" G="1" B="126" A="255"/>
<Vtx X="-7" Y="25" Z="13" S="-836" T="-1092" R="231" G="4" B="124" A="255"/>
<Vtx X="-5" Y="26" Z="12" S="-836" T="-922" R="109" G="64" B="12" A="255"/>
<Vtx X="-7" Y="25" Z="13" S="-836" T="-1092" R="230" G="4" B="124" A="255"/>
<Vtx X="-8" Y="13" Z="12" S="-964" T="-922" R="121" G="224" B="20" A="255"/>
<Vtx X="-10" Y="15" Z="14" S="-964" T="-1092" R="221" G="12" B="122" A="255"/>
<Vtx X="-9" Y="15" Z="11" S="-964" T="-751" R="1" G="253" B="129" A="255"/>
<Vtx X="-7" Y="25" Z="10" S="-836" T="-751" R="11" G="244" B="130" A="255"/>
<Vtx X="-10" Y="15" Z="14" S="-964" T="-580" R="221" G="12" B="122" A="255"/>
<Vtx X="-7" Y="25" Z="13" S="-836" T="-580" R="231" G="4" B="124" A="255"/>
<Vtx X="-15" Y="27" Z="9" S="-708" T="-751" R="22" G="241" B="132" A="255"/>
<Vtx X="-10" Y="15" Z="14" S="-964" T="-1092" R="221" G="13" B="121" A="255"/>
<Vtx X="-9" Y="15" Z="11" S="-964" T="-751" R="1" G="252" B="129" A="255"/>
<Vtx X="-7" Y="25" Z="10" S="-836" T="-751" R="11" G="243" B="130" A="255"/>
<Vtx X="-10" Y="15" Z="14" S="-964" T="-580" R="221" G="13" B="121" A="255"/>
<Vtx X="-10" Y="15" Z="14" S="-964" T="-580" R="221" G="13" B="121" A="255"/>
<Vtx X="-7" Y="25" Z="13" S="-836" T="-580" R="230" G="4" B="124" A="255"/>
<Vtx X="-7" Y="25" Z="10" S="-836" T="-751" R="11" G="243" B="130" A="255"/>
<Vtx X="-15" Y="27" Z="9" S="-708" T="-751" R="23" G="241" B="132" A="255"/>
<Vtx X="-15" Y="27" Z="12" S="-708" T="-580" R="242" G="1" B="126" A="255"/>
<Vtx X="-16" Y="29" Z="10" S="-708" T="-922" R="194" G="110" B="240" A="255"/>
<Vtx X="-29" Y="-11" Z="11" S="-130" T="-1349" R="229" G="124" B="245" A="254"/>
<Vtx X="-29" Y="-12" Z="12" S="-70" T="-1316" R="235" G="11" B="125" A="254"/>
<Vtx X="-16" Y="29" Z="10" S="-708" T="-922" R="194" G="109" B="240" A="255"/>
<Vtx X="-5" Y="26" Z="12" S="-836" T="-922" R="109" G="64" B="12" A="255"/>
<Vtx X="-29" Y="-11" Z="11" S="-130" T="-1349" R="229" G="123" B="244" A="254"/>
<Vtx X="-29" Y="-12" Z="12" S="-70" T="-1316" R="234" G="11" B="125" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-155" T="-1302" R="227" G="123" B="244" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-161" T="-1207" R="14" G="247" B="130" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-161" T="-1207" R="14" G="247" B="130" A="254"/>
<Vtx X="-29" Y="-13" Z="11" S="-70" T="-1316" R="15" G="251" B="130" A="254"/>
<Vtx X="-29" Y="-11" Z="11" S="-130" T="-1349" R="229" G="124" B="245" A="254"/>
<Vtx X="-14" Y="-14" Z="13" S="-159" T="-765" R="46" G="138" B="14" A="254"/>
<Vtx X="-12" Y="-7" Z="14" S="-454" T="-732" R="236" G="12" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-159" T="-765" R="234" G="7" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-161" T="-1207" R="14" G="246" B="130" A="254"/>
<Vtx X="-29" Y="-13" Z="11" S="-70" T="-1316" R="15" G="250" B="130" A="254"/>
<Vtx X="-14" Y="-14" Z="13" S="-159" T="-765" R="46" G="138" B="15" A="254"/>
<Vtx X="-12" Y="-7" Z="14" S="-454" T="-732" R="236" G="13" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-159" T="-765" R="233" G="7" B="125" A="254"/>
<Vtx X="-8" Y="-11" Z="14" S="-349" T="-544" R="88" G="166" B="19" A="254"/>
<Vtx X="-11" Y="-7" Z="13" S="-454" T="-732" R="16" G="253" B="130" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-161" T="-824" R="14" G="247" B="130" A="254"/>
<Vtx X="-8" Y="-2" Z="13" S="-679" T="-646" R="16" G="0" B="130" A="254"/>
<Vtx X="-4" Y="-3" Z="14" S="-681" T="-493" R="124" G="239" B="19" A="254"/>
<Vtx X="-11" Y="-7" Z="13" S="-454" T="-732" R="16" G="252" B="130" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-161" T="-824" R="14" G="246" B="130" A="254"/>
<Vtx X="-8" Y="-2" Z="13" S="-679" T="-646" R="17" G="255" B="130" A="254"/>
<Vtx X="-4" Y="-3" Z="14" S="-681" T="-493" R="124" G="238" B="19" A="254"/>
<Vtx X="-5" Y="7" Z="13" S="-1012" T="-643" R="26" G="124" B="252" A="254"/>
<Vtx X="-10" Y="-1" Z="13" S="-688" T="-724" R="157" G="77" B="237" A="254"/>
<Vtx X="-13" Y="-5" Z="13" S="-510" T="-819" R="182" G="102" B="239" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-215" T="-994" R="14" G="247" B="130" A="254"/>
<Vtx X="-10" Y="-1" Z="13" S="-688" T="-724" R="157" G="77" B="236" A="254"/>
<Vtx X="-13" Y="-5" Z="13" S="-510" T="-819" R="182" G="102" B="238" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-215" T="-994" R="14" G="246" B="130" A="254"/>
<Vtx X="-8" Y="-2" Z="14" S="-679" T="-646" R="236" G="16" B="124" A="254"/>
<Vtx X="-13" Y="-5" Z="13" S="-510" T="-819" R="182" G="102" B="239" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-215" T="-994" R="234" G="7" B="125" A="254"/>
<Vtx X="-12" Y="-7" Z="14" S="-454" T="-732" R="236" G="12" B="125" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-215" T="-994" R="233" G="7" B="125" A="254"/>
<Vtx X="-20" Y="-8" Z="12" S="-310" T="-1033" R="198" G="112" B="240" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-245" T="-1035" R="14" G="247" B="130" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-245" T="-1035" R="14" G="246" B="130" A="254"/>
<Vtx X="-37" Y="-14" Z="10" S="-772" T="-836" R="180" G="206" B="89" A="255"/>
<Vtx X="-37" Y="-14" Z="10" S="-644" T="-836" R="164" G="17" B="86" A="255"/>
<Vtx X="-37" Y="-13" Z="10" S="-644" T="-964" R="142" G="53" B="236" A="255"/>
<Vtx X="-37" Y="-15" Z="10" S="-772" T="-964" R="171" G="161" B="250" A="255"/>
<Vtx X="-37" Y="-15" Z="10" S="-772" T="-836" R="208" G="193" B="156" A="255"/>
<Vtx X="-37" Y="-13" Z="10" S="-644" T="-964" R="143" G="53" B="236" A="255"/>
<Vtx X="-37" Y="-15" Z="10" S="-772" T="-964" R="171" G="162" B="250" A="255"/>
<Vtx X="-37" Y="-15" Z="10" S="-772" T="-836" R="208" G="193" B="157" A="255"/>
<Vtx X="-37" Y="-15" Z="10" S="-772" T="-964" R="171" G="162" B="250" A="255"/>
<Vtx X="-37" Y="-13" Z="10" S="-644" T="-964" R="143" G="53" B="236" A="255"/>
<Vtx X="-37" Y="-14" Z="10" S="-644" T="-836" R="193" G="4" B="146" A="255"/>
<Vtx X="-36" Y="-15" Z="10" S="-772" T="-964" R="0" G="129" B="8" A="255"/>
<Vtx X="-36" Y="-14" Z="11" S="-772" T="-836" R="231" G="206" B="114" A="255"/>
<Vtx X="-37" Y="-14" Z="10" S="-772" T="-836" R="180" G="206" B="89" A="255"/>
<Vtx X="-36" Y="-14" Z="11" S="-772" T="-836" R="230" G="206" B="114" A="255"/>
<Vtx X="-30" Y="-13" Z="12" S="-900" T="-836" R="249" G="213" B="119" A="255"/>
<Vtx X="-30" Y="-14" Z="11" S="-900" T="-964" R="24" G="132" B="11" A="255"/>
<Vtx X="-30" Y="-13" Z="10" S="-900" T="-836" R="26" G="198" B="146" A="255"/>
<Vtx X="-30" Y="-13" Z="10" S="-900" T="-836" R="26" G="198" B="146" A="255"/>
<Vtx X="-36" Y="-15" Z="10" S="-772" T="-964" R="0" G="129" B="8" A="255"/>
<Vtx X="-30" Y="-14" Z="11" S="-900" T="-964" R="24" G="132" B="12" A="255"/>
<Vtx X="-30" Y="-13" Z="10" S="-900" T="-836" R="27" G="198" B="146" A="255"/>
<Vtx X="-36" Y="-15" Z="10" S="-772" T="-836" R="7" G="191" B="147" A="255"/>
<Vtx X="-37" Y="-15" Z="10" S="-772" T="-836" R="208" G="193" B="156" A="255"/>
<Vtx X="-37" Y="-14" Z="10" S="-772" T="-708" R="193" G="4" B="146" A="255"/>
<Vtx X="-36" Y="-13" Z="9" S="-772" T="-708" R="244" G="38" B="135" A="255"/>
<Vtx X="-37" Y="-13" Z="10" S="-772" T="-580" R="142" G="53" B="236" A="255"/>
<Vtx X="-36" Y="-13" Z="10" S="-772" T="-580" R="208" G="117" B="242" A="255"/>
<Vtx X="-36" Y="-13" Z="9" S="-772" T="-708" R="244" G="39" B="136" A="255"/>
<Vtx X="-37" Y="-13" Z="10" S="-772" T="-580" R="143" G="53" B="236" A="255"/>
<Vtx X="-36" Y="-13" Z="10" S="-772" T="-580" R="208" G="117" B="241" A="255"/>
<Vtx X="-36" Y="-13" Z="11" S="-772" T="-708" R="211" G="54" B="106" A="255"/>
<Vtx X="-37" Y="-14" Z="10" S="-772" T="-708" R="164" G="17" B="86" A="255"/>
<Vtx X="-36" Y="-14" Z="11" S="-772" T="-836" R="231" G="206" B="114" A="255"/>
<Vtx X="-37" Y="-14" Z="10" S="-772" T="-836" R="180" G="206" B="89" A="255"/>
<Vtx X="-30" Y="-12" Z="12" S="-900" T="-708" R="229" G="61" B="108" A="255"/>
<Vtx X="-30" Y="-11" Z="11" S="-900" T="-580" R="232" G="124" B="245" A="255"/>
<Vtx X="-30" Y="-12" Z="10" S="-900" T="-708" R="6" G="45" B="137" A="255"/>
<Vtx X="-30" Y="-13" Z="12" S="-900" T="-836" R="249" G="213" B="119" A="255"/>
<Vtx X="-31" Y="-13" Z="12" S="21" T="-445" R="206" G="35" B="111" A="254"/>
<Vtx X="-32" Y="-20" Z="11" S="-730" T="-1234" R="23" G="132" B="11" A="254"/>
<Vtx X="-30" Y="-11" Z="11" S="-900" T="-580" R="232" G="124" B="244" A="255"/>
<Vtx X="-30" Y="-12" Z="10" S="-900" T="-708" R="6" G="46" B="138" A="255"/>
<Vtx X="-31" Y="-13" Z="12" S="21" T="-445" R="206" G="36" B="111" A="254"/>
<Vtx X="-32" Y="-20" Z="11" S="-730" T="-1234" R="23" G="132" B="12" A="254"/>
<Vtx X="-28" Y="-14" Z="11" S="-843" T="-464" R="113" G="201" B="20" A="254"/>
<Vtx X="-31" Y="-13" Z="9" S="21" T="-445" R="241" G="20" B="131" A="254"/>
<Vtx X="-31" Y="-13" Z="9" S="21" T="-445" R="240" G="20" B="132" A="254"/>
<Vtx X="-29" Y="-12" Z="12" S="-926" T="-640" R="35" G="21" B="120" A="254"/>
<Vtx X="-31" Y="-13" Z="12" S="-621" T="-564" R="206" G="35" B="111" A="254"/>
<Vtx X="-31" Y="-13" Z="12" S="-621" T="-564" R="206" G="36" B="111" A="254"/>
<Vtx X="-28" Y="-14" Z="11" S="-986" T="-592" R="113" G="201" B="20" A="254"/>
<Vtx X="-29" Y="-11" Z="11" S="-912" T="-702" R="97" G="82" B="8" A="254"/>
<Vtx X="-32" Y="-8" Z="10" S="-768" T="-807" R="217" G="120" B="243" A="254"/>
<Vtx X="-31" Y="-13" Z="9" S="-621" T="-564" R="241" G="20" B="131" A="254"/>
<Vtx X="-29" Y="-11" Z="11" S="-912" T="-702" R="97" G="82" B="9" A="254"/>
<Vtx X="-32" Y="-8" Z="10" S="-768" T="-807" R="217" G="120" B="242" A="254"/>
<Vtx X="-31" Y="-13" Z="9" S="-621" T="-564" R="240" G="20" B="132" A="254"/>
<Vtx X="-29" Y="-13" Z="11" S="-926" T="-640" R="68" G="6" B="149" A="254"/>
<Vtx X="-31" Y="-13" Z="11" S="-621" T="-564" R="139" G="46" B="236" A="254"/>
<Vtx X="-29" Y="-13" Z="11" S="-70" T="-1316" R="15" G="251" B="130" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-184" T="-1036" R="14" G="247" B="130" A="254"/>
<Vtx X="-28" Y="-14" Z="11" S="-5" T="-1276" R="2" G="129" B="8" A="254"/>
<Vtx X="-22" Y="-15" Z="12" S="-52" T="-1033" R="246" G="130" B="6" A="254"/>
<Vtx X="-14" Y="-14" Z="13" S="-155" T="-1302" R="87" G="92" B="6" A="254"/>
<Vtx X="-13" Y="-15" Z="14" S="-130" T="-1349" R="87" G="92" B="6" A="254"/>
<Vtx X="-15" Y="-16" Z="13" S="-70" T="-1316" R="22" G="249" B="131" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-158" T="-1244" R="21" G="245" B="131" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-215" T="-994" R="21" G="245" B="131" A="254"/>
<Vtx X="-24" Y="-2" Z="11" S="-510" T="-819" R="115" G="52" B="13" A="254"/>
<Vtx X="-29" Y="-13" Z="11" S="-70" T="-1316" R="15" G="250" B="130" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-184" T="-1036" R="14" G="246" B="130" A="254"/>
<Vtx X="-28" Y="-14" Z="11" S="-5" T="-1276" R="2" G="129" B="9" A="254"/>
<Vtx X="-22" Y="-15" Z="12" S="-52" T="-1033" R="245" G="130" B="7" A="254"/>
<Vtx X="-14" Y="-14" Z="13" S="-155" T="-1302" R="87" G="92" B="7" A="254"/>
<Vtx X="-13" Y="-15" Z="14" S="-130" T="-1349" R="87" G="92" B="7" A="254"/>
<Vtx X="-15" Y="-16" Z="13" S="-70" T="-1316" R="23" G="248" B="131" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-158" T="-1244" R="21" G="244" B="131" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-215" T="-994" R="21" G="244" B="131" A="254"/>
<Vtx X="-24" Y="-2" Z="11" S="-510" T="-819" R="115" G="52" B="14" A="254"/>
<Vtx X="-20" Y="-8" Z="12" S="-310" T="-1033" R="106" G="69" B="11" A="254"/>
<Vtx X="-27" Y="-3" Z="10" S="-454" T="-732" R="22" G="251" B="131" A="254"/>
<Vtx X="-27" Y="3" Z="10" S="-679" T="-646" R="24" G="254" B="131" A="254"/>
<Vtx X="-32" Y="-4" Z="10" S="-349" T="-544" R="134" G="223" B="240" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-161" T="-824" R="21" G="245" B="131" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-159" T="-765" R="157" G="176" B="247" A="254"/>
<Vtx X="-27" Y="-3" Z="10" S="-454" T="-732" R="22" G="250" B="131" A="254"/>
<Vtx X="-27" Y="3" Z="10" S="-679" T="-646" R="24" G="253" B="131" A="254"/>
<Vtx X="-32" Y="-4" Z="10" S="-349" T="-544" R="135" G="223" B="240" A="254"/>
<Vtx X="-21" Y="-11" Z="12" S="-161" T="-824" R="21" G="244" B="131" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-159" T="-765" R="158" G="176" B="247" A="254"/>
<Vtx X="-31" Y="4" Z="10" S="-681" T="-493" R="139" G="46" B="236" A="254"/>
<Vtx X="-28" Y="3" Z="11" S="-679" T="-646" R="243" G="14" B="126" A="254"/>
<Vtx X="-27" Y="-3" Z="12" S="-454" T="-732" R="242" G="11" B="126" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-161" T="-824" R="157" G="176" B="247" A="254"/>
<Vtx X="-28" Y="3" Z="11" S="-679" T="-646" R="243" G="14" B="126" A="254"/>
<Vtx X="-24" Y="-2" Z="11" S="-510" T="-819" R="115" G="52" B="13" A="254"/>
<Vtx X="-25" Y="3" Z="11" S="-688" T="-724" R="125" G="17" B="17" A="254"/>
<Vtx X="-27" Y="3" Z="10" S="-679" T="-646" R="24" G="254" B="131" A="254"/>
<Vtx X="-27" Y="-3" Z="12" S="-454" T="-732" R="241" G="11" B="126" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-161" T="-824" R="158" G="176" B="247" A="254"/>
<Vtx X="-25" Y="3" Z="11" S="-688" T="-724" R="125" G="18" B="17" A="254"/>
<Vtx X="-25" Y="12" Z="10" S="-1012" T="-643" R="40" G="121" B="254" A="254"/>
<Vtx X="-31" Y="4" Z="10" S="-681" T="-493" R="139" G="46" B="236" A="254"/>
<Vtx X="-27" Y="-3" Z="12" S="-454" T="-732" R="242" G="11" B="126" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-215" T="-994" R="241" G="5" B="126" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-164" T="-862" R="157" G="176" B="247" A="254"/>
<Vtx X="-28" Y="-10" Z="11" S="-164" T="-862" R="158" G="176" B="247" A="254"/>
<Vtx X="-20" Y="-8" Z="12" S="-310" T="-1033" R="106" G="69" B="11" A="254"/>
<Vtx X="-9" Y="-22" Z="14" S="-772" T="-836" R="39" G="170" B="171" A="255"/>
<Vtx X="-8" Y="-21" Z="14" S="-644" T="-836" R="87" G="221" B="171" A="255"/>
<Vtx X="-7" Y="-21" Z="15" S="-644" T="-964" R="125" G="247" B="19" A="255"/>
<Vtx X="-7" Y="-21" Z="15" S="-644" T="-964" R="125" G="246" B="19" A="255"/>
<Vtx X="-9" Y="-22" Z="15" S="-772" T="-964" R="26" G="132" B="12" A="255"/>
<Vtx X="-9" Y="-22" Z="15" S="-772" T="-836" R="11" G="183" B="103" A="255"/>
<Vtx X="-8" Y="-21" Z="15" S="-644" T="-836" R="58" G="234" B="111" A="255"/>
<Vtx X="-8" Y="-21" Z="15" S="-644" T="-836" R="58" G="234" B="110" A="255"/>
<Vtx X="-10" Y="-22" Z="15" S="-772" T="-964" R="193" G="146" B="254" A="255"/>
<Vtx X="-10" Y="-22" Z="15" S="-772" T="-964" R="193" G="146" B="254" A="255"/>
<Vtx X="-9" Y="-22" Z="15" S="-772" T="-964" R="26" G="132" B="12" A="255"/>
<Vtx X="-9" Y="-22" Z="15" S="-772" T="-836" R="11" G="183" B="103" A="255"/>
<Vtx X="-9" Y="-22" Z="14" S="-772" T="-836" R="39" G="170" B="171" A="255"/>
<Vtx X="-9" Y="-22" Z="14" S="-772" T="-836" R="252" G="194" B="145" A="255"/>
<Vtx X="-14" Y="-17" Z="13" S="-900" T="-836" R="240" G="210" B="139" A="255"/>
<Vtx X="-14" Y="-18" Z="14" S="-900" T="-964" R="173" G="160" B="251" A="255"/>
<Vtx X="-14" Y="-17" Z="14" S="-900" T="-836" R="206" G="225" B="113" A="255"/>
<Vtx X="-9" Y="-22" Z="14" S="-772" T="-836" R="39" G="170" B="171" A="255"/>
<Vtx X="-14" Y="-17" Z="13" S="-900" T="-836" R="239" G="209" B="139" A="255"/>
<Vtx X="-14" Y="-18" Z="14" S="-900" T="-964" R="173" G="160" B="250" A="255"/>
<Vtx X="-14" Y="-17" Z="14" S="-900" T="-836" R="205" G="225" B="112" A="255"/>
<Vtx X="-10" Y="-21" Z="15" S="-772" T="-836" R="219" G="209" B="112" A="255"/>
<Vtx X="-8" Y="-21" Z="15" S="-772" T="-708" R="58" G="234" B="111" A="255"/>
<Vtx X="-9" Y="-20" Z="15" S="-772" T="-708" R="31" G="33" B="119" A="255"/>
<Vtx X="-7" Y="-21" Z="15" S="-772" T="-580" R="125" G="247" B="19" A="255"/>
<Vtx X="-8" Y="-20" Z="15" S="-772" T="-580" R="101" G="77" B="9" A="255"/>
<Vtx X="-9" Y="-22" Z="15" S="-772" T="-836" R="11" G="183" B="103" A="255"/>
<Vtx X="-8" Y="-21" Z="15" S="-772" T="-708" R="58" G="234" B="110" A="255"/>
<Vtx X="-9" Y="-20" Z="15" S="-772" T="-708" R="32" G="33" B="118" A="255"/>
<Vtx X="-7" Y="-21" Z="15" S="-772" T="-580" R="125" G="246" B="19" A="255"/>
<Vtx X="-8" Y="-20" Z="15" S="-772" T="-580" R="100" G="77" B="10" A="255"/>
<Vtx X="-8" Y="-20" Z="14" S="-772" T="-708" R="65" G="18" B="148" A="255"/>
<Vtx X="-8" Y="-21" Z="14" S="-772" T="-708" R="87" G="221" B="171" A="255"/>
<Vtx X="-13" Y="-16" Z="13" S="-900" T="-708" R="52" G="33" B="145" A="255"/>
<Vtx X="-13" Y="-16" Z="14" S="-900" T="-580" R="83" G="96" B="5" A="255"/>
<Vtx X="-8" Y="-20" Z="14" S="-772" T="-708" R="65" G="18" B="148" A="255"/>
<Vtx X="-13" Y="-16" Z="13" S="-900" T="-708" R="52" G="33" B="145" A="255"/>
<Vtx X="-8" Y="-20" Z="15" S="-772" T="-580" R="101" G="77" B="9" A="255"/>
<Vtx X="-9" Y="-20" Z="15" S="-772" T="-708" R="31" G="33" B="119" A="255"/>
<Vtx X="-13" Y="-16" Z="14" S="-900" T="-708" R="18" G="48" B="116" A="255"/>
<Vtx X="-10" Y="-21" Z="15" S="-772" T="-836" R="219" G="209" B="112" A="255"/>
<Vtx X="-14" Y="-17" Z="14" S="-900" T="-836" R="206" G="225" B="113" A="255"/>
<Vtx X="-9" Y="-22" Z="14" S="-772" T="-836" R="252" G="194" B="145" A="255"/>
<Vtx X="-14" Y="-17" Z="13" S="-900" T="-836" R="240" G="210" B="139" A="255"/>
<Vtx X="-13" Y="-16" Z="14" S="-900" T="-580" R="83" G="96" B="6" A="255"/>
<Vtx X="-13" Y="-16" Z="14" S="-900" T="-708" R="19" G="49" B="116" A="255"/>
<Vtx X="-13" Y="-18" Z="12" S="21" T="-445" R="60" G="0" B="144" A="254"/>
<Vtx X="-16" Y="-24" Z="14" S="-730" T="-1234" R="173" G="160" B="251" A="254"/>
<Vtx X="-16" Y="-24" Z="14" S="-730" T="-1234" R="173" G="160" B="250" A="254"/>
<Vtx X="-16" Y="-18" Z="13" S="-843" T="-464" R="131" G="8" B="237" A="254"/>
<Vtx X="-13" Y="-18" Z="15" S="21" T="-445" R="25" G="15" B="124" A="254"/>
<Vtx X="-13" Y="-18" Z="15" S="21" T="-445" R="25" G="16" B="123" A="254"/>
<Vtx X="-13" Y="-18" Z="12" S="-621" T="-564" R="60" G="0" B="144" A="254"/>
<Vtx X="-16" Y="-18" Z="13" S="-986" T="-592" R="131" G="8" B="237" A="254"/>
<Vtx X="-15" Y="-16" Z="13" S="-926" T="-640" R="235" G="30" B="134" A="254"/>
<Vtx X="-13" Y="-15" Z="14" S="-912" T="-702" R="213" G="119" B="242" A="254"/>
<Vtx X="-10" Y="-13" Z="14" S="-768" T="-807" R="94" G="85" B="8" A="254"/>
<Vtx X="-13" Y="-18" Z="15" S="-621" T="-564" R="25" G="15" B="124" A="254"/>
<Vtx X="-13" Y="-18" Z="15" S="-621" T="-564" R="25" G="16" B="123" A="254"/>
<Vtx X="-15" Y="-16" Z="14" S="-926" T="-640" R="201" G="45" B="105" A="254"/>
<Vtx X="-13" Y="-18" Z="14" S="-621" T="-564" R="124" G="239" B="19" A="254"/>
<Vtx X="-14" Y="-14" Z="13" S="-158" T="-1244" R="87" G="92" B="6" A="254"/>
<Vtx X="-14" Y="-14" Z="13" S="-158" T="-1244" R="87" G="92" B="7" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-161" T="-1207" R="241" G="5" B="126" A="254"/>
<Vtx X="-15" Y="-16" Z="14" S="-70" T="-1316" R="242" G="9" B="126" A="254"/>
<Vtx X="-13" Y="-15" Z="14" S="-130" T="-1349" R="87" G="92" B="6" A="254"/>
<Vtx X="-14" Y="-14" Z="13" S="-158" T="-1244" R="87" G="92" B="7" A="254"/>
<Vtx X="-15" Y="-16" Z="14" S="-70" T="-1316" R="242" G="9" B="126" A="254"/>
<Vtx X="-13" Y="-15" Z="14" S="-130" T="-1349" R="87" G="92" B="7" A="254"/>
<Vtx X="-16" Y="-18" Z="13" S="-5" T="-1276" R="191" G="147" B="254" A="254"/>
<Vtx X="-21" Y="-11" Z="13" S="-184" T="-1036" R="241" G="5" B="126" A="254"/>
<Vtx X="-22" Y="-15" Z="12" S="-52" T="-1033" R="202" G="141" B="0" A="254"/>
<Vtx X="-31" Y="-13" Z="12" S="-1985" T="-486" R="206" G="35" B="111" A="254"/>
<Vtx X="-31" Y="-13" Z="12" S="-1985" T="-486" R="206" G="36" B="111" A="254"/>
<Vtx X="-37" Y="-18" Z="10" S="20" T="-600" R="136" G="218" B="241" A="254"/>
<Vtx X="-32" Y="-20" Z="11" S="-430" T="-1143" R="23" G="132" B="11" A="254"/>
<Vtx X="-32" Y="-20" Z="11" S="-430" T="-1143" R="23" G="132" B="12" A="254"/>
<Vtx X="-31" Y="-13" Z="11" S="-1985" T="-486" R="139" G="46" B="236" A="254"/>
<Vtx X="-31" Y="-13" Z="9" S="-1985" T="-486" R="241" G="20" B="131" A="254"/>
<Vtx X="-31" Y="-13" Z="9" S="-1985" T="-486" R="240" G="20" B="132" A="254"/>
<Vtx X="-13" Y="-18" Z="12" S="-1985" T="-486" R="60" G="0" B="144" A="254"/>
<Vtx X="-10" Y="-24" Z="15" S="20" T="-600" R="86" G="164" B="18" A="254"/>
<Vtx X="-16" Y="-24" Z="14" S="-430" T="-1143" R="173" G="160" B="251" A="254"/>
<Vtx X="-10" Y="-24" Z="15" S="20" T="-600" R="85" G="164" B="19" A="254"/>
<Vtx X="-16" Y="-24" Z="14" S="-430" T="-1143" R="173" G="160" B="250" A="254"/>
<Vtx X="-13" Y="-18" Z="14" S="-1985" T="-486" R="124" G="239" B="19" A="254"/>
<Vtx X="-13" Y="-18" Z="15" S="-1985" T="-486" R="25" G="15" B="124" A="254"/>
<Vtx X="-13" Y="-18" Z="15" S="-1985" T="-486" R="25" G="16" B="123" A="254"/>
</Vertex>

View file

@ -0,0 +1,10 @@
<Vertex Version="0">
<Vtx X="-47" Y="-34" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="-47" Y="-34" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="-47" Y="29" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="-47" Y="29" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="-34" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="-34" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="29" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="29" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
</Vertex>

View file

@ -1,21 +1,15 @@
<DisplayList Version="0">
<SetGeometryMode G_ZBUFFER="1" G_SHADE="1" G_CULL_BACK="1" G_FOG="1" G_LIGHTING="1" G_TEXTURE_GEN="1" G_SHADING_SMOOTH="1" />
<PipeSync/>
<SetCombineLERP A0="G_CCMUX_TEXEL0" B0="G_CCMUX_0" C0="G_CCMUX_SHADE" D0="G_CCMUX_0" Aa0="G_ACMUX_0" Ab0="G_ACMUX_0" Ac0="G_ACMUX_0" Ad0="G_ACMUX_1" A1="G_CCMUX_COMBINED" B1="G_CCMUX_0" C1="G_CCMUX_ENVIRONMENT" D1="G_CCMUX_0" Aa1="G_ACMUX_0" Ab1="G_ACMUX_0" Ac1="G_ACMUX_0" Ad1="G_ACMUX_COMBINED"/>
<SetGeometryMode G_ZBUFFER="1" G_SHADE="1" G_CULL_BACK="1" G_FOG="1" G_LIGHTING="1" G_TEXTURE_GEN="1" G_SHADING_SMOOTH="1" />
<ClearGeometryMode G_CULL_FRONT="1" G_TEXTURE_GEN_LINEAR="1" />
<SetOtherMode Cmd="G_SETOTHERMODE_H" Sft="4" Length="20" G_AD_NOISE="1" G_CD_MAGICSQ="1" G_CK_NONE="1" G_TC_FILT="1" G_TF_BILERP="1" G_TL_TILE="1" G_TD_CLAMP="1" G_TP_PERSP="1" G_CYC_2CYCLE="1" G_PM_NPRIMITIVE="1" />
<SetOtherMode Cmd="G_SETOTHERMODE_H" Sft="4" Length="20" G_AD_NOISE="1" G_CD_MAGICSQ="1" G_CK_NONE="1" G_TC_FILT="1" G_TF_BILERP="1" G_TT_NONE="1" G_TL_TILE="1" G_TD_CLAMP="1" G_TP_PERSP="1" G_CYC_2CYCLE="1" G_PM_NPRIMITIVE="1" />
<SetOtherMode Cmd="G_SETOTHERMODE_L" Sft="0" Length="32" G_AC_NONE="1" G_ZS_PIXEL="1" G_RM_FOG_SHADE_A="1" G_RM_AA_ZB_OPA_SURF2="1" />
<Texture S="960" T="960" Level="0" Tile="0" On="1"/>
<SetTextureLUT Mode="G_TT_NONE"/>
<TileSync/>
<SetTextureImage Path="objects/object_keyring/Hilite_new" Format="G_IM_FMT_RGBA" Size="G_IM_SIZ_16b_LOAD_BLOCK" Width="1"/>
<SetTile Format="G_IM_FMT_RGBA" Size="G_IM_SIZ_16b_LOAD_BLOCK" Line="0" TMem="0" Tile="7" Palette="0" Cms0="G_TX_WRAP" Cms1="G_TX_NOMIRROR" Cmt0="G_TX_WRAP" Cmt1="G_TX_NOMIRROR" MaskS="4" ShiftS="0" MaskT="4" ShiftT="0"/>
<LoadSync/>
<SetTextureImage Path="objects/object_keyring/Hilite_new.rgba16" Format="G_IM_FMT_RGBA" Size="G_IM_SIZ_16b_LOAD_BLOCK" Width="1"/>
<SetTile Format="G_IM_FMT_RGBA" Size="G_IM_SIZ_16b_LOAD_BLOCK" Line="0" TMem="0" Tile="7" Palette="0" Cms0="G_TX_WRAP" Cms1="G_TX_NOMIRROR" Cmt0="G_TX_WRAP" Cmt1="G_TX_NOMIRROR" MaskS="0" ShiftS="0" MaskT="0" ShiftT="0"/>
<LoadBlock Tile="7" Uls="0" Ult="0" Lrs="255" Dxt="512"/>
<PipeSync/>
<SetTile Format="G_IM_FMT_RGBA" Size="G_IM_SIZ_16b" Line="4" TMem="0" Tile="0" Palette="0" Cms0="G_TX_WRAP" Cms1="G_TX_NOMIRROR" Cmt0="G_TX_WRAP" Cmt1="G_TX_NOMIRROR" MaskS="4" ShiftS="0" MaskT="4" ShiftT="0"/>
<SetTileSize T="0" Uls="0" Ult="0" Lrs="60" Lrt="60"/>
<SetEnvColor R="255" G="255" B="204" A="255"/>
<EndDisplayList/>
</DisplayList>

View file

@ -0,0 +1,10 @@
<Vertex Version="0">
<Vtx X="-47" Y="-34" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="-47" Y="-34" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="-47" Y="29" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="-47" Y="29" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="-34" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="-34" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="29" Z="19" S="0" T="0" R="0" G="0" B="0" A="0"/>
<Vtx X="8" Y="29" Z="6" S="0" T="0" R="0" G="0" B="0" A="0"/>
</Vertex>

View file

@ -45,12 +45,12 @@ extern "C"
extern OSViContext* __osViNext;
extern OSViMode osViModeFpalLan1;
extern u32 __additional_scanline;
extern u8 gBuildVersion[];
extern const char gBuildVersion[];
extern u16 gBuildVersionMajor;
extern u16 gBuildVersionMinor;
extern u16 gBuildVersionPatch;
extern u8 gGitBranch[];
extern u8 gGitCommitHash[];
extern const char gGitBranch[];
extern const char gGitCommitHash[];
extern u8 gGitCommitTag[];
extern u8 gBuildTeam[];
extern u8 gBuildDate[];

View file

@ -1,103 +0,0 @@
#include "AboutWindow.h"
#include <imgui.h>
#include <soh/GameVersions.h>
#include "soh/ResourceManagerHelpers.h"
extern "C" {
#include "variables.h"
}
AboutWindow::~AboutWindow() {
SPDLOG_TRACE("destruct about window");
}
void AboutWindow::InitElement() {
mIsTaggedVersion = gGitCommitTag[0] != 0;
strncpy(mGitCommitHashTruncated, (char*)gGitCommitHash, 7);
mGitCommitHashTruncated[7] = 0;
}
void AboutWindow::Draw() {
if (!IsVisible()) {
return;
}
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoDocking |
ImGuiWindowFlags_NoScrollWithMouse |
ImGuiWindowFlags_NoScrollbar;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(16 * ImGui::GetIO().FontGlobalScale, 8 * ImGui::GetIO().FontGlobalScale));
if (!ImGui::Begin(GetName().c_str(), &mIsVisible, windowFlags)) {
ImGui::End();
} else {
DrawElement();
ImGui::End();
}
ImGui::PopStyleVar();
// Sync up the IsVisible flag if it was changed by ImGui
SyncVisibilityConsoleVariable();
}
const char* AboutWindow::GetGameVersionString(uint32_t index) {
uint32_t gameVersion = ResourceMgr_GetGameVersion(index);
switch (gameVersion) {
case OOT_NTSC_US_10:
return "NTSC-U 1.0";
case OOT_NTSC_US_11:
return "NTSC-U 1.1";
case OOT_NTSC_US_12:
return "NTSC-U 1.2";
case OOT_PAL_10:
return "PAL 1.0";
case OOT_PAL_11:
return "PAL 1.1";
case OOT_PAL_GC:
return "PAL GC";
case OOT_PAL_MQ:
return "PAL MQ";
case OOT_PAL_GC_DBG1:
case OOT_PAL_GC_DBG2:
return "PAL GC-D";
case OOT_PAL_GC_MQ_DBG:
return "PAL MQ-D";
case OOT_IQUE_CN:
return "IQUE CN";
case OOT_IQUE_TW:
return "IQUE TW";
default:
return "UNKNOWN";
}
}
void AboutWindow::DrawElement() {
// The icon is already padded - adjust for that
ImVec2 cursorPos = ImGui::GetCursorScreenPos();
cursorPos.x -= 16 * ImGui::GetIO().FontGlobalScale;
ImGui::SetCursorScreenPos(cursorPos);
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon"), ImVec2(64.0f * ImGui::GetIO().FontGlobalScale, 64.0f * ImGui::GetIO().FontGlobalScale));
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Text("Ship of Harkinian");
if (mIsTaggedVersion) {
ImGui::Text("%s", gBuildVersion);
} else {
ImGui::Text("%s", gGitBranch);
ImGui::Text("%s", mGitCommitHashTruncated);
}
ImGui::EndGroup();
ImGui::Dummy(ImVec2(0, 2 * ImGui::GetIO().FontGlobalScale));
ImGui::Text("Game Archives:");
for (uint32_t i = 0; i < ResourceMgr_GetNumGameVersions(); i++) {
ImGui::BulletText(GetGameVersionString(i));
}
}

View file

@ -1,20 +0,0 @@
#pragma once
#include <libultraship/libultraship.h>
class AboutWindow : public Ship::GuiWindow {
public:
using GuiWindow::GuiWindow;
~AboutWindow();
private:
void InitElement() override;
void Draw() override;
void DrawElement() override;
void UpdateElement() override {};
const char* GetGameVersionString(uint32_t index);
bool mIsTaggedVersion;
char mGitCommitHashTruncated[8];
};

View file

@ -10,6 +10,12 @@ void Custom_EnMThunder_Update(Actor* thisx, PlayState* play) {
f32 blueRadius;
s32 redGreen;
// If thunder effect doesn't exist (aka player doesn't have magic),
// don't do anything.
if (enMThunder->actionFunc == nullptr) {
return;
}
enMThunder->actionFunc(enMThunder, play);
// don't call this part, it's what makes the spin attack darkness happen
// func_80A9F314(play, this->unk_1BC);

View file

@ -13,20 +13,20 @@ class TimeDisplayWindow : public Ship::GuiWindow {
void TimeDisplayUpdateDisplayOptions();
void TimeDisplayInitSettings();
typedef enum {
typedef enum TimerDisplay {
DISPLAY_IN_GAME_TIMER,
DISPLAY_TIME_OF_DAY,
DISPLAY_CONDITIONAL_TIMER,
DISPLAY_NAVI_TIMER
};
} TimerDisplay;
typedef enum {
typedef enum NaviTimerValues {
NAVI_PREPARE = 600,
NAVI_ACTIVE = 3000,
NAVI_COOLDOWN = 25800,
DAY_BEGINS = 17759,
NIGHT_BEGINS = 49155
};
} NaviTimerValues;
typedef struct {
uint32_t timeID;

View file

@ -20,6 +20,11 @@ static bool sEnteredBlueWarp = false;
* 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) {
// Do nothing when in a boss rush
if (IS_BOSS_RUSH) {
return;
}
bool overrideBlueWarpDestinations =
IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);

View file

@ -65,7 +65,12 @@ void SkipChildRutoInteractions_Register() {
enRu1->action = 42;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0,
Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f);
// If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting
// to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point
// Cutscene of Ruto getting lifted up from getting queued up twice.
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) || enRu1->unk_28C->cameraSetting != 2) {
enRu1->unk_28C->cameraSetting = 1;
}
Actor* sapphire = func_80AEB124(gPlayState);
if (sapphire != NULL) {
Actor_Kill(sapphire);

View file

@ -12,9 +12,15 @@
#include "soh/cvar_prefixes.h"
#include <utils/StringHelper.h>
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "AudioCollection.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
extern "C" {
#include "z64save.h"
extern SaveContext gSaveContext;
}
Vec3f pos = { 0.0f, 0.0f, 0.0f };
f32 freqScale = 1.0f;
s8 reverbAdd = 0;
@ -165,13 +171,20 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence
const std::string previewButton = ICON_FA_PLAY + hiddenKey;
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) == sequenceId) {
if (ImGui::Button(stopButton.c_str())) {
if (UIWidgets::Button(stopButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Stop Preview")
.Color(THEME_COLOR))) {
func_800F5C2C();
CVarSetInteger(CVAR_AUDIO("Playing"), 0);
}
UIWidgets::Tooltip("Stop Preview");
} else {
if (ImGui::Button(previewButton.c_str())) {
if (UIWidgets::Button(previewButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Play Preview")
.Color(THEME_COLOR))) {
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) != 0) {
func_800F5C2C();
CVarSetInteger(CVAR_AUDIO("Playing"), 0);
@ -188,11 +201,10 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence
}
}
}
UIWidgets::Tooltip("Play Preview");
}
}
void Draw_SfxTab(const std::string& tabId, SeqType type) {
void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabName) {
const std::map<u16, SequenceInfo>& map = AudioCollection::Instance->GetAllSequences();
const std::string hiddenTabId = "##" + tabId;
@ -200,7 +212,10 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
const std::string randomizeAllButton = "Randomize All" + hiddenTabId;
const std::string lockAllButton = "Lock All" + hiddenTabId;
const std::string unlockAllButton = "Unlock All" + hiddenTabId;
if (ImGui::Button(resetAllButton.c_str())) {
ImGui::SeparatorText(tabName.c_str());
if (UIWidgets::Button(resetAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
ResetGroup(map, type);
@ -211,7 +226,8 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
}
}
ImGui::SameLine();
if (ImGui::Button(randomizeAllButton.c_str())) {
if (UIWidgets::Button(randomizeAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
RandomizeGroup(type);
@ -222,7 +238,8 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
}
}
ImGui::SameLine();
if (ImGui::Button(lockAllButton.c_str())) {
if (UIWidgets::Button(lockAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
LockGroup(map, type);
@ -233,7 +250,8 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
}
}
ImGui::SameLine();
if (ImGui::Button(unlockAllButton.c_str())) {
if (UIWidgets::Button(unlockAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
UnlockGroup(map, type);
@ -244,10 +262,12 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
}
}
// Longest text in Audio Editor
ImVec2 columnSize = ImGui::CalcTextSize("Navi - Look/Hey/Watchout (Target Enemy)");
ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, columnSize.x + 30);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, columnSize.x + 30);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 160.0f);
for (const auto& [defaultValue, seqData] : map) {
if (~(seqData.category) & type) {
continue;
@ -273,6 +293,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN);
const int initialValue = map.contains(currentValue) ? currentValue : defaultValue;
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo(hiddenKey.c_str(), map.at(initialValue).label.c_str())) {
for (const auto& [value, seqData] : map) {
// If excluded as a replacement sequence, don't show in other dropdowns except the effect's own dropdown.
@ -293,22 +314,30 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
ImGui::EndCombo();
}
UIWidgets::PopStyleCombobox();
ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN);
DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue : currentValue, seqData.sfxKey, type);
auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1;
ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN);
if (ImGui::Button(resetButton.c_str())) {
if (UIWidgets::Button(resetButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Reset to default")
.Color(THEME_COLOR))) {
CVarClear(cvarKey.c_str());
CVarClear(cvarLockKey.c_str());
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
UpdateCurrentBGM(defaultValue, seqData.category);
}
UIWidgets::Tooltip("Reset to default");
ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN);
if (ImGui::Button(randomizeButton.c_str())) {
if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Randomize this sound")
.Color(THEME_COLOR))) {
std::vector<SequenceInfo*> validSequences = {};
for (const auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (seqInfo->category & type) {
@ -327,10 +356,14 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
UpdateCurrentBGM(defaultValue, type);
}
}
UIWidgets::Tooltip("Randomize this sound");
ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN);
if (ImGui::Button(locked ? lockedButton.c_str() : unlockedButton.c_str())) {
if (UIWidgets::Button(locked ? lockedButton.c_str() : unlockedButton.c_str(),
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip(locked ? "Sound locked" : "Sound unlocked")
.Color(THEME_COLOR))) {
if (locked) {
CVarClear(cvarLockKey.c_str());
} else {
@ -338,7 +371,6 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
UIWidgets::Tooltip(locked ? "Sound locked" : "Sound unlocked");
}
ImGui::EndTable();
}
@ -401,10 +433,11 @@ ImVec4 GetSequenceTypeColor(SeqType type) {
}
}
void DrawTypeChip(SeqType type) {
void DrawTypeChip(SeqType type, std::string sequenceName) {
ImGui::BeginDisabled();
ImGui::PushStyleColor(ImGuiCol_Button, GetSequenceTypeColor(type));
ImGui::SmallButton(GetSequenceTypeName(type).c_str());
std::string buttonLabel = GetSequenceTypeName(type) + "##" + sequenceName;
ImGui::Button(buttonLabel.c_str());
ImGui::PopStyleColor();
ImGui::EndDisabled();
}
@ -412,7 +445,7 @@ void DrawTypeChip(SeqType type) {
void AudioEditorRegisterOnSceneInitHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
if (CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) {
if (gSaveContext.gameMode != GAMEMODE_END_CREDITS && CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) {
AudioEditor_RandomizeAll();
}
});
@ -425,114 +458,113 @@ void AudioEditor::InitElement() {
void AudioEditor::DrawElement() {
AudioCollection::Instance->InitializeShufflePool();
float buttonSegments = ImGui::GetContentRegionAvail().x / 4;
if (ImGui::Button("Randomize All Groups", ImVec2(buttonSegments, 30.0f))) {
UIWidgets::Separator();
if (UIWidgets::Button("Randomize All Groups",
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Randomizes all unlocked music and sound effects across tab groups"))) {
AudioEditor_RandomizeAll();
}
UIWidgets::Tooltip("Randomizes all unlocked music and sound effects across tab groups");
ImGui::SameLine();
if (ImGui::Button("Reset All Groups", ImVec2(buttonSegments, 30.0f))) {
if (UIWidgets::Button("Reset All Groups",
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Resets all unlocked music and sound effects across tab groups"))) {
AudioEditor_ResetAll();
}
UIWidgets::Tooltip("Resets all unlocked music and sound effects across tab groups");
ImGui::SameLine();
if (ImGui::Button("Lock All Groups", ImVec2(buttonSegments, 30.0f))) {
if (UIWidgets::Button("Lock All Groups", UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Locks all music and sound effects across tab groups"))) {
AudioEditor_LockAll();
}
UIWidgets::Tooltip("Locks all music and sound effects across tab groups");
ImGui::SameLine();
if (ImGui::Button("Unlock All Groups", ImVec2(buttonSegments, 30.0f))) {
if (UIWidgets::Button("Unlock All Groups",
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Unlocks all music and sound effects across tab groups"))) {
AudioEditor_UnlockAll();
}
UIWidgets::Tooltip("Unlocks all music and sound effects across tab groups");
UIWidgets::Separator();
UIWidgets::PushStyleTabs(THEME_COLOR);
if (ImGui::BeginTabBar("SfxContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
if (ImGui::BeginTabItem("Background Music")) {
Draw_SfxTab("backgroundMusic", SEQ_BGM_WORLD);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Fanfares")) {
Draw_SfxTab("fanfares", SEQ_FANFARE);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Events")) {
Draw_SfxTab("event", SEQ_BGM_EVENT);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Battle Music")) {
Draw_SfxTab("battleMusic", SEQ_BGM_BATTLE);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Ocarina")) {
Draw_SfxTab("instrument", SEQ_INSTRUMENT);
Draw_SfxTab("ocarina", SEQ_OCARINA);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Sound Effects")) {
Draw_SfxTab("sfx", SEQ_SFX);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Voices")) {
Draw_SfxTab("voice", SEQ_VOICE);
ImGui::EndTabItem();
}
static ImVec2 cellPadding(8.0f, 8.0f);
if (ImGui::BeginTabItem("Options")) {
if (ImGui::BeginTabItem("Audio Options")) {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding);
ImGui::BeginTable("Options", 1, ImGuiTableFlags_SizingStretchSame);
ImGui::BeginTable("Audio Options", 1, ImGuiTableFlags_SizingStretchSame);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) {
ImGui::PushItemWidth(-FLT_MIN);
UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", CVAR_AUDIO("EnemyBGMDisable"));
UIWidgets::InsertHelpHoverText(
"Disables the music change when getting close to enemies. Useful for hearing "
"your custom music for each scene more often.");
UIWidgets::EnhancementCheckbox("Disable Leading Music in Lost Woods", CVAR_AUDIO("LostWoodsConsistentVolume"));
UIWidgets::InsertHelpHoverText(
"Disables the volume shifting in the Lost Woods. Useful for hearing "
UIWidgets::CVarCheckbox(
"Mute Low HP Alarm", CVAR_AUDIO("LowHpAlarm"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR).Tooltip("Disable the low HP beeping sound."));
UIWidgets::CVarCheckbox("Disable Navi Call Audio", CVAR_AUDIO("DisableNaviCallAudio"),
UIWidgets::CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Disables the voice audio when Navi calls you."));
UIWidgets::CVarCheckbox(
"Disable Enemy Proximity Music", CVAR_AUDIO("EnemyBGMDisable"),
UIWidgets::CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Disables the music change when getting close to enemies. Useful for hearing "
"your custom music for each scene more often."));
UIWidgets::CVarCheckbox(
"Disable Leading Music in Lost Woods", CVAR_AUDIO("LostWoodsConsistentVolume"),
UIWidgets::CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Disables the volume shifting in the Lost Woods. Useful for hearing "
"your custom music in the Lost Woods if you don't need the navigation assitance "
"the volume changing provides. If toggling this while in the Lost Woods, reload "
"the area for the effect to kick in."
);
UIWidgets::EnhancementCheckbox("Display Sequence Name on Overlay", CVAR_AUDIO("SeqNameOverlay"));
UIWidgets::InsertHelpHoverText(
"Displays the name of the current sequence in the corner of the screen whenever a new sequence "
"is loaded to the main sequence player (does not apply to fanfares or enemy BGM)."
);
"the area for the effect to kick in."));
UIWidgets::CVarCheckbox(
"Display Sequence Name on Overlay", CVAR_AUDIO("SeqNameOverlay"),
UIWidgets::CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Displays the name of the current sequence in the corner of the screen whenever a new "
"sequence "
"is loaded to the main sequence player (does not apply to fanfares or enemy BGM)."));
UIWidgets::CVarSliderInt("Overlay Duration: %d seconds", CVAR_AUDIO("SeqNameOverlayDuration"),
UIWidgets::IntSliderOptions()
.Min(1)
.Max(10)
.DefaultValue(5)
.Size(ImVec2(300.0f, 0.0f))
.Color(THEME_COLOR));
UIWidgets::CVarSliderFloat("Link's voice pitch multiplier", CVAR_AUDIO("LinkVoiceFreqMultiplier"),
UIWidgets::FloatSliderOptions()
.IsPercentage()
.Min(0.4f)
.Max(2.5f)
.DefaultValue(1.0f)
.Size(ImVec2(300.0f, 0.0f))
.Color(THEME_COLOR));
ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
UIWidgets::EnhancementSliderInt("Overlay Duration: %d seconds", "##SeqNameOverlayDuration",
CVAR_AUDIO("SeqNameOverlayDuration"), 1, 10, "", 5);
ImGui::PopItemWidth();
ImGui::NewLine();
ImGui::PopItemWidth();
UIWidgets::EnhancementSliderFloat("Link's voice pitch multiplier: %.1f %%", "##linkVoiceFreqMultiplier",
CVAR_AUDIO("LinkVoiceFreqMultiplier"), 0.4, 2.5, "", 1.0, true, true);
ImGui::SameLine();
const std::string resetButton = "Reset##linkVoiceFreqMultiplier";
if (ImGui::Button(resetButton.c_str())) {
ImGui::SetCursorPosY(ImGui::GetCursorPos().y + 40.f);
if (UIWidgets::Button("Reset##linkVoiceFreqMultiplier",
UIWidgets::ButtonOptions().Size(ImVec2(80, 36)).Padding(ImVec2(5.0f, 0.0f)))) {
CVarSetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0f);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
ImGui::NewLine();
UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", CVAR_AUDIO("RandomizeAllOnNewScene"));
UIWidgets::Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene.");
ImGui::NewLine();
ImGui::PushItemWidth(-FLT_MIN);
UIWidgets::PaddedSeparator();
UIWidgets::PaddedText("The following options are experimental and may cause music\nto sound odd or have other undesireable effects.");
UIWidgets::EnhancementCheckbox("Lower Octaves of Unplayable High Notes", CVAR_AUDIO("ExperimentalOctaveDrop"));
UIWidgets::InsertHelpHoverText("Some custom sequences may have notes that are too high for the game's audio "
UIWidgets::CVarCheckbox(
"Randomize All Music and Sound Effects on New Scene", CVAR_AUDIO("RandomizeAllOnNewScene"),
UIWidgets::CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip(
"Enables randomizing all unlocked music and sound effects when you enter a new scene."));
UIWidgets::CVarCheckbox(
"Lower Octaves of Unplayable High Notes", CVAR_AUDIO("ExperimentalOctaveDrop"),
UIWidgets::CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Some custom sequences may have notes that are too high for the game's audio "
"engine to play. Enabling this checkbox will cause these notes to drop a "
"couple of octaves so they can still harmonize with the other notes of the "
"sequence.");
ImGui::PopItemWidth();
"sequence."));
}
ImGui::EndChild();
ImGui::EndTable();
@ -540,6 +572,36 @@ void AudioEditor::DrawElement() {
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Background Music")) {
Draw_SfxTab("backgroundMusic", SEQ_BGM_WORLD, "Background Music");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Fanfares")) {
Draw_SfxTab("fanfares", SEQ_FANFARE, "Fanfares");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Events")) {
Draw_SfxTab("event", SEQ_BGM_EVENT, "Events");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Battle Music")) {
Draw_SfxTab("battleMusic", SEQ_BGM_BATTLE, "Battle Music");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Ocarina")) {
Draw_SfxTab("instrument", SEQ_INSTRUMENT, "Instruments");
Draw_SfxTab("ocarina", SEQ_OCARINA, "Ocarina");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Sound Effects")) {
Draw_SfxTab("sfx", SEQ_SFX, "Sound Effects");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Voices")) {
Draw_SfxTab("voice", SEQ_VOICE, "Voices");
ImGui::EndTabItem();
}
static bool excludeTabOpen = false;
if (ImGui::BeginTabItem("Audio Shuffle Pool Management")) {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding);
@ -564,9 +626,12 @@ void AudioEditor::DrawElement() {
std::set<SequenceInfo*> seqsToExclude = {};
static ImGuiTextFilter sequenceSearch;
UIWidgets::PushStyleInput(THEME_COLOR);
sequenceSearch.Draw("Filter (inc,-exc)", 490.0f);
UIWidgets::PopStyleInput();
ImGui::SameLine();
if (ImGui::Button("Exclude All")) {
if (UIWidgets::Button("Exclude All",
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
seqsToExclude.insert(seqInfo);
@ -574,7 +639,8 @@ void AudioEditor::DrawElement() {
}
}
ImGui::SameLine();
if (ImGui::Button("Include All")) {
if (UIWidgets::Button("Include All",
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
seqsToInclude.insert(seqInfo);
@ -643,13 +709,17 @@ void AudioEditor::DrawElement() {
ImGui::BeginChild("ChildIncludedSequences", ImVec2(0, -8));
for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
if (ImGui::Button(std::string(ICON_FA_TIMES "##" + seqInfo->sfxKey).c_str())) {
if (UIWidgets::Button(std::string(ICON_FA_TIMES "##" + seqInfo->sfxKey).c_str(),
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) {
seqsToExclude.insert(seqInfo);
}
ImGui::SameLine();
DrawPreviewButton(seqInfo->sequenceId, seqInfo->sfxKey, seqInfo->category);
ImGui::SameLine();
DrawTypeChip(seqInfo->category);
DrawTypeChip(seqInfo->category, seqInfo->label);
ImGui::SameLine();
ImGui::Text("%s", seqInfo->label.c_str());
}
@ -667,13 +737,17 @@ void AudioEditor::DrawElement() {
ImGui::BeginChild("ChildExcludedSequences", ImVec2(0, -8));
for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
if (ImGui::Button(std::string(ICON_FA_PLUS "##" + seqInfo->sfxKey).c_str())) {
if (UIWidgets::Button(std::string(ICON_FA_PLUS "##" + seqInfo->sfxKey).c_str(),
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) {
seqsToInclude.insert(seqInfo);
}
ImGui::SameLine();
DrawPreviewButton(seqInfo->sequenceId, seqInfo->sfxKey, seqInfo->category);
ImGui::SameLine();
DrawTypeChip(seqInfo->category);
DrawTypeChip(seqInfo->category, seqInfo->sfxKey);
ImGui::SameLine();
ImGui::Text("%s", seqInfo->label.c_str());
}
@ -695,6 +769,7 @@ void AudioEditor::DrawElement() {
ImGui::EndTabBar();
}
UIWidgets::PopStyleTabs();
}
std::vector<SeqType> allTypes = { SEQ_BGM_WORLD, SEQ_BGM_EVENT, SEQ_BGM_BATTLE, SEQ_OCARINA, SEQ_FANFARE, SEQ_INSTRUMENT, SEQ_SFX, SEQ_VOICE };

View file

@ -10,31 +10,25 @@
#include <cmath>
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
using namespace UIWidgets;
// Text colors
static ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
static ImVec4 range1Color = ImVec4(1.0f, 0.7f, 0, 1.0f);
static ImVec4 range2Color = ImVec4(0, 1.0f, 0, 1.0f);
static Color_RGBA8 textColorDefault = { 255, 255, 255, 255 };
static Color_RGBA8 range1ColorDefault = { 255, 178, 0, 255 };
static Color_RGBA8 range2ColorDefault = { 0, 255, 0, 255 };
static const char* buttonOutlineOptions[4] = { "Always Shown", "Shown Only While Not Pressed",
"Shown Only While Pressed", "Always Hidden" };
static const char* buttonOutlineOptionsVerbose[4] = { "Outline Always Shown", "Outline Shown Only While Not Pressed",
"Outline Shown Only While Pressed", "Outline Always Hidden" };
static std::unordered_map<int32_t, const char*> buttonOutlineOptions =
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Always Hidden" }};
static std::unordered_map<int32_t, const char*> buttonOutlineOptionsVerbose =
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Outline Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Outline Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Outline Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Outline Always Hidden" }};
static const char* stickModeOptions[3] = { "Always", "While In Use", "Never" };
static Color_RGBA8 vec2Color(ImVec4 vec) {
Color_RGBA8 color;
color.r = vec.x * 255.0;
color.g = vec.y * 255.0;
color.b = vec.z * 255.0;
color.a = vec.w * 255.0;
return color;
}
static ImVec4 color2Vec(Color_RGBA8 color) {
return ImVec4(color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0);
}
static std::unordered_map<int32_t, const char*> stickModeOptions =
{{ STICK_MODE_ALWAYS_SHOWN, "Always" }, { STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" }, { STICK_MODE_ALWAYS_HIDDEN, "Never" }};
InputViewer::~InputViewer() {
SPDLOG_TRACE("destruct input viewer");
@ -399,17 +393,17 @@ void InputViewer::DrawElement() {
(rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
color2Vec(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), vec2Color(range1Color))));
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), range1ColorDefault)));
}
else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
color2Vec(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), vec2Color(range2Color))));
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), range2ColorDefault)));
}
else {
ImGui::PushStyleColor(ImGuiCol_Text, color2Vec(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor"),
vec2Color(textColor))));
ImGui::PushStyleColor(ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"),
textColorDefault)));
}
// Render text
@ -435,157 +429,138 @@ InputViewerSettingsWindow::~InputViewerSettingsWindow() {
void InputViewerSettingsWindow::DrawElement() {
// gInputViewer.Scale
UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", CVAR_INPUT_VIEWER("Scale"), 0.1f, 5.0f, "",
1.0f, false, true);
UIWidgets::Tooltip("Sets the on screen size of the input viewer");
CVarSliderFloat("Input Viewer Scale: %.2f", CVAR_INPUT_VIEWER("Scale"),
FloatSliderOptions().Color(THEME_COLOR).DefaultValue(1.0f).Min(0.1f).Max(5.0f).ShowButtons(true).Tooltip("Sets the on screen size of the input viewer"));
// gInputViewer.EnableDragging
UIWidgets::EnhancementCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.ShowBackground
UIWidgets::EnhancementCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true);
PushStyleHeader(THEME_COLOR);
if (ImGui::CollapsingHeader("Buttons")) {
// gInputViewer.ButtonOutlineMode
UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false);
UIWidgets::EnhancementCombobox(
CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, BUTTON_OUTLINE_NOT_PRESSED,
!CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), "",
CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
UIWidgets::Tooltip(
"Sets the desired visibility behavior for the button outline/background layers. Useful for "
"custom input viewers.");
CVarCombobox("Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions,
ComboboxOptions({{ .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), .disabledTooltip = "Disabled because Global Button Outline is off" }})
.Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)
.Tooltip("Sets the desired visibility behavior for the button outline/background layers. Useful for "
"custom input viewers."));
// gInputViewer.UseGlobalButtonOutlineMode
UIWidgets::EnhancementCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator();
bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
// gInputViewer.ABtn
UIWidgets::EnhancementCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.BBtn
UIWidgets::EnhancementCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##BBtnOutline", CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CUp
UIWidgets::EnhancementCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##CUpOutline", CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CRight
UIWidgets::EnhancementCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##CRightOutline", CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CDown
UIWidgets::EnhancementCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##CDownOutline", CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CLeft
UIWidgets::EnhancementCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##CLeftOutline", CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.LBtn
UIWidgets::EnhancementCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##LBtnOutline", CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.RBtn
UIWidgets::EnhancementCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##RBtnOutline", CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.ZBtn
UIWidgets::EnhancementCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##ZBtnOutline", CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.StartBtn
UIWidgets::EnhancementCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
CVarCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##StartBtnOutline", CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.Dpad
UIWidgets::EnhancementCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, false);
CVarCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##DpadOutline", CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.Mod1
UIWidgets::EnhancementCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, false);
CVarCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##Mmod1Outline", CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.Mod2
UIWidgets::EnhancementCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"), false, "",
UIWidgets::CheckboxGraphics::Checkmark, false);
CVarCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) {
ImGui::Indent();
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose,
BUTTON_OUTLINE_NOT_PRESSED);
CVarCombobox("##Mod2Outline", CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
@ -594,90 +569,74 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Analog Stick")) {
// gInputViewer.AnalogStick.VisibilityMode
UIWidgets::PaddedText("Analog Stick Visibility", true, false);
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
STICK_MODE_ALWAYS_SHOWN);
UIWidgets::Tooltip(
"Determines the conditions under which the moving layer of the analog stick texture is visible.");
CVarCombobox("Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the moving layer of the analog stick texture is visible."));
// gInputViewer.AnalogStick.OutlineMode
UIWidgets::PaddedText("Analog Stick Outline/Background Visibility", true, false);
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), stickModeOptions,
STICK_MODE_ALWAYS_SHOWN);
UIWidgets::Tooltip(
"Determines the conditions under which the analog stick outline/background texture is visible.");
CVarCombobox("Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the analog stick outline/background texture is visible."));
// gInputViewer.AnalogStick.Movement
UIWidgets::EnhancementSliderInt("Analog Stick Movement: %dpx", "##AnalogMovement",
CVAR_INPUT_VIEWER("AnalogStick.Movement"), 0, 200, "", 12, true);
UIWidgets::Tooltip(
"Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers.");
CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(12).ShowButtons(true)
.Tooltip("Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers."));
UIWidgets::PaddedSeparator(true, true);
}
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
// gInputViewer.RightStick.VisibilityMode
UIWidgets::PaddedText("Right Stick Visibility", true, false);
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
STICK_MODE_HIDDEN_IN_DEADZONE);
UIWidgets::Tooltip(
"Determines the conditions under which the moving layer of the right stick texture is visible.");
CVarCombobox("Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the moving layer of the right stick texture is visible."));
// gInputViewer.RightStick.OutlineMode
UIWidgets::PaddedText("Right Stick Outline/Background Visibility", true, false);
UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
STICK_MODE_HIDDEN_IN_DEADZONE);
UIWidgets::Tooltip(
"Determines the conditions under which the right stick outline/background texture is visible.");
CVarCombobox("Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the right stick outline/background texture is visible."));
// gInputViewer.RightStick.Movement
UIWidgets::EnhancementSliderInt("Right Stick Movement: %dpx", "##RightMovement",
CVAR_INPUT_VIEWER("RightStick.Movement"), 0, 200, "", 7, true);
UIWidgets::Tooltip(
"Sets the distance to move the right stick in the input viewer. Useful for custom input viewers.");
CVarSliderInt("Right Stick Movement: %dpx", CVAR_INPUT_VIEWER("RightStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(7).ShowButtons(true)
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."));
UIWidgets::PaddedSeparator(true, true);
}
if (ImGui::CollapsingHeader("Analog Angle Values")) {
// gAnalogAngles
UIWidgets::EnhancementCheckbox("Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"));
UIWidgets::Tooltip("Displays analog stick angle values in the input viewer");
CVarCheckbox("Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Displays analog stick angle values in the input viewer"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0)) {
// gInputViewer.AnalogAngles.TextColor
if (ImGui::ColorEdit4("Text Color", (float*)&textColor)) {
CVarSetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), vec2Color(textColor));
}
CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
// gAnalogAngleScale
UIWidgets::EnhancementSliderFloat("Angle Text Scale: %.2f%%", "##AnalogAngleScale",
CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 0.1f, 5.0f, "", 1.0f, true, true);
CVarSliderFloat("Angle Text Scale: %.2f%%", CVAR_INPUT_VIEWER("AnalogAngles.Scale"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.1f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
// gInputViewer.AnalogAngles.Offset
UIWidgets::EnhancementSliderInt("Angle Text Offset: %dpx", "##AnalogAngleOffset",
CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0, 400, "", 0, true);
CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(400).DefaultValue(0).ShowButtons(true)
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."));
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range1.Enabled
UIWidgets::EnhancementCheckbox("Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"));
UIWidgets::Tooltip(
"Highlights the angle value text when the analog stick is in ESS position (on flat ground)");
CVarCheckbox("Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Highlights the angle value text when the analog stick is in ESS position (on flat ground)"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range1.Color
if (ImGui::ColorEdit4("ESS Color", (float*)&range1Color)) {
CVarSetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), vec2Color(range1Color));
}
CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
}
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range2.Enabled
UIWidgets::EnhancementCheckbox("Highlight Walking Speed Angles",
CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"));
UIWidgets::Tooltip("Highlights the angle value text when the analog stick is at an angle that would "
CVarCheckbox("Highlight Walking Speed Angles", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Highlights the angle value text when the analog stick is at an angle that would "
"produce a walking speed (on flat ground)\n\n"
"Useful for 1.0 Empty Jumpslash Quick Put Away");
"Useful for 1.0 Empty Jumpslash Quick Put Away"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range2.Color
if (ImGui::ColorEdit4("Walking Speed Color", (float*)&range2Color)) {
CVarSetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), vec2Color(range2Color));
}
CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), range2ColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
}
}
}
PopStyleHeader();
}

View file

@ -2,6 +2,7 @@
#include <utils/StringHelper.h>
#include "soh/OTRGlobals.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "z64.h"
#include "soh/cvar_prefixes.h"
#ifndef __WIIU__
@ -10,6 +11,8 @@
#define SCALE_IMGUI_SIZE(value) ((value / 13.0f) * ImGui::GetFontSize())
using namespace UIWidgets;
SohInputEditorWindow::~SohInputEditorWindow() {
}
@ -1062,17 +1065,16 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
}
// todo: clean this up, probably just hardcode to LED_COLOR_SOURCE_GAME and use SoH options only here
if (mapping->GetColorSource() == LED_COLOR_SOURCE_GAME) {
static const char* ledSources[] = {
static std::vector<const char*> ledSources = {
"Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors",
"Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom"
};
UIWidgets::PaddedText("Source");
UIWidgets::EnhancementCombobox(CVAR_SETTING("LEDColorSource"), ledSources, LED_SOURCE_TUNIC_ORIGINAL);
UIWidgets::Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when "
CVarCombobox("Source", CVAR_SETTING("LEDColorSource"), ledSources, UIWidgets::ComboboxOptions().Color(THEME_COLOR).DefaultIndex(LED_SOURCE_TUNIC_ORIGINAL)
.Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when "
"health < 40%. Green otherwise.\n\n"
"Tunics: colors will mirror currently equipped tunic, whether original or the current "
"values in Cosmetics Editor.\n\n"
"Custom: single, solid color");
"Custom: single, solid color"));
if (CVarGetInteger(CVAR_SETTING("LEDColorSource"), 1) == LED_SOURCE_CUSTOM) {
UIWidgets::Spacer(3);
auto port1Color = CVarGetColor24(CVAR_SETTING("LEDPort1Color"), { 255, 255, 255 });
@ -1090,14 +1092,13 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
ImGui::SameLine();
ImGui::Text("Custom Color");
}
UIWidgets::PaddedEnhancementSliderFloat("Brightness: %.1f %%", "##LED_Brightness", CVAR_SETTING("LEDBrightness"), 0.0f,
1.0f, "", 1.0f, true, true);
UIWidgets::Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off.");
UIWidgets::PaddedEnhancementCheckbox(
"Critical Health Override", CVAR_SETTING("LEDCriticalOverride"), true, true,
CVarGetInteger(CVAR_SETTING("LEDColorSource"), LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH,
"Override redundant for health source.", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Shows red color when health is critical, otherwise displays according to color source.");
CVarSliderFloat("Brightness: %.1f %%", CVAR_SETTING("LEDBrightness"),
FloatSliderOptions().IsPercentage().Min(0.0f).Max(1.0f).DefaultValue(1.0f).ShowButtons(true)
.Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off."));
CVarCheckbox("Critical Health Override", CVAR_SETTING("LEDCriticalOverride"),
CheckboxOptions({{ .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"), LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH,
.disabledTooltip = "Override redundant for health source."}}).DefaultValue(true)
.Tooltip("Shows red color when health is critical, otherwise displays according to color source."));
}
ImGui::TreePop();
}
@ -1281,7 +1282,6 @@ void SohInputEditorWindow::DrawMapping(CustomButtonMap& mapping, float labelWidt
preview = "Unknown";
}
UIWidgets::Spacer(0);
ImVec2 cursorPos = ImGui::GetCursorPos();
ImVec2 textSize = ImGui::CalcTextSize(mapping.label);
ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4);
@ -1303,16 +1303,16 @@ void SohInputEditorWindow::DrawMapping(CustomButtonMap& mapping, float labelWidt
}
ImGui::EndCombo();
}
UIWidgets::Spacer(0);
}
void SohInputEditorWindow::DrawOcarinaControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x, cursor.y + 5));
UIWidgets::EnhancementCheckbox("Dpad Ocarina Playback", CVAR_SETTING("CustomOcarina.Dpad"));
UIWidgets::EnhancementCheckbox("Right Stick Ocarina Playback", CVAR_SETTING("CustomOcarina.RightStick"));
UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", CVAR_SETTING("CustomOcarina.Enabled"));
CheckboxOptions checkOpt = CheckboxOptions().Color(THEME_COLOR);
CVarCheckbox("Dpad Ocarina Playback", CVAR_SETTING("CustomOcarina.Dpad"), checkOpt);
CVarCheckbox("Right Stick Ocarina Playback", CVAR_SETTING("CustomOcarina.RightStick"), checkOpt);
CVarCheckbox("Customize Ocarina Controls", CVAR_SETTING("CustomOcarina.Enabled"), checkOpt);
if (!CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) {
ImGui::BeginDisabled();
@ -1344,60 +1344,56 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"));
UIWidgets::Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming");
CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"));
if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
UIWidgets::PaddedEnhancementCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"));
UIWidgets::Tooltip("Changes the left stick to move the player while in first person mode");
CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Changes the left stick to move the player while in first person mode"));
}
UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"));
UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming");
UIWidgets::PaddedEnhancementCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming");
UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Inverts the Shield Aiming X Axis");
UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"));
UIWidgets::Tooltip("Inverts the Shield Aiming Y Axis");
UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming");
UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"));
UIWidgets::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming");
if (UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), true, false)) {
CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Shield Aiming X Axis"));
CVarCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Inverts the Shield Aiming Y Axis"));
CVarCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"));
CVarCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"));
if (CVarCheckbox("Enable Custom Aiming/First-Person sensitivity", CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), CheckboxOptions().Color(THEME_COLOR))) {
if (!CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X"));
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y"));
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
}
if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
UIWidgets::EnhancementSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", "##FirstPersonSensitivity Horizontal",
CVAR_SETTING("FirstPersonCameraSensitivity.X"), 0.01f, 5.0f, "", 1.0f, true);
UIWidgets::EnhancementSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", "##FirstPersonSensitivity Vertical",
CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 0.01f, 5.0f, "", 1.0f, true);
CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.X"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.Y"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
}
UIWidgets::Spacer(0);
Ship::GuiWindow::EndGroupPanel(0);
UIWidgets::Spacer(0);
cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Free Look", CVAR_SETTING("FreeLook.Enabled"));
UIWidgets::Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the "
"controller config menu, and map the camera stick to the right stick.");
UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"));
UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free look");
UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Free look");
UIWidgets::Spacer(0);
UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", "##ThirdPersonSensitivity Horizontal",
CVAR_SETTING("FreeLook.CameraSensitivity.X"), 0.01f, 5.0f, "", 1.0f, true, true, false, true);
UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", "##ThirdPersonSensitivity Vertical",
CVAR_SETTING("FreeLook.CameraSensitivity.Y"), 0.01f, 5.0f, "", 1.0f, true, true, false, true);
UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist",
CVAR_SETTING("FreeLook.MaxCameraDistance"), 100, 900, "", 185, true, false, true);
UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed",
CVAR_SETTING("FreeLook.TransitionSpeed"), 0, 900, "", 25, true, false, true);
CVarCheckbox("Free Look", CVAR_SETTING("FreeLook.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the "
"controller config menu, and map the camera stick to the right stick."));
CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Inverts the Camera X Axis in:\n-Free look"));
CVarCheckbox("Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-Free look"));
CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.X"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.Y"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderInt("Camera Distance: %d", CVAR_SETTING("FreeLook.MaxCameraDistance"), IntSliderOptions().Color(THEME_COLOR).Min(100).Max(900).DefaultValue(185).ShowButtons(true));
CVarSliderInt("Camera Transition Speed: %d", CVAR_SETTING("FreeLook.TransitionSpeed"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(900).DefaultValue(25).ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0);
}
@ -1405,17 +1401,17 @@ void SohInputEditorWindow::DrawDpadControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"));
UIWidgets::Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold C-Up to equip instead of navigate");
UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"));
UIWidgets::Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad");
CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold C-Up to equip instead of navigate"));
CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
ImGui::BeginDisabled();
}
UIWidgets::PaddedEnhancementCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held");
CVarCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
ImGui::EndDisabled();
@ -1505,10 +1501,10 @@ void SohInputEditorWindow::DrawLinkTab() {
}
if (ImGui::CollapsingHeader("D-Pad", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_UP).c_str(), portIndex, BTN_DUP);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_DOWN).c_str(), portIndex, BTN_DDOWN);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_LEFT).c_str(), portIndex, BTN_DLEFT);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_DRIGHT);
DrawButtonLine(StringHelper::Sprintf("D %s", ICON_FA_ARROW_UP).c_str(), portIndex, BTN_DUP);
DrawButtonLine(StringHelper::Sprintf("D %s", ICON_FA_ARROW_DOWN).c_str(), portIndex, BTN_DDOWN);
DrawButtonLine(StringHelper::Sprintf("D %s", ICON_FA_ARROW_LEFT).c_str(), portIndex, BTN_DLEFT);
DrawButtonLine(StringHelper::Sprintf("D %s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_DRIGHT);
}
if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
@ -1536,30 +1532,24 @@ void SohInputEditorWindow::DrawLinkTab() {
DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"), true, false);
UIWidgets::Tooltip("Hold the assigned button to change the maximum walking or swimming speed");
CVarCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Hold the assigned button to change the maximum walking or swimming speed"));
if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) {
UIWidgets::Spacer(5);
Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding",
CVAR_SETTING("WalkModifier.SpeedToggle"), true, false);
CVarCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"), CheckboxOptions().Color(THEME_COLOR));
Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity",
CVAR_SETTING("WalkModifier.DoesntChangeJump"), true, false);
UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1",
CVAR_SETTING("WalkModifier.Mapping1"), 0.0f, 5.0f, "", 1.0f,
true, true, false, true);
UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2",
CVAR_SETTING("WalkModifier.Mapping2"), 0.0f, 5.0f, "", 1.0f,
true, true, false, true);
CVarCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"), CheckboxOptions().Color(THEME_COLOR));
CVarSliderFloat("Walk Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.Mapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Walk Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.Mapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1",
CVAR_SETTING("WalkModifier.SwimMapping1"), 0.0f, 5.0f, "", 1.0f,
true, true, false, true);
UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2",
CVAR_SETTING("WalkModifier.SwimMapping2"), 0.0f, 5.0f, "", 1.0f,
true, true, false, true);
CVarSliderFloat("Swim Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Swim Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::EndGroupPanel(0);
}
@ -1659,9 +1649,7 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo
UpdateBitmaskToMappingIds(portIndex);
UpdateStickDirectionToMappingIds(portIndex);
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
PushStyleHeader(THEME_COLOR);
if (ImGui::CollapsingHeader("Buttons", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
DrawButtonLine("A", portIndex, BTN_A, CHIP_COLOR_N64_BLUE);
@ -1690,19 +1678,20 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo
DrawStickSection(portIndex, Ship::LEFT, 0);
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
PopStyleHeader();
ImGui::EndTabItem();
}
}
void SohInputEditorWindow::DrawClearAllButton(uint8_t portIndex) {
PushStyleButton(THEME_COLOR);
if (ImGui::Button("Clear All", ImGui::CalcTextSize("Clear All") * 2)) {
ImGui::OpenPopup("Clear All##clearAllPopup");
}
PopStyleButton();
if (ImGui::BeginPopupModal("Clear All##clearAllPopup", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("This will clear all mappings for port %d.\n\nContinue?", portIndex + 1);
PushStyleButton(THEME_COLOR);
if (ImGui::Button("Cancel")) {
ImGui::CloseCurrentPopup();
}
@ -1710,6 +1699,7 @@ void SohInputEditorWindow::DrawClearAllButton(uint8_t portIndex) {
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->ClearAllMappings();
ImGui::CloseCurrentPopup();
}
PopStyleButton();
ImGui::EndPopup();
}
}
@ -1717,22 +1707,23 @@ void SohInputEditorWindow::DrawClearAllButton(uint8_t portIndex) {
void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
ImGui::SameLine();
auto popupId = StringHelper::Sprintf("setDefaultsPopup##%d", portIndex);
PushStyleButton(THEME_COLOR);
if (ImGui::Button(StringHelper::Sprintf("Set Defaults##%d", portIndex).c_str(),
ImVec2(ImGui::CalcTextSize("Set Defaults") * 2))) {
ImGui::OpenPopup(popupId.c_str());
}
PopStyleButton();
if (ImGui::BeginPopup(popupId.c_str())) {
bool shouldClose = false;
ImGui::PushStyleColor(ImGuiCol_Button, BUTTON_COLOR_KEYBOARD_BEIGE);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED);
PushStyleButton(BUTTON_COLOR_KEYBOARD_BEIGE);
if (ImGui::Button(StringHelper::Sprintf("%s Keyboard", ICON_FA_KEYBOARD_O).c_str())) {
ImGui::OpenPopup("Set Defaults for Keyboard");
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
PopStyleButton();
if (ImGui::BeginPopupModal("Set Defaults for Keyboard", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("This will clear all existing mappings for\nKeyboard on port %d.\n\nContinue?", portIndex + 1);
PushStyleButton(THEME_COLOR);
if (ImGui::Button("Cancel")) {
shouldClose = true;
ImGui::CloseCurrentPopup();
@ -1747,21 +1738,21 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
shouldClose = true;
ImGui::CloseCurrentPopup();
}
PopStyleButton();
ImGui::EndPopup();
}
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
GetButtonColorsForDeviceType(Ship::PhysicalDeviceType::SDLGamepad, buttonColor, buttonHoveredColor);
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
PushStyleButton(buttonColor);
if (ImGui::Button(StringHelper::Sprintf("%s %s", ICON_FA_GAMEPAD, "Gamepad (SDL)").c_str())) {
ImGui::OpenPopup("Set Defaults for Gamepad (SDL)");
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
PopStyleButton();
if (ImGui::BeginPopupModal("Set Defaults for Gamepad (SDL)", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?", portIndex + 1);
PushStyleButton(THEME_COLOR);
if (ImGui::Button("Cancel")) {
shouldClose = true;
ImGui::CloseCurrentPopup();
@ -1776,18 +1767,26 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
shouldClose = true;
ImGui::CloseCurrentPopup();
}
PopStyleButton();
ImGui::EndPopup();
}
PushStyleButton(THEME_COLOR);
if (ImGui::Button("Cancel") || shouldClose) {
ImGui::CloseCurrentPopup();
}
PopStyleButton();
ImGui::EndPopup();
}
}
void SohInputEditorWindow::DrawElement() {
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
ImVec4 themeColor = ColorValues.at(THEME_COLOR);
ImGui::PushStyleColor(ImGuiCol_Tab, ImVec4(themeColor.x, themeColor.y, themeColor.z, 0.8f));
ImGui::PushStyleColor(ImGuiCol_TabHovered, ImVec4(themeColor.x, themeColor.y, themeColor.z, 0.6f));
ImGui::PushStyleColor(ImGuiCol_TabActive, ImVec4(themeColor.x, themeColor.y, themeColor.z, 0.6f));
ImGui::BeginTabBar("##ControllerConfigPortTabs");
DrawLinkTab();
DrawIvanTab();
@ -1796,4 +1795,6 @@ void SohInputEditorWindow::DrawElement() {
DrawDebugPortTab(3);
}
ImGui::EndTabBar();
ImGui::PopStyleColor(3);
ImGui::PopFont();
}

File diff suppressed because it is too large Load diff

View file

@ -52,7 +52,6 @@ static float TablesCellsWidth = 300.0f;
static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
ImVec4 GetRandomValue();
void CosmeticsEditor_RandomizeAll();
void CosmeticsEditor_RandomizeGroup(CosmeticGroup group);
void CosmeticsEditor_ResetAll();

View file

@ -79,6 +79,7 @@ static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std:
if (args[8][0] != ',') {
spawnPoint.rot.z = std::stoi(args[8]);
}
[[fallthrough]];
case 6:
if (args[3][0] != ',') {
spawnPoint.pos.x = std::stoi(args[3]);

View file

@ -1,6 +1,9 @@
#include "MessageViewer.h"
#include <soh/SohGui/UIWidgets.hpp>
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "soh/OTRGlobals.h"
#include <textures/message_static/message_static.h>
#include "../custom-message/CustomMessageManager.h"
@ -13,6 +16,8 @@
extern "C" u8 sMessageHasSetSfx;
using namespace UIWidgets;
void MessageViewer::InitElement() {
CustomMessageManager::Instance->AddCustomMessageTable(TABLE_ID);
mTableIdBuf = static_cast<char*>(calloc(MAX_STRING_SIZE, sizeof(char)));
@ -23,6 +28,7 @@ void MessageViewer::InitElement() {
void MessageViewer::DrawElement() {
ImGui::Text("Table ID");
ImGui::SameLine();
PushStyleInput(THEME_COLOR);
ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum);
UIWidgets::InsertHelpHoverText("Leave blank for vanilla table");
ImGui::Text("Text ID");
@ -38,6 +44,8 @@ void MessageViewer::DrawElement() {
UIWidgets::InsertHelpHoverText("Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F).");
break;
}
PopStyleInput();
PushStyleCheckbox(THEME_COLOR);
if (ImGui::RadioButton("Hexadecimal", &mTextIdBase, HEXADECIMAL)) {
memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE);
}
@ -45,8 +53,10 @@ void MessageViewer::DrawElement() {
if (ImGui::RadioButton("Decimal", &mTextIdBase, DECIMAL)) {
memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE);
}
PopStyleCheckbox();
ImGui::Text("Language");
ImGui::SameLine();
PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##Language", mLanguages[mLanguage])) {
// ReSharper disable CppDFAUnreachableCode
for (size_t i = 0; i < mLanguages.size(); i++) {
@ -58,7 +68,9 @@ void MessageViewer::DrawElement() {
}
ImGui::EndCombo();
}
PopStyleCombobox();
UIWidgets::InsertHelpHoverText("Which language to load from the selected text ID");
PushStyleButton(THEME_COLOR);
if (ImGui::Button("Display Message##ExistingMessage")) {
mDisplayExistingMessageClicked = true;
}
@ -66,11 +78,13 @@ void MessageViewer::DrawElement() {
UIWidgets::InsertHelpHoverText("Enter a string using Custom Message Syntax to preview it in-game. "
"Any newline (\\n) characters inserted by the Enter key will be stripped "
"from the output.");
PushStyleInput(THEME_COLOR);
ImGui::InputTextMultiline("##CustomMessage", mCustomMessageBuf, MAX_STRING_SIZE);
PopStyleInput();
if (ImGui::Button("Display Message##CustomMessage")) {
mDisplayCustomMessageClicked = true;
}
// ReSharper restore CppDFAUnreachableCode
PopStyleButton();
}
void MessageViewer::UpdateElement() {

View file

@ -1,6 +1,7 @@
#include "actorViewer.h"
#include "../../util.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "soh/ActorDB.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/nametag.h"
@ -59,6 +60,8 @@ std::array<const char*, 12> acMapping = {
"Chest"
};
using namespace UIWidgets;
typedef enum {
ACTORVIEWER_NAMETAGS_NONE,
ACTORVIEWER_NAMETAGS_DESC,
@ -70,29 +73,18 @@ const std::string GetActorDescription(u16 id) {
return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.desc : "???";
}
template <typename T> void DrawGroupWithBorder(T&& drawFunc) {
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
// First group encapsulates the inner portion and border
ImGui::BeginGroup();
ImVec2 padding = ImGui::GetStyle().FramePadding;
ImVec2 p0 = ImGui::GetCursorScreenPos();
ImGui::SetCursorScreenPos(ImVec2(p0.x + padding.x, p0.y + padding.y));
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY);
// Second group encapsulates just the inner portion
ImGui::BeginGroup();
ImGui::AlignTextToFramePadding();
drawFunc();
ImGui::Dummy(padding);
ImGui::EndGroup();
ImVec2 p1 = ImGui::GetItemRectMax();
p1.x += padding.x;
ImVec4 borderCol = ImGui::GetStyle().Colors[ImGuiCol_Border];
ImGui::GetWindowDrawList()->AddRect(
p0, p1, IM_COL32(borderCol.x * 255, borderCol.y * 255, borderCol.z * 255, borderCol.w * 255));
ImGui::EndGroup();
ImGui::EndChild();
}
void PopulateActorDropdown(int i, std::vector<Actor*>& data) {
@ -938,7 +930,7 @@ void ActorViewerWindow::DrawElement() {
static std::string filler = "Please select";
static std::vector<Actor*> list;
static u16 lastSceneId = 0;
static char searchString[64] = "";
static std::string searchString = "";
static s16 currentSelectedInDropdown;
static std::vector<u16> actors;
@ -951,13 +943,13 @@ void ActorViewerWindow::DrawElement() {
filler = "Please Select";
list.clear();
needs_reset = false;
for (size_t i = 0; i < ARRAY_COUNT(searchString); i += 1) {
searchString[i] = 0;
}
searchString = "";
currentSelectedInDropdown = -1;
actors.clear();
}
lastSceneId = gPlayState->sceneNum;
PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Actor Type", acMapping[category])) {
for (int i = 0; i < acMapping.size(); i++) {
if (ImGui::Selectable(acMapping[i])) {
@ -990,7 +982,9 @@ void ActorViewerWindow::DrawElement() {
}
ImGui::EndCombo();
}
PopStyleCombobox();
PushStyleHeader(THEME_COLOR);
if (ImGui::TreeNode("Selected Actor")) {
DrawGroupWithBorder([&]() {
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
@ -998,46 +992,52 @@ void ActorViewerWindow::DrawElement() {
ImGui::Text("Category: %s", acMapping[display->category]);
ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params);
});
}, "Selected Actor");
ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR);
ImGui::Text("Actor Position");
ImGui::InputScalar("x pos", ImGuiDataType_Float, &display->world.pos.x);
ImGui::InputScalar("X##CurPos", ImGuiDataType_Float, &display->world.pos.x);
ImGui::InputScalar("Y##CurPos", ImGuiDataType_Float, &display->world.pos.y);
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "Actor Position");
ImGui::SameLine();
ImGui::InputScalar("y pos", ImGuiDataType_Float, &display->world.pos.y);
ImGui::SameLine();
ImGui::InputScalar("z pos", ImGuiDataType_Float, &display->world.pos.z);
});
DrawGroupWithBorder([&]() {
PushStyleInput(THEME_COLOR);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::Text("Actor Rotation");
ImGui::InputScalar("x rot", ImGuiDataType_S16, &display->world.rot.x);
ImGui::SameLine();
ImGui::InputScalar("y rot", ImGuiDataType_S16, &display->world.rot.y);
ImGui::SameLine();
ImGui::InputScalar("z rot", ImGuiDataType_S16, &display->world.rot.z);
});
ImGui::InputScalar("X##CurRot", ImGuiDataType_S16, &display->world.rot.x);
ImGui::InputScalar("Y##CurRot", ImGuiDataType_S16, &display->world.rot.y);
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "Actor Rotation");
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
PushStyleInput(THEME_COLOR);
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display->colChkInfo.health);
PopStyleInput();
UIWidgets::InsertHelpHoverText("Some actors might not use this!");
}
DrawGroupWithBorder([&]() {
ImGui::Text("flags");
UIWidgets::DrawFlagArray32("flags", display->flags);
});
}, "flags");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
ImGui::Text("bgCheckFlags");
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
});
}, "bgCheckFlags");
if (ImGui::Button("Refresh")) {
if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) {
PopulateActorDropdown(category, list);
switch (rm) {
case INTERACT:
@ -1053,13 +1053,13 @@ void ActorViewerWindow::DrawElement() {
}
}
if (ImGui::Button("Go to Actor")) {
if (Button("Go to Actor", ButtonOptions().Color(THEME_COLOR))) {
Player* player = GET_PLAYER(gPlayState);
Math_Vec3f_Copy(&player->actor.world.pos, &display->world.pos);
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
}
if (ImGui::Button("Fetch from Target")) {
if (Button("Fetch from Target", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->talkActor;
if (fetch != NULL) {
@ -1069,8 +1069,7 @@ void ActorViewerWindow::DrawElement() {
rm = TARGET;
}
}
UIWidgets::InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies");
if (ImGui::Button("Fetch from Held")) {
if (Button("Fetch from Held", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->heldActor;
if (fetch != NULL) {
@ -1080,8 +1079,7 @@ void ActorViewerWindow::DrawElement() {
rm = HELD;
}
}
UIWidgets::InsertHelpHoverText("Grabs actor that Link is holding");
if (ImGui::Button("Fetch from Interaction")) {
if (Button("Fetch from Interaction", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->interactRangeActor;
if (fetch != NULL) {
@ -1091,21 +1089,21 @@ void ActorViewerWindow::DrawElement() {
rm = INTERACT;
}
}
UIWidgets::InsertHelpHoverText("Grabs actor from \"interaction range\"");
ImGui::TreePop();
}
if (ImGui::TreeNode("New...")) {
ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
//ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
if (ImGui::InputText("Search Actor", searchString, ARRAY_COUNT(searchString))) {
actors = GetActorsWithDescriptionContainingString(std::string(searchString));
if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) {
actors = GetActorsWithDescriptionContainingString(searchString);
currentSelectedInDropdown = -1;
}
if (searchString[0] != 0 && !actors.empty()) {
if (!SohUtils::IsStringEmpty(searchString) && !actors.empty()) {
std::string preview = currentSelectedInDropdown == -1 ? "Please Select" : ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc;
PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Results", preview.c_str())) {
for (u8 i = 0; i < actors.size(); i++) {
if (ImGui::Selectable(
@ -1118,6 +1116,7 @@ void ActorViewerWindow::DrawElement() {
}
ImGui::EndCombo();
}
PopStyleCombobox();
}
ImGui::Text("%s", GetActorDescription(newActor.id).c_str());
@ -1125,44 +1124,51 @@ void ActorViewerWindow::DrawElement() {
newActor.params = 0;
}
UIWidgets::EnhancementCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"));
UIWidgets::InsertHelpHoverText("Changes the actor specific param menus with a direct input");
CVarCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), CheckboxOptions().Tooltip("Changes the actor specific param menus with a direct input"));
if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), 0)) {
PushStyleInput(THEME_COLOR);
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);
PopStyleInput();
} else if (std::find(noParamsActors.begin(), noParamsActors.end(), newActor.id) == noParamsActors.end()) {
CreateActorSpecificData();
if (actorSpecificData.find(newActor.id) == actorSpecificData.end()) {
PushStyleInput(THEME_COLOR);
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);
PopStyleInput();
} else {
DrawGroupWithBorder([&]() {
ImGui::Text("Actor Specific Data");
newActor.params = actorSpecificData[newActor.id](newActor.params);
});
}, "Actor Specific Data");
}
}
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Position");
ImGui::InputScalar("posX", ImGuiDataType_Float, &newActor.pos.x);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("X##NewPos", ImGuiDataType_Float, &newActor.pos.x);
ImGui::InputScalar("Y##NewPos", ImGuiDataType_Float, &newActor.pos.y);
ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "New Actor Position");
ImGui::SameLine();
ImGui::InputScalar("posY", ImGuiDataType_Float, &newActor.pos.y);
ImGui::SameLine();
ImGui::InputScalar("posZ", ImGuiDataType_Float, &newActor.pos.z);
});
DrawGroupWithBorder([&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Rotation");
ImGui::InputScalar("rotX", ImGuiDataType_S16, &newActor.rot.x);
ImGui::SameLine();
ImGui::InputScalar("rotY", ImGuiDataType_S16, &newActor.rot.y);
ImGui::SameLine();
ImGui::InputScalar("rotZ", ImGuiDataType_S16, &newActor.rot.z);
});
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("X##NewRot", ImGuiDataType_S16, &newActor.rot.x);
ImGui::InputScalar("Y##NewRot", ImGuiDataType_S16, &newActor.rot.y);
ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "New Actor Rotation");
if (ImGui::Button("Fetch from Link")) {
if (Button("Fetch from Link", ButtonOptions().Color(THEME_COLOR))) {
Player* player = GET_PLAYER(gPlayState);
Vec3f newPos = player->actor.world.pos;
Vec3s newRot = player->actor.world.rot;
@ -1170,7 +1176,7 @@ void ActorViewerWindow::DrawElement() {
newActor.rot = newRot;
}
if (ImGui::Button("Spawn")) {
if (Button("Spawn", ButtonOptions().Color(THEME_COLOR))) {
if (ActorDB::Instance->RetrieveEntry(newActor.id).entry.valid) {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, newActor.id, newActor.pos.x, newActor.pos.y,
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params, 0);
@ -1179,7 +1185,7 @@ void ActorViewerWindow::DrawElement() {
}
}
if (ImGui::Button("Spawn as Child")) {
if (Button("Spawn as Child", ButtonOptions().Color(THEME_COLOR))) {
Actor* parent = display;
if (parent != NULL) {
if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX &&
@ -1193,28 +1199,26 @@ void ActorViewerWindow::DrawElement() {
}
}
if (ImGui::Button("Reset")) {
if (Button("Reset", ButtonOptions().Color(THEME_COLOR))) {
newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } };
}
ImGui::TreePop();
}
PopStyleHeader();
static const char* nameTagOptions[] = {
"None",
"Short Description",
"Actor ID",
"Both"
static std::unordered_map<int32_t, const char*> nameTagOptions = {
{ 0, "None" },
{ 1, "Short Description" },
{ 2, "Actor ID" },
{ 3, "Both" },
};
UIWidgets::Spacer(0);
ImGui::Text("Actor Name Tags");
if (UIWidgets::EnhancementCombobox(CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions, ACTORVIEWER_NAMETAGS_NONE)) {
if (CVarCombobox("Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions,
ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) {
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
ActorViewer_AddTagForAllActors();
}
UIWidgets::Tooltip("Adds \"name tags\" above actors for identification");
} else {
ImGui::Text("Global Context needed for actor info!");
if (needs_reset) {
@ -1223,9 +1227,7 @@ void ActorViewerWindow::DrawElement() {
filler = "Please Select";
list.clear();
needs_reset = false;
for (size_t i = 0; i < ARRAY_COUNT(searchString); i += 1) {
searchString[i] = 0;
}
searchString = "";
currentSelectedInDropdown = -1;
actors.clear();
}

View file

@ -1,6 +1,7 @@
#include "colViewer.h"
#include "../../frame_interpolation.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include <vector>
#include <string>
@ -19,12 +20,12 @@ extern "C" {
extern PlayState* gPlayState;
}
enum class ColRenderSetting { Disabled, Solid, Transparent };
typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting ;
static const char* ColRenderSettingNames[] = {
"Disabled",
"Solid",
"Transparent",
static std::unordered_map<int32_t, const char*> ColRenderSettingNames = {
{ ColRenderDisabled, "Disabled" },
{ ColRenderSolid, "Solid" },
{ ColRenderTransparent, "Transparent" },
};
ImVec4 scene_col;
@ -53,45 +54,69 @@ static std::vector<Vtx> cylinderVtx;
static std::vector<Gfx> sphereGfx;
static std::vector<Vtx> sphereVtx;
using namespace UIWidgets;
// Draws the ImGui window for the collision viewer
void ColViewerWindow::DrawElement() {
UIWidgets::EnhancementCheckbox("Enabled", CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"));
CheckboxOptions checkOpt = CheckboxOptions().Color(THEME_COLOR);
ComboboxOptions comboOpt = ComboboxOptions().Color(THEME_COLOR);
CVarCheckbox("Enabled", CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), checkOpt);
UIWidgets::LabeledRightAlignedEnhancementCombobox("Scene", CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), ColRenderSettingNames, COLVIEW_DISABLED);
UIWidgets::LabeledRightAlignedEnhancementCombobox("Bg Actors", CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), ColRenderSettingNames, COLVIEW_DISABLED);
UIWidgets::LabeledRightAlignedEnhancementCombobox("Col Check", CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), ColRenderSettingNames, COLVIEW_DISABLED);
UIWidgets::LabeledRightAlignedEnhancementCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, COLVIEW_DISABLED);
CVarCombobox("Scene", CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), ColRenderSettingNames, comboOpt);
CVarCombobox("Bg Actors", CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), ColRenderSettingNames, comboOpt);
CVarCombobox("Col Check", CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), ColRenderSettingNames, comboOpt);
CVarCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, comboOpt);
UIWidgets::EnhancementCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"), false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"with the scene geometry, but can cause other artifacts.");
UIWidgets::EnhancementCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"));
UIWidgets::InsertHelpHoverText("Applies the scene's shading to the collision display.");
CVarCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"),
checkOpt.DefaultValue(true).Tooltip("Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"with the scene geometry, but can cause other artifacts."));
CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"), checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display."));
// This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered()
const std::string colorHelpText = "View and change the colors used for collision display.";
PushStyleHeader(THEME_COLOR);
if (ImGui::TreeNode("Colors")) {
UIWidgets::InsertHelpHoverText(colorHelpText);
UIWidgets::Tooltip(colorHelpText.c_str());
UIWidgets::EnhancementColor("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), scene_col, ImVec4(255, 255, 255, 255), false);
UIWidgets::EnhancementColor("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), hookshot_col, ImVec4(128, 128, 255, 255),
false);
UIWidgets::EnhancementColor("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), entrance_col, ImVec4(0, 255, 0, 255), false);
UIWidgets::EnhancementColor("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"),
specialSurface_col, ImVec4(192, 255, 192, 255), false);
UIWidgets::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"),
interactable_col, ImVec4(192, 0, 192, 255), false);
UIWidgets::EnhancementColor("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), slope_col, ImVec4(255, 255, 128, 255), false);
UIWidgets::EnhancementColor("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), void_col, ImVec4(255, 0, 0, 255), false);
UIWidgets::EnhancementColor("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), oc_col, ImVec4(255, 255, 255, 255), false);
UIWidgets::EnhancementColor("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), ac_col, ImVec4(0, 0, 255, 255), false);
UIWidgets::EnhancementColor("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), at_col, ImVec4(255, 0, 0, 255), false);
UIWidgets::EnhancementColor("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), waterbox_col, ImVec4(0, 0, 255, 255), false);
if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
scene_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }));
}
if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
hookshot_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }));
}
if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
entrance_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }));
}
if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
specialSurface_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }));
}
if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
interactable_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }));
}
if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
slope_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }));
}
if (CVarColorPicker("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
void_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }));
}
if (CVarColorPicker("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
oc_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }));
}
if (CVarColorPicker("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
ac_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }));
}
if (CVarColorPicker("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
at_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }));
}
if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
waterbox_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }));
}
ImGui::TreePop();
} else {
UIWidgets::InsertHelpHoverText(colorHelpText);
UIWidgets::Tooltip(colorHelpText.c_str());
}
PopStyleHeader();
}
// Calculates the normal for a triangle at the 3 specified points
@ -287,7 +312,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
uint64_t cm;
uint32_t gm;
if (setting == ColRenderSetting::Transparent) {
if (setting == ColRenderTransparent) {
rm = Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL;
blc1 = GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA);
blc2 = GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA);
@ -301,7 +326,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Decal"), 1) != 0) {
rm |= ZMODE_DEC;
} else if (setting == ColRenderSetting::Transparent) {
} else if (setting == ColRenderTransparent) {
rm |= ZMODE_XLU;
} else {
rm |= ZMODE_OPA;
@ -340,21 +365,21 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
CollisionPoly* poly = &col->polyList[i];
if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot.Value"), { 128, 128, 255, 255 });
} else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), {192, 0, 192, 255});
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable.Value"), {192, 0, 192, 255});
} else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid.Value"), { 255, 0, 0, 255 });
} else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) ||
func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x05) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance.Value"), { 0, 255, 0, 255 });
} else if (func_80041D4C(&gPlayState->colCtx, poly, bgId) != 0 ||
SurfaceType_IsWallDamage(&gPlayState->colCtx, poly, bgId)) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface.Value"), { 192, 255, 192, 255 });
} else if (SurfaceType_GetSlope(&gPlayState->colCtx, poly, bgId) == 0x01) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope.Value"), { 255, 255, 128, 255 });
} else {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal.Value"), { 255, 255, 255, 255 });
}
if (color.r != lastColorR || color.g != lastColorG || color.b != lastColorB) {
@ -404,11 +429,11 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
void DrawSceneCollision() {
ColRenderSetting showSceneColSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED);
if (showSceneColSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
if (showSceneColSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
}
std::vector<Gfx>& dl = (showSceneColSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
std::vector<Gfx>& dl = (showSceneColSetting == ColRenderTransparent) ? xluDl : opaDl;
InitGfx(dl, showSceneColSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
@ -418,11 +443,11 @@ void DrawSceneCollision() {
// Draws all Bg Actors
void DrawBgActorCollision() {
ColRenderSetting showBgActorSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED);
if (showBgActorSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
if (showBgActorSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
}
std::vector<Gfx>& dl = (showBgActorSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
std::vector<Gfx>& dl = (showBgActorSetting == ColRenderTransparent) ? xluDl : opaDl;
InitGfx(dl, showBgActorSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
@ -543,22 +568,22 @@ void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
// Draws all Col Check objects
void DrawColCheckCollision() {
ColRenderSetting showColCheckSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED);
if (showColCheckSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
if (showColCheckSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
}
std::vector<Gfx>& dl = (showColCheckSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
std::vector<Gfx>& dl = (showColCheckSetting == ColRenderTransparent) ? xluDl : opaDl;
InitGfx(dl, showColCheckSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
CollisionCheckContext& col = gPlayState->colChkCtx;
Color_RGBA8 color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 });
Color_RGBA8 color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC.Value"), { 255, 255, 255, 255 });
dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
DrawColCheckList(dl, col.colOC, col.colOCCount);
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC.Value"), { 0, 0, 255, 255 });
dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
DrawColCheckList(dl, col.colAC, col.colACCount);
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 0, 0, 255, 255 });
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT.Value"), { 0, 0, 255, 255 });
dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
DrawColCheckList(dl, col.colAT, col.colATCount);
@ -595,15 +620,15 @@ extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes
void DrawWaterboxList() {
ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED);
if (showWaterboxSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
if (showWaterboxSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
}
std::vector<Gfx>& dl = (showWaterboxSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
std::vector<Gfx>& dl = (showWaterboxSetting == ColRenderTransparent) ? xluDl : opaDl;
InitGfx(dl, showWaterboxSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
Color_RGBA8 color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 });
Color_RGBA8 color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox.Value"), { 0, 0, 255, 255 });
dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
#include "actorViewer.h"
#include "soh/util.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "ResourceManager.h"
#include "DisplayList.h"
#include "soh/OTRGlobals.h"
@ -91,10 +92,14 @@ void PerformDisplayListSearch() {
void DLViewerWindow::DrawElement() {
// Debounce the search field as listing otr files is expensive
UIWidgets::PushStyleInput(THEME_COLOR);
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
if (ImGui::InputText("Search Display Lists", searchString, ARRAY_COUNT(searchString))) {
doSearch = true;
searchDebounceFrames = 30;
}
UIWidgets::PopStyleInput();
if (doSearch) {
if (searchDebounceFrames == 0) {
@ -105,6 +110,7 @@ void DLViewerWindow::DrawElement() {
searchDebounceFrames--;
}
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Active Display List", activeDisplayList.c_str())) {
for (size_t i = 0; i < displayListSearchResults.size(); i++) {
if (ImGui::Selectable(displayListSearchResults[i].c_str())) {
@ -114,8 +120,10 @@ void DLViewerWindow::DrawElement() {
}
ImGui::EndCombo();
}
UIWidgets::PopStyleCombobox();
if (activeDisplayList == "") {
ImGui::PopFont();
return;
}
@ -144,6 +152,7 @@ void DLViewerWindow::DrawElement() {
ImGui::SameLine();
ImGui::PushItemWidth(175.0f);
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo(("CMD" + id).c_str(), cmdLabel.c_str())) {
if (ImGui::Selectable("gsDPSetPrimColor") && cmd != G_SETPRIMCOLOR) {
*gfx = gsDPSetPrimColor(0, 0, 0, 0, 0, 255);
@ -162,6 +171,7 @@ void DLViewerWindow::DrawElement() {
}
ImGui::EndCombo();
}
UIWidgets::PopStyleCombobox();
ImGui::PopItemWidth();
@ -194,9 +204,11 @@ void DLViewerWindow::DrawElement() {
if (cmd == G_SETGRAYSCALE) {
bool* state = (bool*)&gfx->words.w1;
ImGui::SameLine();
UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (ImGui::Checkbox(("state" + id).c_str(), state)) {
//
}
UIWidgets::PopStyleCheckbox();
}
if (cmd == G_SETTILE) {
ImGui::SameLine();
@ -317,8 +329,11 @@ void DLViewerWindow::DrawElement() {
}
} catch (const std::exception& e) {
ImGui::Text("Error displaying DL instructions.");
ImGui::PopFont();
return;
}
ImGui::PopFont();
}
void DLViewerWindow::InitElement() {

View file

@ -1,31 +1,33 @@
#include "hookDebugger.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/OTRGlobals.h"
#include <string>
#include <version>
static std::unordered_map<const char*, std::unordered_map<HOOK_ID, HookInfo>*> hookData;
static std::map<const char*, std::map<HOOK_ID, HookInfo>*> hookData;
const ImVec4 grey = ImVec4(0.75, 0.75, 0.75, 1);
const ImVec4 yellow = ImVec4(1, 1, 0, 1);
const ImVec4 red = ImVec4(1, 0, 0, 1);
void DrawHookRegisteringInfos(const char* hookName) {
if ((*hookData[hookName]).size() == 0) {
size_t numHooks = (*hookData[hookName]).size();
if (numHooks == 0) {
ImGui::TextColored(grey, "No hooks found");
return;
}
if (ImGui::BeginTable(
("Table##" + std::string(hookName)).c_str(),
4,
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit
)) {
ImGui::TableSetupColumn("Id");
ImGui::TableSetupColumn("Type");
ImGui::TableSetupColumn("Registration Info");
//ImGui::TableSetupColumn("Stub");
ImGui::TableSetupColumn("Number of Calls");
ImGui::Text("Total Registered: %d", numHooks);
if (ImGui::BeginTable(("Table##" + std::string(hookName)).c_str(), 4,
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable |
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Registration Info", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("# Calls", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableHeadersRow();
for (auto& [id, hookInfo] : (*hookData[hookName])) {
ImGui::TableNextRow();
@ -39,7 +41,7 @@ void DrawHookRegisteringInfos(const char* hookName) {
ImGui::Text("Normal");
break;
case HOOK_TYPE_ID:
ImGui::Text("Id");
ImGui::Text("ID");
break;
case HOOK_TYPE_PTR:
ImGui::Text("Ptr");
@ -54,27 +56,19 @@ void DrawHookRegisteringInfos(const char* hookName) {
ImGui::TableNextColumn();
if (hookInfo.registering.valid) {
ImGui::Text("%s(%d:%d) %s", hookInfo.registering.file, hookInfo.registering.line, hookInfo.registering.column, hookInfo.registering.function);
// Replace the space after the return type of the parent function with a non-breaking space
std::string parentFunction = std::string(hookInfo.registering.function);
size_t pos = parentFunction.find_first_of(" ");
if (pos != std::string::npos) {
parentFunction.replace(pos, 1, "\u00A0");
}
// Non breaking space to keep the arrow with the parent function
ImGui::TextWrapped("%s(%d:%d) <-\u00A0%s", hookInfo.registering.file, hookInfo.registering.line,
hookInfo.registering.column, parentFunction.c_str());
} else {
ImGui::TextColored(yellow, "[Unavaliable]");
ImGui::TextColored(yellow, "[Unavailable]");
}
//TODO: not currently possible
/*
ImGui::TableNextColumn();
ImGui::BeginDisabled();
bool stubButtonPressed = ImGui::Button(("Stub##" + std::to_string(id)).c_str());
UIWidgets::SetLastItemHoverText("Stub this hook.\nThis is not possible to automatically undo.");
if (stubButtonPressed) {
//stub
}
ImGui::EndDisabled();
*/
ImGui::TableNextColumn();
ImGui::Text("%d", hookInfo.calls);
}
@ -84,20 +78,21 @@ void DrawHookRegisteringInfos(const char* hookName) {
void HookDebuggerWindow::DrawElement() {
#ifndef __cpp_lib_source_location
ImGui::TextColored(
yellow,
"Some features of the Hook Debugger are unavaliable because SoH was compiled "
ImGui::TextColored(yellow, "Some features of the Hook Debugger are unavailable because SoH was compiled "
"without \"<source_location>\" support "
"(\"__cpp_lib_source_location\" not defined in \"<version>\")."
);
"(\"__cpp_lib_source_location\" not defined in \"<version>\").");
#endif
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
for (auto& [hookName, _] : hookData) {
if (ImGui::TreeNode(hookName)) {
DrawHookRegisteringInfos(hookName);
ImGui::TreePop();
}
}
ImGui::PopFont();
}
void HookDebuggerWindow::InitElement() {

View file

@ -0,0 +1,30 @@
#include "sohConsole.h"
#include "soh/OTRGlobals.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
void SohConsoleWindow::InitElement() {
ConsoleWindow::InitElement();
}
void SohConsoleWindow::UpdateElement() {
ConsoleWindow::UpdateElement();
}
void SohConsoleWindow::DrawElement() {
UIWidgets::PushStyleInput(THEME_COLOR);
// Small font (13) to match hardcoded width values in the LUS window.. set large font after below TODO addressed
ImGui::PushFont(OTRGlobals::Instance->fontMonoSmall);
// TODO: This can be removed after the LUS console window is designed better without hardcoding widths
ImGui::BeginChild("##Console Wrapper", ImVec2(0, 0), ImGuiChildFlags_None,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoScrollWithMouse);
ConsoleWindow::DrawElement();
ImGui::EndChild();
ImGui::PopFont();
UIWidgets::PopStyleInput();
}

View file

@ -0,0 +1,17 @@
#ifndef SOH_CONSOLE_H
#define SOH_CONSOLE_H
#include "window/gui/GuiWindow.h"
#include "window/gui/ConsoleWindow.h"
class SohConsoleWindow : public Ship::ConsoleWindow {
public:
using ConsoleWindow::ConsoleWindow;
protected:
void InitElement() override;
void UpdateElement() override;
void DrawElement() override;
};
#endif // SOH_CONSOLE_H

View file

@ -0,0 +1,16 @@
#include "sohGfxDebugger.h"
#include "soh/OTRGlobals.h"
void SohGfxDebuggerWindow::InitElement() {
GfxDebuggerWindow::InitElement();
}
void SohGfxDebuggerWindow::UpdateElement() {
GfxDebuggerWindow::UpdateElement();
}
void SohGfxDebuggerWindow::DrawElement() {
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
GfxDebuggerWindow::DrawElement();
ImGui::PopFont();
}

View file

@ -0,0 +1,17 @@
#ifndef SOH_GFX_DEBUGGER_H
#define SOH_GFX_DEBUGGER_H
#include "window/gui/GuiWindow.h"
#include "window/gui/GfxDebuggerWindow.h"
class SohGfxDebuggerWindow : public LUS::GfxDebuggerWindow {
public:
using GfxDebuggerWindow::GfxDebuggerWindow;
protected:
void InitElement() override;
void UpdateElement() override;
void DrawElement() override;
};
#endif // SOH_GFX_DEBUGGER_H

View file

@ -1,5 +1,6 @@
#include "valueViewer.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp"
@ -142,13 +143,14 @@ void RegisterValueViewerHooks() {
RegisterShipInitFunc initFunc(RegisterValueViewerHooks, { CVAR_NAME });
void ValueViewerWindow::DrawElement() {
UIWidgets::PaddedEnhancementCheckbox("Enable Printing", CVAR_NAME);
UIWidgets::CVarCheckbox("Enable Printing", CVAR_NAME, UIWidgets::CheckboxOptions().Color(THEME_COLOR));
ImGui::BeginGroup();
static int selectedElement = -1;
std::string selectedElementText = (selectedElement == -1) ? "Select a value" : (
std::string(valueTable[selectedElement].name) + " (" + std::string(valueTable[selectedElement].path) + ")"
);
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) {
for (int i = 0; i < valueTable.size(); i++) {
if (valueTable[i].isActive) continue;
@ -165,20 +167,28 @@ void ValueViewerWindow::DrawElement() {
}
ImGui::EndCombo();
}
UIWidgets::PopStyleCombobox();
ImGui::SameLine();
UIWidgets::PushStyleButton(THEME_COLOR);
if (selectedElement != -1 && ImGui::Button("+")) {
valueTable[selectedElement].isActive = true;
selectedElement = -1;
}
UIWidgets::PopStyleButton();
ImGui::EndGroup();
for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i];
if (!element.isActive || (gPlayState == NULL && element.requiresPlayState)) continue;
if (ImGui::Button(("x##" + std::string(element.name)).c_str())) {
UIWidgets::PushStyleButton(THEME_COLOR);
UIWidgets::PushStyleCheckbox(THEME_COLOR);
ImGui::AlignTextToFramePadding();
if (ImGui::Button((ICON_FA_TIMES + std::string("##") + std::string(element.name)).c_str())) {
element.isActive = false;
element.isPrinted = false;
}
UIWidgets::PopStyleCheckbox();
UIWidgets::PopStyleButton();
ImGui::SameLine();
ImGui::Text("%s:", element.name);
ImGui::SameLine();
@ -212,7 +222,7 @@ void ValueViewerWindow::DrawElement() {
break;
}
ImGui::SameLine();
UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (element.type <= TYPE_U32) {
ImGui::Checkbox(("Hex##" + std::string(element.name)).c_str(), &element.typeFormat);
ImGui::SameLine();
@ -220,23 +230,30 @@ void ValueViewerWindow::DrawElement() {
ImGui::Checkbox(("Trim##" + std::string(element.name)).c_str(), &element.typeFormat);
ImGui::SameLine();
}
UIWidgets::PopStyleCheckbox();
ImGui::BeginGroup();
if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ValueViewerEnablePrinting"), 0)) {
UIWidgets::PushStyleCheckbox(THEME_COLOR);
ImGui::Checkbox(("Print##" + std::string(element.name)).c_str(), &element.isPrinted);
UIWidgets::PopStyleCheckbox();
if (element.isPrinted) {
char* prefix = (char*)element.prefix.c_str();
ImGui::SameLine();
ImGui::SetNextItemWidth(80.0f);
UIWidgets::PushStyleInput(THEME_COLOR);
if (ImGui::InputText(("Prefix##" + std::string(element.name)).c_str(), prefix, 10)) {
element.prefix = prefix;
}
UIWidgets::PopStyleInput();
ImGui::SameLine();
ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine();
UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) {
ImGui::OpenPopup(("Position Picker##" + std::string(element.name)).c_str());
}
UIWidgets::PopStyleCheckbox();
if (ImGui::BeginPopup(("Position Picker##" + std::string(element.name)).c_str())) {
ImGui::DragInt("X", (int*)&element.x, 1.0f, 0, 44);
ImGui::DragInt("Y", (int*)&element.y, 1.0f, 0, 29);

View file

@ -186,7 +186,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
// Lengthen timer in non-MQ Jabu Jabu bubble room.
if (!isMQ && *actorId == ACTOR_OBJ_ROOMTIMER && *params == 30760 && play->sceneNum == SCENE_JABU_JABU &&
play->roomCtx.curRoom.num == 12) {
*params = 92280;
*params = (*params & ~0x3FF) | 120;
}
if (IsEnemyFoundToRandomize(play->sceneNum, play->roomCtx.curRoom.num, *actorId, *params, *posX)) {
@ -286,7 +286,7 @@ void GetSelectedEnemies() {
for (int i = 0; i < 49; i++) {
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemyList.All"), 0)) {
selectedEnemyList.push_back(randomizedEnemySpawnTable[i]);
} else if (CVarGetInteger(enemyCVarList[i], 0)) {
} else if (CVarGetInteger(enemyCVarList[i], 1)) {
selectedEnemyList.push_back(randomizedEnemySpawnTable[i]);
}
}

View file

@ -39,7 +39,7 @@ typedef enum {
MIRRORED_WORLD_ALWAYS,
MIRRORED_WORLD_RANDOM,
MIRRORED_WORLD_RANDOM_SEEDED,
MIRRORED_WORLD_DUNGEONS_All,
MIRRORED_WORLD_DUNGEONS_ALL,
MIRRORED_WORLD_DUNGEONS_VANILLA,
MIRRORED_WORLD_DUNGEONS_MQ,
MIRRORED_WORLD_DUNGEONS_RANDOM,
@ -75,6 +75,18 @@ typedef enum {
BONK_DAMAGE_OHKO,
} BonkDamage;
typedef enum {
DAMAGE_VANILLA,
DAMAGE_DOUBLE,
DAMAGE_QUADRUPLE,
DAMAGE_OCTUPLE,
DAMAGE_FOOLISH,
DAMAGE_RIDICULOUS,
DAMAGE_MERCILESS,
DAMAGE_TORTURE,
DAMAGE_OHKO
} DamageMultType;
typedef enum {
DEKU_STICK_NORMAL,
DEKU_STICK_UNBREAKABLE,
@ -87,4 +99,16 @@ typedef enum {
SWORD_TOGGLE_BOTH_AGES,
} SwordToggleMode;
typedef enum {
TIME_TRAVEL_DISABLED,
TIME_TRAVEL_OOT,
TIME_TRAVEL_ANY
} TimeTravelType;
typedef enum {
WATERFALL_ALWAYS,
WATERFALL_ONCE,
WATERFALL_NEVER
} SleepingWaterfallType;
#endif

View file

@ -4,8 +4,8 @@
#define GameInteractor_h
#include "libultraship/libultraship.h"
#include "GameInteractionEffect.h"
#include "vanilla-behavior/GIVanillaBehavior.h"
#include "GameInteractionEffect.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include <z64.h>
@ -92,19 +92,20 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state);
}
#endif
#ifdef __cplusplus
#include <stdarg.h>
#include <thread>
#include <map>
#include <unordered_map>
#include <vector>
#include <functional>
#include <string>
#include <version>
#ifdef __cpp_lib_source_location
#include <source_location>
#else
#pragma message("Compiling without <source_location> support, the Hook Debugger will not be avaliable")
#pragma message("Compiling without <source_location> support, the Hook Debugger will not be available")
#endif
typedef uint32_t HOOK_ID;
@ -124,24 +125,31 @@ struct HookRegisteringInfo {
const char* function;
HookType type;
HookRegisteringInfo() : valid(false), file("unknown file"), line(0), column(0), function("unknown function"), type(HOOK_TYPE_NORMAL) {}
HookRegisteringInfo()
: valid(false), file("unknown file"), line(0), column(0), function("unknown function"), type(HOOK_TYPE_NORMAL) {
}
HookRegisteringInfo(const char* _file, std::uint_least32_t _line, std::uint_least32_t _column, const char* _function, HookType _type) :
valid(true), file(_file), line(_line), column(_column), function(_function), type(_type) {}
HookRegisteringInfo(const char* _file, std::uint_least32_t _line, std::uint_least32_t _column,
const char* _function, HookType _type)
: valid(true), file(_file), line(_line), column(_column), function(_function), type(_type) {
// Trim off user parent directories
const char* trimmed = strstr(_file, "soh/soh/");
if (trimmed != nullptr) {
file = trimmed;
}
}
};
struct HookInfo {
uint32_t calls;
HookRegisteringInfo registering;
HookInfo() : calls(0), registering(HookRegisteringInfo{}) {}
HookInfo(HookRegisteringInfo _registering) : calls(0), registering(_registering) {}
};
#ifdef __cpp_lib_source_location
#define GET_CURRENT_REGISTERING_INFO(type) HookRegisteringInfo{location.file_name(), location.line(), location.column(), location.function_name(), type}
#define GET_CURRENT_REGISTERING_INFO(type) \
(HookRegisteringInfo{ location.file_name(), location.line(), location.column(), location.function_name(), type })
#else
#define GET_CURRENT_REGISTERING_INFO(type) HookRegisteringInfo{}
#define GET_CURRENT_REGISTERING_INFO(type) (HookRegisteringInfo{})
#endif
#define REGISTER_VB_SHOULD(flag, body) \
@ -219,6 +227,7 @@ public:
// Game Hooks
HOOK_ID nextHookId = 1;
template <typename H> struct RegisteredGameHooks {
inline static std::unordered_map<HOOK_ID, typename H::fn> functions;
inline static std::unordered_map<int32_t, std::unordered_map<HOOK_ID, typename H::fn>> functionsForID;
@ -226,7 +235,7 @@ public:
inline static std::unordered_map<HOOK_ID, std::pair<typename H::filter, typename H::fn>> functionsForFilter;
// Used for the hook debugger
inline static std::unordered_map<HOOK_ID, HookInfo> hookData;
inline static std::map<HOOK_ID, HookInfo> hookData;
};
template <typename H> struct HooksToUnregister {
@ -236,39 +245,43 @@ public:
inline static std::vector<HOOK_ID> hooksForFilter;
};
template <typename H> std::unordered_map<uint32_t, HookInfo>* GetHookData() {
template <typename H> std::map<uint32_t, HookInfo>* GetHookData() {
return &RegisteredGameHooks<H>::hookData;
}
// General Hooks
template <typename H> HOOK_ID RegisterGameHook(
typename H::fn h
template <typename H>
#ifdef __cpp_lib_source_location
, const std::source_location location = std::source_location::current()
HOOK_ID RegisterGameHook(typename H::fn h, const std::source_location location = std::source_location::current()) {
#else
HOOK_ID RegisterGameHook(typename H::fn h) {
#endif
) {
// Ensure hook id is unique and not 0, which is reserved for invalid hooks
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX)
this->nextHookId = 1;
while (RegisteredGameHooks<H>::functions.find(this->nextHookId) != RegisteredGameHooks<H>::functions.end()) {
this->nextHookId++;
}
RegisteredGameHooks<H>::functions[this->nextHookId] = h;
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_NORMAL)};
RegisteredGameHooks<H>::hookData[this->nextHookId] =
HookInfo{ 0, GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_NORMAL) };
return this->nextHookId++;
}
template <typename H> void UnregisterGameHook(HOOK_ID hookId) {
if (hookId == 0) return;
if (hookId == 0)
return;
HooksToUnregister<H>::hooks.push_back(hookId);
}
template <typename H, typename... Args> void ExecuteHooks(Args&&... args) {
// Remove pending hooks for this type
for (auto& hookId : HooksToUnregister<H>::hooks) {
RegisteredGameHooks<H>::functions.erase(hookId);
RegisteredGameHooks<H>::hookData.erase(hookId);
}
HooksToUnregister<H>::hooks.clear();
// Execute hooks
for (auto& hook : RegisteredGameHooks<H>::functions) {
hook.second(std::forward<Args>(args)...);
RegisteredGameHooks<H>::hookData[hook.first].calls += 1;
@ -276,39 +289,60 @@ public:
}
// ID based Hooks
template <typename H> HOOK_ID RegisterGameHookForID(
int32_t id, typename H::fn h
template <typename H>
#ifdef __cpp_lib_source_location
, const std::source_location location = std::source_location::current()
HOOK_ID RegisterGameHookForID(int32_t id, typename H::fn h,
std::source_location location = std::source_location::current()) {
#else
HOOK_ID RegisterGameHookForID(int32_t id, typename H::fn h) {
#endif
) {
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
while (RegisteredGameHooks<H>::functionsForID[id].find(this->nextHookId) != RegisteredGameHooks<H>::functionsForID[id].end()) {
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX)
this->nextHookId = 1;
while (RegisteredGameHooks<H>::functionsForID[id].find(this->nextHookId) !=
RegisteredGameHooks<H>::functionsForID[id].end()) {
this->nextHookId++;
}
RegisteredGameHooks<H>::functionsForID[id][this->nextHookId] = h;
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_ID)};
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{ 0, GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_ID) };
return this->nextHookId++;
}
template <typename H> void UnregisterGameHookForID(HOOK_ID hookId) {
if (hookId == 0) return;
if (hookId == 0)
return;
HooksToUnregister<H>::hooksForID.push_back(hookId);
}
template <typename H, typename... Args> void ExecuteHooksForID(int32_t id, Args&&... args) {
for (auto& hookId : HooksToUnregister<H>::hooksForID) {
for (auto it = RegisteredGameHooks<H>::functionsForID[id].begin(); it != RegisteredGameHooks<H>::functionsForID[id].end(); ) {
if (it->first == hookId) {
// Remove pending hooks for this type
for (auto hookIdIt = HooksToUnregister<H>::hooksForID.begin();
hookIdIt != HooksToUnregister<H>::hooksForID.end();) {
bool remove = false;
if (RegisteredGameHooks<H>::functionsForID[id].size() == 0) {
break;
}
for (auto it = RegisteredGameHooks<H>::functionsForID[id].begin();
it != RegisteredGameHooks<H>::functionsForID[id].end();) {
if (it->first == *hookIdIt) {
it = RegisteredGameHooks<H>::functionsForID[id].erase(it);
HooksToUnregister<H>::hooksForID.erase(std::remove(HooksToUnregister<H>::hooksForID.begin(), HooksToUnregister<H>::hooksForID.end(), hookId), HooksToUnregister<H>::hooksForID.end());
RegisteredGameHooks<H>::hookData.erase(hookId);
RegisteredGameHooks<H>::hookData.erase(*hookIdIt);
remove = true;
break;
} else {
++it;
}
}
if (remove) {
hookIdIt = HooksToUnregister<H>::hooksForID.erase(hookIdIt);
} else {
++hookIdIt;
}
}
// Execute hooks
for (auto& hook : RegisteredGameHooks<H>::functionsForID[id]) {
hook.second(std::forward<Args>(args)...);
RegisteredGameHooks<H>::hookData[hook.first].calls += 1;
@ -316,39 +350,60 @@ public:
}
// PTR based Hooks
template <typename H> HOOK_ID RegisterGameHookForPtr(
uintptr_t ptr, typename H::fn h
template <typename H>
#ifdef __cpp_lib_source_location
, const std::source_location location = std::source_location::current()
HOOK_ID RegisterGameHookForPtr(uintptr_t ptr, typename H::fn h,
const std::source_location location = std::source_location::current()) {
#else
HOOK_ID RegisterGameHookForPtr(uintptr_t ptr, typename H::fn h) {
#endif
) {
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
while (RegisteredGameHooks<H>::functionsForPtr[ptr].find(this->nextHookId) != RegisteredGameHooks<H>::functionsForPtr[ptr].end()) {
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX)
this->nextHookId = 1;
while (RegisteredGameHooks<H>::functionsForPtr[ptr].find(this->nextHookId) !=
RegisteredGameHooks<H>::functionsForPtr[ptr].end()) {
this->nextHookId++;
}
RegisteredGameHooks<H>::functionsForPtr[ptr][this->nextHookId] = h;
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_PTR)};
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{ 0, GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_PTR) };
return this->nextHookId++;
}
template <typename H> void UnregisterGameHookForPtr(HOOK_ID hookId) {
if (hookId == 0) return;
if (hookId == 0)
return;
HooksToUnregister<H>::hooksForPtr.push_back(hookId);
}
template <typename H, typename... Args> void ExecuteHooksForPtr(uintptr_t ptr, Args&&... args) {
for (auto& hookId : HooksToUnregister<H>::hooksForPtr) {
for (auto it = RegisteredGameHooks<H>::functionsForPtr[ptr].begin(); it != RegisteredGameHooks<H>::functionsForPtr[ptr].end(); ) {
if (it->first == hookId) {
// Remove pending hooks for this type
for (auto hookIdIt = HooksToUnregister<H>::hooksForPtr.begin();
hookIdIt != HooksToUnregister<H>::hooksForPtr.end();) {
bool remove = false;
if (RegisteredGameHooks<H>::functionsForPtr[ptr].size() == 0) {
break;
}
for (auto it = RegisteredGameHooks<H>::functionsForPtr[ptr].begin();
it != RegisteredGameHooks<H>::functionsForPtr[ptr].end();) {
if (it->first == *hookIdIt) {
it = RegisteredGameHooks<H>::functionsForPtr[ptr].erase(it);
HooksToUnregister<H>::hooksForPtr.erase(std::remove(HooksToUnregister<H>::hooksForPtr.begin(), HooksToUnregister<H>::hooksForPtr.end(), hookId), HooksToUnregister<H>::hooksForPtr.end());
RegisteredGameHooks<H>::hookData.erase(hookId);
RegisteredGameHooks<H>::hookData.erase(*hookIdIt);
remove = true;
break;
} else {
++it;
}
}
if (remove) {
hookIdIt = HooksToUnregister<H>::hooksForPtr.erase(hookIdIt);
} else {
++hookIdIt;
}
}
// Execute hooks
for (auto& hook : RegisteredGameHooks<H>::functionsForPtr[ptr]) {
hook.second(std::forward<Args>(args)...);
RegisteredGameHooks<H>::hookData[hook.first].calls += 1;
@ -356,33 +411,40 @@ public:
}
// Filter based Hooks
template <typename H> HOOK_ID RegisterGameHookForFilter(
typename H::filter f, typename H::fn h
template <typename H>
#ifdef __cpp_lib_source_location
, const std::source_location location = std::source_location::current()
HOOK_ID RegisterGameHookForFilter(typename H::filter f, typename H::fn h,
const std::source_location location = std::source_location::current()) {
#else
HOOK_ID RegisterGameHookForFilter(typename H::filter f, typename H::fn h) {
#endif
) {
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
while (RegisteredGameHooks<H>::functionsForFilter.find(this->nextHookId) != RegisteredGameHooks<H>::functionsForFilter.end()) {
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX)
this->nextHookId = 1;
while (RegisteredGameHooks<H>::functionsForFilter.find(this->nextHookId) !=
RegisteredGameHooks<H>::functionsForFilter.end()) {
this->nextHookId++;
}
RegisteredGameHooks<H>::functionsForFilter[this->nextHookId] = std::make_pair(f, h);
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_FILTER)};
RegisteredGameHooks<H>::hookData[this->nextHookId] =
HookInfo{ 0, GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_FILTER) };
return this->nextHookId++;
}
template <typename H> void UnregisterGameHookForFilter(HOOK_ID hookId) {
if (hookId == 0) return;
if (hookId == 0)
return;
HooksToUnregister<H>::hooksForFilter.push_back(hookId);
}
template <typename H, typename... Args> void ExecuteHooksForFilter(Args&&... args) {
// Remove pending hooks for this type
for (auto& hookId : HooksToUnregister<H>::hooksForFilter) {
RegisteredGameHooks<H>::functionsForFilter.erase(hookId);
RegisteredGameHooks<H>::hookData.erase(hookId);
}
HooksToUnregister<H>::hooksForFilter.clear();
// Execute hooks
for (auto& hook : RegisteredGameHooks<H>::functionsForFilter) {
if (hook.second.first(std::forward<Args>(args)...)) {
hook.second.second(std::forward<Args>(args)...);
@ -391,6 +453,60 @@ public:
}
}
template <typename H> void ProcessUnregisteredHooks() {
// Normal
for (auto& hookId : HooksToUnregister<H>::hooks) {
RegisteredGameHooks<H>::functions.erase(hookId);
RegisteredGameHooks<H>::hookData.erase(hookId);
}
HooksToUnregister<H>::hooks.clear();
// ID
for (auto& hookId : HooksToUnregister<H>::hooksForID) {
for (auto& idGroup : RegisteredGameHooks<H>::functionsForID) {
for (auto it = idGroup.second.begin(); it != idGroup.second.end();) {
if (it->first == hookId) {
it = idGroup.second.erase(it);
RegisteredGameHooks<H>::hookData.erase(hookId);
} else {
++it;
}
}
}
}
HooksToUnregister<H>::hooksForID.clear();
// Ptr
for (auto& hookId : HooksToUnregister<H>::hooksForPtr) {
for (auto& ptrGroup : RegisteredGameHooks<H>::functionsForPtr) {
for (auto it = ptrGroup.second.begin(); it != ptrGroup.second.end();) {
if (it->first == hookId) {
it = ptrGroup.second.erase(it);
RegisteredGameHooks<H>::hookData.erase(hookId);
} else {
++it;
}
}
}
}
HooksToUnregister<H>::hooksForPtr.clear();
// Filter
for (auto& hookId : HooksToUnregister<H>::hooksForFilter) {
RegisteredGameHooks<H>::functionsForFilter.erase(hookId);
RegisteredGameHooks<H>::hookData.erase(hookId);
}
HooksToUnregister<H>::hooksForFilter.clear();
}
void RemoveAllQueuedHooks() {
#define DEFINE_HOOK(name, _) ProcessUnregisteredHooks<name>();
#include "GameInteractor_HookTable.h"
#undef DEFINE_HOOK
}
class HookFilter {
public:
static auto ActorNotPlayer(Actor* actor) {
@ -401,15 +517,11 @@ public:
return actor->id != ACTOR_PLAYER;
}
static auto ActorMatchIdAndParams(int16_t id, int16_t params) {
return [id, params](Actor* actor) {
return actor->id == id && actor->params == params;
};
return [id, params](Actor* actor) { return actor->id == id && actor->params == params; };
}
// For use with Should hooks
static auto SActorMatchIdAndParams(int16_t id, int16_t params) {
return [id, params](Actor* actor, bool* result) {
return actor->id == id && actor->params == params;
};
return [id, params](Actor* actor, bool* result) { return actor->id == id && actor->params == params; };
}
};

View file

@ -19,6 +19,9 @@ void GameInteractor_ExecuteOnExitGame(int32_t fileNum) {
}
void GameInteractor_ExecuteOnGameStateMainStart() {
// Cleanup all hooks at the start of each frame
GameInteractor::Instance->RemoveAllQueuedHooks();
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnGameStateMainStart>();
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "vanilla-behavior/GIVanillaBehavior.h"
#include "GameInteractor.h"
#include <stdarg.h>

View file

@ -220,6 +220,9 @@ bool GameInteractor::RawAction::CheckFlag(int16_t flagType, int16_t flag) {
return Flags_GetRandomizerInf(static_cast<RandomizerInf>(flag));
case FlagType::FLAG_GS_TOKEN:
return GET_GS_FLAGS((flag & 0x1F00) >> 8);
default:
assert(false);
return false;
}
}
@ -564,7 +567,7 @@ void GameInteractor::RawAction::SetRandomWind(bool active) {
void GameInteractor::RawAction::SetPlayerInvincibility(bool active) {
Player* player = GET_PLAYER(gPlayState);
if (active) {
player->invincibilityTimer = 1000;
player->invincibilityTimer = -20;
} else {
player->invincibilityTimer = 0;
}

View file

@ -1,3 +1,8 @@
#pragma once
#ifndef GI_VANILLA_BEHAVIOR_H
#define GI_VANILLA_BEHAVIOR_H
typedef enum {
// #### `result`
// ```c
@ -400,6 +405,14 @@ typedef enum {
// - `*int16_t` (item id)
VB_DRAW_AMMO_COUNT,
// #### `result`
// ```c
// (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)
// ```
// #### `args`
// - None
VB_END_GERUDO_MEMBERSHIP_TALK,
// #### `result`
// ```c
// !(this->stateFlags3 & PLAYER_STATE3_PAUSE_ACTION_FUNC)
@ -1265,6 +1278,14 @@ typedef enum {
// - None
VB_PLAY_BOLERO_OF_FIRE_CS,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnDaiku`
VB_PLAY_CARPENTER_FREE_CS,
// #### `result`
// Close enough & various cutscene checks
// ```c
@ -1869,3 +1890,5 @@ typedef enum {
// - `*EnWonderTalk2`
VB_WONDER_TALK,
} GIVanillaBehavior;
#endif

View file

@ -1,11 +1,11 @@
#include "gameplaystats.h"
#include "gameplaystatswindow.h"
#include "soh/SaveManager.h"
#include "functions.h"
#include "macros.h"
#include "soh/cvar_prefixes.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "soh/util.h"
#include <vector>
@ -376,14 +376,18 @@ void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
});
}
void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE) {
void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE,
const char* tooltip = "") {
ImGui::PushStyleColor(ImGuiCol_Text, color);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s", label);
ImGui::SameLine(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize(value.c_str()).x - 8.0f));
ImGui::SameLine(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize(value.c_str()).x));
ImGui::Text("%s", value.c_str());
ImGui::PopStyleColor();
if (tooltip != "" && ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", tooltip);
}
}
bool compareTimestampInfoByTime(const TimestampInfo& a, const TimestampInfo& b) {
@ -527,8 +531,8 @@ void DrawGameplayStatsCountsTab() {
}
}
}
GameplayStatsRow("Rupees Collected:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_RUPEES_COLLECTED]));
UIWidgets::Tooltip("Includes rupees collected with a full wallet.");
GameplayStatsRow("Rupees Collected:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_RUPEES_COLLECTED]),
COLOR_WHITE, "Includes rupees collected with a full wallet.");
GameplayStatsRow("Rupees Spent:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_RUPEES_SPENT]));
GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED]));
GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed));
@ -606,26 +610,36 @@ void DrawGameplayStatsBreakdownTab() {
}
void DrawGameplayStatsOptionsTab() {
UIWidgets::PaddedEnhancementCheckbox("Show in-game total timer", CVAR_ENHANCEMENT("GameplayStats.ShowIngameTimer"), true, false);
UIWidgets::InsertHelpHoverText("Keep track of the timer as an in-game HUD element. The position of the timer can be changed in the Cosmetics Editor.");
UIWidgets::PaddedEnhancementCheckbox("Show latest timestamps on top", CVAR_ENHANCEMENT("GameplayStats.ReverseTimestamps"), true, false);
UIWidgets::PaddedEnhancementCheckbox("Room Breakdown", CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), true, false);
ImGui::SameLine();
UIWidgets::InsertHelpHoverText("Allows a more in-depth perspective of time spent in a certain map.");
UIWidgets::PaddedEnhancementCheckbox("RTA Timing on new files", CVAR_ENHANCEMENT("GameplayStats.RTATiming"), true, false);
ImGui::SameLine();
UIWidgets::InsertHelpHoverText(
"Timestamps are relative to starting timestamp rather than in game time, usually necessary for races/speedruns.\n\n"
UIWidgets::CVarCheckbox("Show in-game total timer", CVAR_ENHANCEMENT("GameplayStats.ShowIngameTimer"),
UIWidgets::CheckboxOptions()
.Tooltip("Keep track of the timer as an in-game HUD element. The position of the "
"timer can be changed in the Cosmetics Editor.")
.Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show latest timestamps on top", CVAR_ENHANCEMENT("GameplayStats.ReverseTimestamps"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Room Breakdown", CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"),
UIWidgets::CheckboxOptions()
.Tooltip("Allows a more in-depth perspective of time spent in a certain map.")
.Color(THEME_COLOR));
UIWidgets::CVarCheckbox("RTA Timing on new files", CVAR_ENHANCEMENT("GameplayStats.RTATiming"),
UIWidgets::CheckboxOptions()
.Tooltip("Timestamps are relative to starting timestamp rather than in game time, "
"usually necessary for races/speedruns.\n\n"
"Starting timestamp is on first non-c-up input after intro cutscene.\n\n"
"NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT"
);
UIWidgets::PaddedEnhancementCheckbox("Show additional detail timers", CVAR_ENHANCEMENT("GameplayStats.ShowAdditionalTimers"), true, false);
UIWidgets::PaddedEnhancementCheckbox("Show Debug Info", CVAR_ENHANCEMENT("GameplayStats.ShowDebugInfo"));
"NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT")
.Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show additional detail timers", CVAR_ENHANCEMENT("GameplayStats.ShowAdditionalTimers"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show Debug Info", CVAR_ENHANCEMENT("GameplayStats.ShowDebugInfo"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
}
void GameplayStatsWindow::DrawElement() {
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
DrawGameplayStatsHeader();
UIWidgets::PushStyleTabs(THEME_COLOR);
if (ImGui::BeginTabBar("Stats", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
if (ImGui::BeginTabItem("Timestamps")) {
DrawGameplayStatsTimestampsTab();
@ -646,6 +660,9 @@ void GameplayStatsWindow::DrawElement() {
ImGui::EndTabBar();
}
UIWidgets::PopStyleTabs();
ImGui::PopFont();
ImGui::Text("Note: Gameplay stats are saved to the current file and will be\nlost if you quit without saving.");
}
void InitStats(bool isDebug) {

View file

@ -1,5 +1,4 @@
#include <libultraship/libultraship.h>
#include "gameplaystats.h"
class GameplayStatsWindow : public Ship::GuiWindow {
public:

View file

@ -16,7 +16,6 @@
#include "soh/Enhancements/timesaver_hook_handlers.h"
#include "soh/Enhancements/TimeSavers/TimeSavers.h"
#include "soh/Enhancements/randomizer/hook_handlers.h"
#include "objects/object_gi_compass/object_gi_compass.h"
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
#include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h"
@ -463,7 +462,7 @@ void UpdateMirrorModeState(int32_t sceneNum) {
mirroredMode == MIRRORED_WORLD_ALWAYS ||
((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) ||
// Dungeon modes
(inDungeon && (mirroredMode == MIRRORED_WORLD_DUNGEONS_All ||
(inDungeon && (mirroredMode == MIRRORED_WORLD_DUNGEONS_ALL ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) && randomMirror)))
@ -810,8 +809,10 @@ void RegisterRandomizedEnemySizes() {
Actor* actor = static_cast<Actor*>(refActor);
// Exclude wobbly platforms in Jabu because they need to act like platforms.
// Exclude demo effect for Zora sapphire being re-categorized as a "boss".
// Exclude Dead Hand hands and Bongo Bongo main body because they make the fights (near) impossible.
uint8_t excludedEnemy = actor->id == ACTOR_EN_BROB || actor->id == ACTOR_EN_DHA || (actor->id == ACTOR_BOSS_SST && actor->params == -1);
uint8_t excludedEnemy = actor->id == ACTOR_EN_BROB || actor->id == ACTOR_EN_DHA ||
actor->id == ACTOR_DEMO_EFFECT || (actor->id == ACTOR_BOSS_SST && actor->params == -1);
// Dodongo, Volvagia and Dead Hand are always smaller because they're impossible when bigger.
uint8_t smallOnlyEnemy = actor->id == ACTOR_BOSS_DODONGO || actor->id == ACTOR_BOSS_FD ||
@ -998,26 +999,6 @@ void RegisterPauseMenuHooks() {
});
}
extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
void PatchCompasses() {
s8 compassesCanBeOutsideDungeon = IS_RANDO && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS);
s8 isColoredCompassesEnabled = compassesCanBeOutsideDungeon && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MatchCompassColors"), 1);
if (isColoredCompassesEnabled) {
ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_PrimColor", 5, gsDPNoOp());
ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_EnvColor", 6, gsDPNoOp());
} else {
ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_PrimColor");
ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_EnvColor");
}
}
void RegisterRandomizerCompasses() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadFile>([](int32_t _unused) {
PatchCompasses();
});
}
void RegisterCustomSkeletons() {
static int8_t previousTunic = -1;
@ -1065,7 +1046,6 @@ void InitMods() {
RegisterRandomizedEnemySizes();
RegisterOpenAllHours();
RegisterToTMedallions();
RegisterRandomizerCompasses();
NameTag_RegisterHooks();
RegisterFloorSwitchesHook();
RegisterPatchHandHandler();

View file

@ -11,7 +11,6 @@ void UpdateDirtPathFixState(int32_t sceneNum);
void UpdateMirrorModeState(int32_t sceneNum);
void UpdateHurtContainerModeState(bool newState);
void PatchToTMedallions();
void PatchCompasses();
void UpdatePermanentHeartLossState();
void UpdateHyperEnemiesState();
void UpdateHyperBossesState();

View file

@ -3,8 +3,10 @@
#include <string>
#include <cstdint>
#include <libultraship/bridge.h>
#include "soh/SohGui/UIWidgets.hpp"
#include <libultraship/libultraship.h>
#include "soh/SohGui/MenuTypes.h"
#include "soh/SohGui/SohMenu.h"
#include "soh/SohGui/SohGui.hpp"
std::string FormatLocations(std::vector<RandomizerCheck> locs) {
std::string locString = "";
@ -30,6 +32,7 @@ void applyPreset(std::vector<PresetEntry> entries) {
CVarSetString(cvar, std::get<std::string>(value).c_str());
break;
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
}
@ -47,21 +50,22 @@ void DrawPresetSelector(PresetType presetTypeId) {
comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description);
}
UIWidgets::PaddedText("Presets", false, true);
ImGui::Text("Presets");
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) {
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) {
if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) {
CVarSetInteger(presetTypeCvar.c_str(), iter->first);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
}
ImGui::EndCombo();
}
UIWidgets::PopStyleCombobox();
UIWidgets::Tooltip(comboboxTooltip.c_str());
UIWidgets::Spacer(0);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f));
UIWidgets::PushStyleButton(THEME_COLOR);
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
for(const char* block : presetTypeDef.blocksToClear) {
CVarClearBlock(block);
@ -75,5 +79,5 @@ void DrawPresetSelector(PresetType presetTypeId) {
Rando::Settings::GetInstance()->ReloadOptions();
}
}
ImGui::PopStyleVar(1);
UIWidgets::PopStyleButton();
}

View file

@ -242,7 +242,7 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
// Disable Navi Call Audio
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1),
PRESET_ENTRY_S32(CVAR_AUDIO("DisableNaviCallAudio"), 1),
// Equipment Toggle
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1),
@ -373,7 +373,7 @@ const std::vector<PresetEntry> randomizerPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
// Disable Navi Call Audio
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1),
PRESET_ENTRY_S32(CVAR_AUDIO("DisableNaviCallAudio"), 1),
// Equipment Toggle
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1),
@ -436,7 +436,7 @@ const std::vector<PresetEntry> spockRacePresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoForcedNavi"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1),
PRESET_ENTRY_S32(CVAR_AUDIO("DisableNaviCallAudio"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastDrops"), 1),
PRESET_ENTRY_S32(CVAR_SETTING("DpadInText"), 1),
@ -531,7 +531,7 @@ const std::vector<PresetEntry> spockRaceNoLogicPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeAllNight"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DayGravePull"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1),
PRESET_ENTRY_S32(CVAR_AUDIO("DisableNaviCallAudio"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),

View file

@ -2,258 +2,9 @@
#include "../../custom-message/CustomMessageManager.h"
#include "z64item.h"
#include <array>
#include <set>
#include <sstream>
namespace CustomMessages {
using namespace std::literals::string_literals;
class MessageEntryComp {
public:
bool operator()(const MessageEntry& lhs, const MessageEntry& rhs) const {
return lhs.id < rhs.id;
}
};
constexpr std::array EnglishDungeonNames = {
"Deku Tree",
"Dodongo's Cavern",
"Jabu Jabu's Belly",
"Forest Temple",
"Fire Temple",
"Water Temple",
"Spirit Temple",
"Shadow Temple",
"Bottom of the Well",
"Ice Cavern",
"Ganon's Tower",
"Gerudo Training Ground",
"Gerudo Fortress",
"Ganon's Castle",
};
constexpr std::array FrenchDungeonNames = {
"Vénérable Arbre Mojo",
"Caverne Dodongo",
"Ventre de Jabu-Jabu",
"Temple de la Forêt",
"Temple du Feu",
"Temple de l'Eau",
"Temple de l'Esprit",
"Temple de l'Ombre",
"Puits",
"Caverne Polaire",
"Tour de Ganon",
"Gymnase Gerudo",
"Repaire des Voleurs",
"Château de Ganon",
};
constexpr std::array FrenchDungeonArticles = {
"du ",
"de la ",
"du ",
"du ",
"du ",
"du ",
"du ",
"du ",
"du ",
"de la ",
"",
"du ",
"de la ",
"du ",
};
constexpr std::array SpanishDungeonNames = {
"Gran Árbol Deku",
"Cueva de los Dodongos",
"Tripa de Jabu-Jabu",
"Templo del Bosque",
"Templo del Fuego",
"Templo del Agua",
"Templo del Espíritu",
"Templo de las Sombras",
"Fondo del pozo",
"Caverna de hielo",
"Torre de Ganon",
"Centro de Instrucción Gerudo",
"Fortaleza Gerudo",
"Castillo de Ganon",
};
constexpr std::array SpanishDungeonArticles = {
"del",
"de la",
"de la",
"del",
"del",
"del",
"del",
"del",
"del",
"de la",
"de la",
"del",
"de la",
"del",
};
constexpr std::array DungeonColors = {
QM_GREEN,
QM_RED,
QM_BLUE,
QM_GREEN,
QM_RED,
QM_BLUE,
QM_YELLOW,
QM_PINK,
QM_PINK,
QM_LBLUE,
QM_BLACK,
QM_YELLOW,
QM_YELLOW,
QM_RED,
};
std::set<MessageEntry, MessageEntryComp> messageEntries;
std::stringstream messageData;
//textBoxType and textBoxPosition are defined here: https://wiki.cloudmodding.com/oot/Text_Format#Message_Id
void CreateMessage(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition,
std::string englishText, std::string frenchText, std::string spanishText) {
MessageEntry newEntry = { textId, unk_04, textBoxType, textBoxPosition, { 0 } };
while ((englishText.size() % 4) != 0) {
englishText += "\0"s;
}
messageData.seekg(0, messageData.end);
newEntry.info[ENGLISH_U].offset = (char*)((int)messageData.tellg());
newEntry.info[ENGLISH_U].length = englishText.size();
messageData << englishText;
while ((frenchText.size() % 4) != 0) {
frenchText += "\0"s;
}
messageData.seekg(0, messageData.end);
newEntry.info[FRENCH_U].offset = (char*)((int)messageData.tellg());
newEntry.info[FRENCH_U].length = frenchText.size();
messageData << frenchText;
while ((spanishText.size() % 4) != 0) {
spanishText += "\0"s;
}
messageData.seekg(0, messageData.end);
newEntry.info[SPANISH_U].offset = (char*)((int)messageData.tellg());
newEntry.info[SPANISH_U].length = spanishText.size();
messageData << spanishText;
messageEntries.insert(newEntry);
}
void CreateMessageFromTextObject(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition, const Text& text) {
CreateMessage(textId, unk_04, textBoxType, textBoxPosition, text.GetEnglish(), text.GetFrench(), text.GetSpanish());
}
Text AddColorsAndFormat(Text text, const std::vector<std::string>& colors /*= {}*/) {
//for each language
for (std::string* textStr : {&text.english, &text.french, &text.spanish}) {
//insert playername
size_t atSymbol = textStr->find('@');
while (atSymbol != std::string::npos) {
textStr->replace(atSymbol, 1, PLAYER_NAME());
atSymbol = textStr->find('@');
}
//insert newlines either manually or when encountering a '&'
constexpr size_t lineLength = 44;
size_t lastNewline = 0;
while (lastNewline + lineLength < textStr->length()) {
size_t carrot = textStr->find('^', lastNewline);
size_t ampersand = textStr->find('&', lastNewline);
size_t lastSpace = textStr->rfind(' ', lastNewline + lineLength);
size_t lastPeriod = textStr->rfind('.', lastNewline + lineLength);
//replace '&' first if it's within the newline range
if (ampersand < lastNewline + lineLength) {
textStr->replace(ampersand, 1, NEWLINE());
lastNewline = ampersand + NEWLINE().length();
//or move the lastNewline cursor to the next line if a '^' is encountered
} else if (carrot < lastNewline + lineLength) {
lastNewline = carrot + 1;
//some lines need to be split but don't have spaces, look for periods instead
} else if (lastSpace == std::string::npos) {
textStr->replace(lastPeriod, 1, "."+NEWLINE());
lastNewline = lastPeriod + NEWLINE().length() + 1;
} else {
textStr->replace(lastSpace, 1, NEWLINE());
lastNewline = lastSpace + NEWLINE().length();
}
}
//clean up any remaining '&' characters
size_t ampersand = textStr->find('&');
while (ampersand != std::string::npos) {
textStr->replace(ampersand, 1, NEWLINE());
ampersand = textStr->find('&');
}
//insert box break
size_t carrotSymbol = textStr->find('^');
while (carrotSymbol != std::string::npos) {
textStr->replace(carrotSymbol, 1, INSTANT_TEXT_OFF()+WAIT_FOR_INPUT()+INSTANT_TEXT_ON());
carrotSymbol = textStr->find('^');
}
//If there's a two-way choice and only 1 newline before it in the same text box, add another one
size_t choice = textStr->find(TWO_WAY_CHOICE());
if (choice != std::string::npos) {
size_t newLinesCount = 0;
size_t lastBoxBreak = textStr->rfind(WAIT_FOR_INPUT(), choice);
lastNewline = choice;
if (lastBoxBreak == std::string::npos) {
lastBoxBreak = 0;
}
while ((lastNewline != std::string::npos)) {
lastNewline = textStr->rfind(NEWLINE(), lastNewline - 1);
if (lastNewline != std::string::npos && lastNewline > lastBoxBreak) {
newLinesCount++;
} else {
break;
}
}
if (newLinesCount <= 1) {
textStr->replace(choice, TWO_WAY_CHOICE().length(), NEWLINE()+TWO_WAY_CHOICE());
}
}
//add colors
for (auto color : colors) {
size_t firstHashtag = textStr->find('#');
if (firstHashtag != std::string::npos) {
textStr->replace(firstHashtag, 1, COLOR(color));
size_t secondHashtag = textStr->find('#');
if (secondHashtag == std::string::npos) {
//CitraPrint("ERROR: Couldn't find second '#' in " + (*textStr));
} else {
textStr->replace(secondHashtag, 1, COLOR(QM_WHITE));
}
}
}
}
return Text{"","",""}+UNSKIPPABLE()+INSTANT_TEXT_ON()+text+INSTANT_TEXT_OFF()+MESSAGE_END();
}
void ClearMessages() {
messageEntries.clear();
messageData.str("");
}
std::string MESSAGE_END() { return "\x7F\x00"s; }
std::string WAIT_FOR_INPUT() { return "\x7F\x01"s; }
std::string HORIZONTAL_SPACE(uint8_t x) {
@ -280,7 +31,7 @@ constexpr std::array DungeonColors = {
std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x);
}
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; } //RANDOTODO just refernce the versions in CustomMessage
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; }
std::string CURRENT_TIME() { return "\x7F\x17"s; }
std::string UNSKIPPABLE() { return "\x7F\x19"s; }
std::string TWO_WAY_CHOICE() { return "\x1B"s; }

View file

@ -1,50 +1,11 @@
#pragma once
#include <string>
#include <utility>
#include <vector>
#include <cstdint>
#include "text.hpp"
namespace CustomMessages {
typedef struct {
// In the true file format, offset is the offset into the QM file.
// In randomizer, offset will be a pointer to the text in the game's address space.
// Since these pointers will be much larger as u32 than the original script's offsets,
// We will be able to distinguish between original and custom text using their numerical value.
const char* offset;
uint32_t length;
} MessageLanguageInfo;
typedef enum {
/* 0x00 */ JAPANESE_J,
/* 0x01 */ ENGLISH_U,
/* 0x02 */ ENGLISH_E,
/* 0x03 */ GERMAN_E,
/* 0x04 */ FRENCH_E,
/* 0x05 */ FRENCH_U,
/* 0x06 */ SPANISH_E,
/* 0x07 */ SPANISH_U,
/* 0x08 */ ITALIAN_E,
/* 0x09 */ DUTCH_E,
} MessageLanguage;
typedef struct {
uint32_t id;
uint32_t unk_04;
uint32_t unk_08;
uint32_t unk_0C;
MessageLanguageInfo info[10];
} MessageEntry; // size = 0x60
void CreateMessage(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition,
std::string englishText, std::string frenchText, std::string spanishText);
void CreateMessageFromTextObject(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition, const Text& text);
Text AddColorsAndFormat(Text text, const std::vector<uint8_t>& colors = {});
void ClearMessages();
std::string MESSAGE_END();
std::string WAIT_FOR_INPUT();
std::string HORIZONTAL_SPACE(uint8_t x);

View file

@ -1,6 +1,5 @@
#include "fill.hpp"
#include "custom_messages.hpp"
#include "../dungeon.h"
#include "../context.h"
#include "item_pool.hpp"
@ -19,7 +18,6 @@
#include <set>
#include <spdlog/spdlog.h>
using namespace CustomMessages;
using namespace Rando;

View file

@ -2070,23 +2070,23 @@ void StaticData::HintTable_Init_Item() {
CustomMessage("a rightward tone", /*german*/"ein rechtsseitiger Ton", /*french*/"une tonalité vers la droite")});
// /*spanish*/un tono hacia la derecha
hintTextTable[RHT_FISHING_POLE] = HintText(CustomMessage("a fishing pole", /*german*/"eine Angelrute", /*french*/"canne à pêche"),
hintTextTable[RHT_FISHING_POLE] = HintText(CustomMessage("a fishing pole", /*german*/"eine Angelrute", /*french*/"une canne à pêche"),
// /*spanish*/caña de pescar
{
CustomMessage("the pond owner's property", /*german*/"der Besitz des Teicheigners", /*french*/"(canne à pêche)")
CustomMessage("the pond owner's property", /*german*/"der Besitz des Teicheigners", /*french*/"(un truc qui appartient au propriétaire de l'étang)")
// /*spanish*/(caña de pescar)
}, {
CustomMessage("a fish-puller", /*german*/"ein Fischzieher", /*french*/"(canne à pêche)")});
CustomMessage("a fish-puller", /*german*/"ein Fischzieher", /*french*/"(un aimant à poisson)")});
// /*spanish*/(caña de pescar)
hintTextTable[RHT_BOMBCHU_BAG] = HintText(CustomMessage("Bombchu Bag", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_BOMBCHU_BAG] = HintText(CustomMessage("Bombchu Bag", /*german*/"!!!", /*french*/"un Sac de Missiles Teigneux"),
{
CustomMessage("explosives", /*german*/"ein Explosivpaket", /*french*/"un paquet d'explosifs"),
// /*spanish*/un montón de explosivos
CustomMessage("something that can remove boulders", /*german*/"etwas, das Geröll entfernen kann", /*french*/"une chose qui enlève les rochers")
// /*spanish*/algo que pueda quitar rocas
}, {
CustomMessage("sack of mice", /*german*/"!!!", /*french*/"!!!")});
CustomMessage("sack of mice", /*german*/"!!!", /*french*/"un Sac rempli de souris")});
hintTextTable[RHT_SKELETON_KEY] = HintText(CustomMessage("a Skeleton Key", /*german*/ "ein Universalschlüssel", /*french*/ "une Clé Squelette"),
// /*spanish*/una Llave Maestra
@ -2096,49 +2096,49 @@ void StaticData::HintTable_Init_Item() {
},
{ CustomMessage("a master unlocker", /*german*/ "ein Meisterentsperrer", /*french*/ "un Kit de Déverrouillage") });
// /*spanish*/un desbloqueador maestro
hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"!!!", /*french*/"un Carquois Infini"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {
CustomMessage("", /*german*/"!!!", /*french*/"!!!")});
hintTextTable[RHT_BOMB_BAG_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_BOMB_BAG_INF] = HintText(CustomMessage("an infinite Bomb Bag", /*german*/"!!!", /*french*/"un Sac de Bombe sans fond"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {
CustomMessage("", /*german*/"!!!", /*french*/"!!!")});
hintTextTable[RHT_BULLET_BAG_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_BULLET_BAG_INF] = HintText(CustomMessage("an infinite Bullet Bag", /*german*/"!!!", /*french*/"un Sac de Graine sans fond"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {
CustomMessage("", /*german*/"!!!", /*french*/"!!!")});
hintTextTable[RHT_STICK_UPGRADE_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_STICK_UPGRADE_INF] = HintText(CustomMessage("infinite Deku Sticks", /*german*/"!!!", /*french*/" des Bâtons Mojo illimités"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {
CustomMessage("", /*german*/"!!!", /*french*/"!!!")});
hintTextTable[RHT_NUT_UPGRADE_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_NUT_UPGRADE_INF] = HintText(CustomMessage("infinite Deku Nut", /*german*/"!!!", /*french*/"des Noix Mojo illimitées"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {
CustomMessage("", /*german*/"!!!", /*french*/"!!!")});
hintTextTable[RHT_MAGIC_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_MAGIC_INF] = HintText(CustomMessage("unlimited Magic", /*german*/"!!!", /*french*/"de la Magie infinie"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {
CustomMessage("", /*german*/"!!!", /*french*/"!!!")});
hintTextTable[RHT_BOMBCHU_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_BOMBCHU_INF] = HintText(CustomMessage("infinite Bombchus", /*german*/"!!!", /*french*/"des Missiles Teigneux illimités"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {
CustomMessage("", /*german*/"!!!", /*french*/"!!!")});
hintTextTable[RHT_WALLET_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
hintTextTable[RHT_WALLET_INF] = HintText(CustomMessage("an infinite Wallet", /*german*/"!!!", /*french*/"une Bourse sans fond"),
{
CustomMessage("", /*german*/"!!!", /*french*/"!!!"),
}, {

View file

@ -1297,7 +1297,7 @@ void GenerateItemPool() {
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Get() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Get() >= RO_GANON_BOSS_KEY_LACS_VANILLA) {
ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) {
ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY);

View file

@ -2,7 +2,6 @@
#include <libultraship/libultraship.h>
#include <boost_custom/container_hash/hash_32.hpp>
#include "custom_messages.hpp"
#include "fill.hpp"
#include "../location_access.h"
#include "random.hpp"
@ -23,7 +22,6 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
auto ctx = Rando::Context::GetInstance();
ctx->overrides.clear();
CustomMessages::ClearMessages();
ctx->ItemReset();
ctx->HintReset();
ctx->GetLogic()->Reset();

View file

@ -275,6 +275,9 @@ int GetShopsanityReplaceAmount() {
return 7;
} else if (ctx->GetOption(RSK_SHOPSANITY_COUNT).Is(RO_SHOPSANITY_COUNT_EIGHT_ITEMS)) {
return 8; //temporarily unreachable due to logic limitations
} else {
assert(false);
return 0;
}
} else { //Random, get number in [1, 7]
return Random(1, 8);

View file

@ -57,7 +57,7 @@ void GenerateStartingInventory() {
// Add Ganon's Boss key with Triforce Hunt so the game thinks it's obtainable from the start.
// During save init, the boss key isn't actually given and it's instead given when completing the triforce.
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH) ||
ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
ctx->GetOption(RSK_TRIFORCE_HUNT)) {
AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY);
}

View file

@ -0,0 +1,43 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/ShipInit.hpp"
#include "z64save.h"
#include "objects/object_gi_compass/object_gi_compass.h"
#include "objects/object_gi_map/object_gi_map.h"
extern "C" {
extern SaveContext gSaveContext;
#include "variables.h"
#include "macros.h"
u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
}
#define CVAR_COLORED_MAPS_AND_COMPASSES_NAME CVAR_RANDOMIZER_ENHANCEMENT("ColoredMapsAndCompasses")
#define CVAR_COLORED_MAPS_AND_COMPASSES_DEFAULT 1
#define CVAR_COLORED_MAPS_AND_COMPASSES_VALUE CVarGetInteger(CVAR_COLORED_MAPS_AND_COMPASSES_NAME, CVAR_COLORED_MAPS_AND_COMPASSES_DEFAULT)
void OnLoadFileColoredMapsAndCompasses(int32_t _) {
s8 mapsAndCompassesCanBeOutsideDungeon = IS_RANDO && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS);
s8 isColoredMapsAndCompassesEnabled = mapsAndCompassesCanBeOutsideDungeon && CVAR_COLORED_MAPS_AND_COMPASSES_VALUE;
if (isColoredMapsAndCompassesEnabled) {
ResourceMgr_PatchGfxByName(gGiDungeonMapDL, "Map_PrimColor", 5, gsDPNoOp());
ResourceMgr_PatchGfxByName(gGiDungeonMapDL, "Map_EnvColor", 6, gsDPNoOp());
ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_PrimColor", 5, gsDPNoOp());
ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_EnvColor", 6, gsDPNoOp());
} else {
ResourceMgr_UnpatchGfxByName(gGiDungeonMapDL, "Map_PrimColor");
ResourceMgr_UnpatchGfxByName(gGiDungeonMapDL, "Map_EnvColor");
ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_PrimColor");
ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_EnvColor");
}
}
void RegisterColoredMapsAndCompasses() {
COND_HOOK(OnLoadFile, CVAR_COLORED_MAPS_AND_COMPASSES_VALUE, OnLoadFileColoredMapsAndCompasses)
//Also need to call it directly to patch/unpatch on cvar change
OnLoadFileColoredMapsAndCompasses(0);
}
static RegisterShipInitFunc initFunc(RegisterColoredMapsAndCompasses, { CVAR_COLORED_MAPS_AND_COMPASSES_NAME });

View file

@ -1,4 +1,5 @@
#include "Plandomizer.h"
#include <soh/SohGui/SohGui.hpp>
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/util.h"
#include <vector>
@ -836,21 +837,9 @@ void PlandomizerDrawItemSlots(uint32_t index) {
void PlandomizerDrawShopSlider(uint32_t index) {
ImGui::PushID(index);
ImGui::Text("Price:");
ImGui::SameLine();
std::string MinusBTNName = " - ##Price";
if (ImGui::Button(MinusBTNName.c_str()) && plandoLogData[index].shopPrice > 0) {
plandoLogData[index].shopPrice--;
}
ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 40.0f);
ImGui::SliderInt("", &plandoLogData[index].shopPrice, 0, 999, "%d Rupees");
ImGui::PopItemWidth();
ImGui::SameLine();
std::string PlusBTNName = " + ##Price";
if (ImGui::Button(PlusBTNName.c_str()) && plandoLogData[index].shopPrice < 999) {
plandoLogData[index].shopPrice++;
}
UIWidgets::SliderInt("Price:", &plandoLogData[index].shopPrice, UIWidgets::IntSliderOptions()
.Color(THEME_COLOR).Format("%d Rupees").Min(0).Max(999).LabelPosition(UIWidgets::LabelPositions::Near)
.ComponentAlignment(UIWidgets::ComponentAlignments::Right).Size(UIWidgets::Sizes::Inline));
ImGui::PopID();
}
@ -883,13 +872,13 @@ void PlandomizerDrawIceTrapSetup(uint32_t index) {
ImGui::SameLine();
if (plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_NONE &&
plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_SOLD_OUT) {
if (ImGui::Button(randomizeButton.c_str())) {
if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline).Padding(ImVec2(10.f, 6.f)))) {
plandoLogData[index].iceTrapName =
GetIceTrapName(plandoLogData[index].iceTrapModel.GetRandomizerGet()).GetForLanguage(CVarGetInteger(CVAR_SETTING("Languages"), 0)).c_str();
}
ImGui::SameLine();
}
if (UIWidgets::InputString("##TrapName", &trapTextInput)) {
if (UIWidgets::InputString("##TrapName", &trapTextInput, UIWidgets::InputOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None))) {
plandoLogData[index].iceTrapName = trapTextInput.c_str();
}
@ -900,39 +889,64 @@ void PlandomizerDrawIceTrapSetup(uint32_t index) {
ImGui::PopID();
}
static std::unordered_map<RandomizerCheckArea, const char*> rcAreaNameMap = {
{ RCAREA_KOKIRI_FOREST, "Kokiri Forest" },
{ RCAREA_LOST_WOODS, "Lost Woods" },
{ RCAREA_SACRED_FOREST_MEADOW, "Sacred Forest Meadow" },
{ RCAREA_HYRULE_FIELD, "Hyrule Field" },
{ RCAREA_LAKE_HYLIA, "Lake Hylia" },
{ RCAREA_GERUDO_VALLEY, "Gerudo Valley" },
{ RCAREA_GERUDO_FORTRESS, "Gerudo Fortress" },
{ RCAREA_WASTELAND, "Haunted Wasteland" },
{ RCAREA_DESERT_COLOSSUS, "Desert Colossus" },
{ RCAREA_MARKET, "Hyrule Market" },
{ RCAREA_HYRULE_CASTLE, "Hyrule Castle" },
{ RCAREA_KAKARIKO_VILLAGE, "Kakariko Village" },
{ RCAREA_GRAVEYARD, "Graveyard" },
{ RCAREA_DEATH_MOUNTAIN_TRAIL, "Death Mountain Trail" },
{ RCAREA_GORON_CITY, "Goron City" },
{ RCAREA_DEATH_MOUNTAIN_CRATER, "Death Mountain Crater" },
{ RCAREA_ZORAS_RIVER, "Zora's River" },
{ RCAREA_ZORAS_DOMAIN, "Zora's Domain" },
{ RCAREA_ZORAS_FOUNTAIN, "Zora's Fountain" },
{ RCAREA_LON_LON_RANCH, "Lon Lon Ranch" },
{ RCAREA_DEKU_TREE, "Deku Tree" },
{ RCAREA_DODONGOS_CAVERN, "Dodongo's Cavern" },
{ RCAREA_JABU_JABUS_BELLY, "Jabu Jabu's Belly" },
{ RCAREA_FOREST_TEMPLE, "Forest Temple" },
{ RCAREA_FIRE_TEMPLE, "Fire Temple" },
{ RCAREA_WATER_TEMPLE, "Water Temple" },
{ RCAREA_SPIRIT_TEMPLE, "Spirit Temple" },
{ RCAREA_SHADOW_TEMPLE, "Shadow Temple" },
{ RCAREA_BOTTOM_OF_THE_WELL, "Bottom of the Well" },
{ RCAREA_ICE_CAVERN, "Ice Cavern" },
{ RCAREA_GERUDO_TRAINING_GROUND, "Gerudo Training Ground" },
{ RCAREA_GANONS_CASTLE, "Ganon's Castle" },
{ RCAREA_INVALID, "All" },
};
void PlandomizerDrawOptions() {
if (ImGui::BeginTable("LoadSpoiler", 2)) {
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextColumn();
ImGui::SeparatorText("Load/Save Spoiler Log");
PlandomizerPopulateSeedList();
static size_t selectedList = 0;
if (existingSeedList.size() != 0) {
if (ImGui::BeginCombo("##JsonFiles", existingSeedList[selectedList].c_str())) {
for (size_t i = 0; i < existingSeedList.size(); i++) {
bool isSelected = (selectedList == i);
if (ImGui::Selectable(existingSeedList[i].c_str(), isSelected)) {
selectedList = i;
}
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
UIWidgets::Combobox("##JsonFiles", &selectedList, existingSeedList, UIWidgets::ComboboxOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None));
}
else {
ImGui::Text("No Spoiler Logs found.");
}
ImGui::BeginDisabled(existingSeedList.empty());
if (ImGui::Button("Load")) {
if (UIWidgets::Button("Load", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
logTemp = existingSeedList[selectedList].c_str();
PlandomizerLoadSpoilerLog(logTemp.c_str());
}
ImGui::EndDisabled();
ImGui::BeginDisabled(spoilerLogData.empty());
ImGui::SameLine();
if (ImGui::Button("Save")) {
if (UIWidgets::Button("Save", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
PlandomizerSaveSpoilerLog();
}
ImGui::EndDisabled();
@ -1000,44 +1014,19 @@ void PlandomizerDrawOptions() {
}
if (getTabID == TAB_HINTS) {
if (ImGui::Button("Clear All Hints")) {
if (UIWidgets::Button("Clear All Hints", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
PlandomizerRemoveAllHints();
}
ImGui::SameLine();
if (ImGui::Button("Randomize All Hints")) {
if (UIWidgets::Button("Randomize All Hints", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
PlandomizerRandomizeHint(HINT_ALL, 0);
}
}
if (getTabID == TAB_LOCATIONS) {
if (plandoLogData.size() > 0) {
const char* comboLabel = rcAreaNames[selectedArea].c_str();
if (selectedArea == RCAREA_INVALID) {
comboLabel = "All";
}
ImGui::Text("Filter by Area:");
UIWidgets::Combobox("Filter by Area:##AreaFilter", &selectedArea, rcAreaNameMap, UIWidgets::ComboboxOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::Near).ComponentAlignment(UIWidgets::ComponentAlignments::Right));
ImGui::SameLine();
ImGui::PushItemWidth(300.0f);
if (ImGui::BeginCombo("##AreaFilter", comboLabel)) {
for (const auto& [area, name] : rcAreaNames) {
bool isSelected = (selectedArea == area);
const char* displayName = name.c_str();
if (area == RCAREA_INVALID) {
displayName = "All";
}
if (ImGui::Selectable(displayName, isSelected)) {
selectedArea = area;
}
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
ImGui::SameLine();
if (ImGui::Button("Empty All Rewards")) {
if (UIWidgets::Button("Empty All Rewards", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline).Padding(ImVec2(10.f, 6.f)))) {
PlandomizerRemoveAllItems();
}
}
@ -1067,16 +1056,14 @@ void PlandomizerDrawHintsWindow() {
}
ImGui::Text("New Hint: ");
ImGui::SameLine();
if (ImGui::Button(randomizeButton.c_str())) {
if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions().Color(THEME_COLOR).Padding(ImVec2(10.f, 6.f)).Size(UIWidgets::Sizes::Inline).Tooltip("Randomize Hint"))) {
PlandomizerRandomizeHint(HINT_SINGLE, index);
}
UIWidgets::Tooltip("Randomize Hint");
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 10);
if (UIWidgets::InputString("##HintMessage", &hintInputText)) {
if (UIWidgets::InputString("##HintMessage", &hintInputText, UIWidgets::InputOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None).Tooltip(plandomizerHintsTooltip().c_str()))) {
plandoHintData[index].hintText = hintInputText.c_str();
}
UIWidgets::Tooltip(plandomizerHintsTooltip().c_str());
index++;
ImGui::PopID();
}
@ -1133,6 +1120,7 @@ void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) {
void PlandomizerDrawSpoilerTable() {
ImGui::BeginChild("Main");
UIWidgets::PushStyleTabs(THEME_COLOR);
if (ImGui::BeginTabBar("Check Tabs")) {
if (ImGui::BeginTabItem("Gossip Stones")) {
getTabID = TAB_HINTS;
@ -1146,12 +1134,13 @@ void PlandomizerDrawSpoilerTable() {
}
}
ImGui::EndTabBar();
UIWidgets::PopStyleTabs();
ImGui::EndChild();
}
void PlandomizerWindow::DrawElement() {
PlandomizerDrawOptions();
UIWidgets::PaddedSeparator();
UIWidgets::Separator(true, true, 0.f, 0.f);
PlandomizerDrawSpoilerTable();
}

View file

@ -39,14 +39,14 @@ typedef struct {
std::string hintText;
} SpoilerHintObject;
typedef enum {
typedef enum PlandoTabs {
TAB_HINTS,
TAB_LOCATIONS
};
} PlandoTabs;
typedef enum {
typedef enum PlandoHints {
HINT_SINGLE,
HINT_ALL,
};
} PlandoHints;
#endif

View file

@ -54,9 +54,6 @@ void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor, PlayState* play) {
void ObjTsubo_RandomizerInit(void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef);
// Check for Lake Hylia specifically because the game spawns 2 pots out of bounds there for some reason.
if (actor->id != ACTOR_OBJ_TSUBO || gPlayState->sceneNum == SCENE_LAKE_HYLIA || gPlayState->sceneNum == SCENE_HYRULE_CASTLE) return;
ObjTsubo* potActor = static_cast<ObjTsubo*>(actorRef);
potActor->potIdentity = OTRGlobals::Instance->gRandomizer->IdentifyPot(gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z);

View file

@ -11,6 +11,7 @@
#include "objects/object_gi_key/object_gi_key.h"
#include "objects/object_gi_bosskey/object_gi_bosskey.h"
#include "objects/object_gi_compass/object_gi_compass.h"
#include "objects/object_gi_map/object_gi_map.h"
#include "objects/object_gi_hearts/object_gi_hearts.h"
#include "objects/object_gi_scale/object_gi_scale.h"
#include "objects/object_gi_fire/object_gi_fire.h"
@ -80,7 +81,7 @@ Color_RGB8 SmallEmblemDefaultValue[10] = {
extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry) {
s8 isCustomKeysEnabled = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("CustomKeyModels"), 0);
s8 isCustomKeysEnabled = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("CustomKeyModels"), 1);
int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_SMALL_KEY;
Gfx* customIconDLs[] = {
@ -131,15 +132,35 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
CLOSE_DISPS(play->state.gfxCtx);
}
extern "C" {
void GetItem_DrawCompass(PlayState* play, s16 drawId);
void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction);
void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
extern "C" void Randomizer_DrawMap(PlayState* play, GetItemEntry* getItemEntry) {
s16 color_slot = getItemEntry->drawItemId - RG_DEKU_TREE_MAP;
s16 colors[12][3] = {
{ 4, 100, 46 }, // Deku Tree
{ 140, 30, 30 }, // Dodongo's Cavern
{ 30, 60, 255 }, // Jabu Jabu's Belly
{ 4, 195, 46 }, // Forest Temple
{ 237, 95, 95 }, // Fire Temple
{ 85, 180, 223 }, // Water Temple
{ 222, 158, 47 }, // Spirit Temple
{ 126, 16, 177 }, // Shadow Temple
{ 227, 110, 255 }, // Bottom of the Well
{ 0, 255, 255 }, // Ice Cavern
};
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiDungeonMapDL);
CLOSE_DISPS(play->state.gfxCtx);
}
extern "C" void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEntry) {
s16 color_slot = getItemEntry->getItemId - RG_DEKU_TREE_COMPASS;
s16 color_slot = getItemEntry->drawItemId - RG_DEKU_TREE_COMPASS;
s16 colors[12][3] = {
{ 4, 100, 46 }, // Deku Tree
{ 140, 30, 30 }, // Dodongo's Cavern
@ -158,8 +179,7 @@ extern "C" void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEnt
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
gDPSetEnvColor(POLY_OPA_DISP++, colors[color_slot][0] / 2, colors[color_slot][1] / 2, colors[color_slot][2] / 2, 255);
@ -167,8 +187,7 @@ extern "C" void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEnt
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiCompassDL);
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 5);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiCompassGlassDL);
CLOSE_DISPS(play->state.gfxCtx);
@ -247,7 +266,7 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
}
extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry) {
s8 isCustomKeysEnabled = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("CustomKeyModels"), 0);
s8 isCustomKeysEnabled = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("CustomKeyModels"), 1);
int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_KEY_RING;
Gfx* CustomIconDLs[] = {
@ -485,7 +504,7 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get
CLOSE_DISPS(play->state.gfxCtx);
}
extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry) {
extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry) {
Color_RGB8 color = { 0, 60, 100 };
if (CVarGetInteger(CVAR_COSMETIC("World.MysteryItem.Changed"), 0)) {
color = CVarGetColor24(CVAR_COSMETIC("World.MysteryItem.Value"), color);

View file

@ -10,6 +10,7 @@ typedef struct PlayState PlayState;
extern "C" {
#endif
void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawMap(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry);
@ -22,7 +23,7 @@ void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry);

View file

@ -587,6 +587,10 @@ CustomMessage Hint::GetGanonBossKeyText() {
auto ctx = Rando::Context::GetInstance();
CustomMessage ganonBossKeyMessage;
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage();
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH)) {
return StaticData::hintTextTable[RHT_GANON_BK_START_WITH_HINT].GetHintMessage();
}
@ -631,9 +635,6 @@ CustomMessage Hint::GetGanonBossKeyText() {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_TOKENS_HINT].GetHintMessage();
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage();
}
return ganonBossKeyMessage;
}

View file

@ -297,17 +297,22 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
rc != RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE &&
// Always show ItemGet animation for ice traps
!(getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId == RG_ICE_TRAP) &&
// Always show ItemGet animation outside of randomizer to keep behaviour consistent in vanilla
IS_RANDO &&
(
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED) == SGIA_ALL ||
CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED) == SGIA_ALL ||
(
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED) == SGIA_JUNK &&
CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED) == SGIA_JUNK &&
(
//crude fix to ensure map hints are readable. Ideally replace with better hint tracking.
!(getItemEntry.getItemId >= RG_DEKU_TREE_MAP && getItemEntry.getItemId <= RG_ICE_CAVERN_MAP) && (
getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK ||
getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN ||
getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER
)
)
)
)
) {
Item_DropCollectible(gPlayState, &spawnPos, ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000);
}
@ -411,7 +416,7 @@ void EnExItem_WaitForObjectRandomized(EnExItem* enExItem, PlayState* play) {
}
void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) {
f32 mtxScale = CVarGetFloat(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimationScale"), 10.0f);
f32 mtxScale = CVarGetFloat(CVAR_RANDOMIZER_ENHANCEMENT("TimeSavers.SkipGetItemAnimationScale"), 10.0f);
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
GetItemEntry randoItem = enItem00->itemEntry;
if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) &&
@ -542,27 +547,6 @@ u8 EnGm_RandoCanGetMedigoronItem() {
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON);
}
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) {
switch (songIndex) {
case FROG_ZL:
return RC_ZR_FROGS_ZELDAS_LULLABY;
case FROG_EPONA:
return RC_ZR_FROGS_EPONAS_SONG;
case FROG_SARIA:
return RC_ZR_FROGS_SARIAS_SONG;
case FROG_SUNS:
return RC_ZR_FROGS_SUNS_SONG;
case FROG_SOT:
return RC_ZR_FROGS_SONG_OF_TIME;
case FROG_STORMS:
return RC_ZR_FROGS_IN_THE_RAIN;
case FROG_CHOIR_SONG:
return RC_ZR_FROGS_OCARINA_GAME;
default:
return RC_UNKNOWN_CHECK;
}
}
void RandomizerSetChestGameRandomizerInf(RandomizerCheck rc) {
switch (rc) {
case RC_MARKET_TREASURE_CHEST_GAME_ITEM_1:
@ -783,7 +767,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
}
case VB_PLAY_SLOW_CHEST_CS: {
// We force fast chests if SkipGetItemAnimation is enabled because the camera in the CS looks pretty wonky otherwise
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED)) {
if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED)) {
*should = false;
}
break;
@ -2033,8 +2017,10 @@ void RandomizerOnActorInitHandler(void* actorRef) {
// Deletes all actors in the boss category if the soul isn't found.
// Some actors, like Dark Link, Arwings, and Zora's Sapphire...?, are in this category despite not being actual bosses,
// so ignore any "boss" if `currentBossSoulRandInf` doesn't change from RAND_INF_MAX.
// Iron Knuckle (Nabooru) in Twinrova's room is a special exception, so exclude knuckles too.
if (currentBossSoulRandInf != RAND_INF_MAX) {
if (!Flags_GetRandomizerInf(currentBossSoulRandInf) && actor->category == ACTORCAT_BOSS) {
if (!Flags_GetRandomizerInf(currentBossSoulRandInf) && actor->category == ACTORCAT_BOSS &&
actor->id != ACTOR_EN_IK) {
Actor_Delete(&gPlayState->actorCtx, actor, gPlayState);
}
//Special case for Phantom Ganon's horse (and fake), as they're considered "background actors",
@ -2382,7 +2368,7 @@ void RandomizerRegisterHooks() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(fishsanityOnVanillaBehaviorHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemReceive>(fishsanityOnItemReceiveHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(shufflePotsOnActorInitHook);
GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::OnActorInit>(shufflePotsOnActorInitHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(shufflePotsOnVanillaBehaviorHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(shuffleFreestandingOnVanillaBehaviorHook);
@ -2458,7 +2444,7 @@ void RandomizerRegisterHooks() {
}
if (RAND_GET_OPTION(RSK_SHUFFLE_POTS) != RO_SHUFFLE_POTS_OFF) {
shufflePotsOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(ObjTsubo_RandomizerInit);
shufflePotsOnActorInitHook = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_OBJ_TSUBO, ObjTsubo_RandomizerInit);
shufflePotsOnVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(ShufflePots_OnVanillaBehaviorHandler);
}

View file

@ -94,6 +94,7 @@ std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
actual = RG_DEKU_STICK_BAG;
break;
}
[[fallthrough]];
case 1:
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
actual = RG_STICK_UPGRADE_INF;
@ -123,6 +124,7 @@ std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
actual = RG_DEKU_NUT_BAG;
break;
}
[[fallthrough]];
case 1:
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
actual = RG_NUT_UPGRADE_INF;

View file

@ -98,15 +98,25 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
// Maps and Compasses
itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DEKU_TREE_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DODONGOS_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_JABU_JABUS_BELLY_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_FIRE_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_WATER_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_SPIRIT_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_SHADOW_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_BOTTOM_OF_THE_WELL_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_ICE_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap);
itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass);
itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
@ -339,7 +349,7 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale);
itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "Sac de Missiles Teigneux" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag);
itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);

View file

@ -71,8 +71,8 @@ void RegionTable_Init_DekuTree() {
}, {
//Locations
LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, true),
LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE, logic->CanJumpslashExceptHammer() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE)),
LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanUseProjectile() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->CanJumpslashExceptHammer())),
LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)),
LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW)),
}, {
//Exits
Entrance(RR_DEKU_TREE_LOBBY, []{return true;}),
@ -84,7 +84,7 @@ void RegionTable_Init_DekuTree() {
areaTable[RR_DEKU_TREE_BASEMENT_SCRUB_ROOM] = Region("Deku Tree Basement Scrub Room", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return true;}),
Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, []{return Here(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW);});}),
Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, []{return Here(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return logic->CanHitEyeTargets();});}),
});
areaTable[RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT] = Region("Deku Tree Basement Water Room Front", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {

View file

@ -154,6 +154,7 @@ void RegionTable_Init_DodongosCavern() {
LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART, true),
}, {
//Exits
Entrance(RR_DODONGOS_CAVERN_ARMOS_ROOM, []{return true;}),
Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, []{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->CanBreakMudWalls() || (ctx->GetTrickOption(RT_DC_SCRUB_ROOM) && logic->HasItem(RG_GORONS_BRACELET));});}),
Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, []{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, []{return (logic->IsAdult && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}),
@ -304,6 +305,7 @@ void RegionTable_Init_DodongosCavern() {
LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_4, logic->CanBreakPots()),
}, {
//Exits
Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return true;}),
//This is possible with sticks and shield, igniting a first flower by "touch" then very quickly crouch stabbing in a way that cuts the corner to light the 3rd bomb on the other side, but that's a trick
Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, []{return Here(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return logic->HasExplosives() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DC_STAIRCASE) && logic->CanUse(RG_FAIRY_BOW));});}),
Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_MUD_WALL, []{return Here(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return logic->CanBreakMudWalls();});}),
@ -460,7 +462,7 @@ void RegionTable_Init_DodongosCavern() {
LOCATION(RC_DODONGOS_CAVERN_MQ_POE_ROOM_POT_4, logic->CanBreakPots()),
}, {
//Exits
Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}),
Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}),
Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, []{return true;}),
Entrance(RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM, []{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}),
});

View file

@ -357,7 +357,7 @@ void RegionTable_Init_FireTemple() {
areaTable[RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER] = Region("Fire Temple MQ First Room Upper", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return true;}),
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->HasFireSource();}),
Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, []{return logic->HasFireSource();}),
Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, []{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, []{return logic->CanUse(RG_MEGATON_HAMMER);});}),
});

View file

@ -28,7 +28,7 @@ void RegionTable_Init_ForestTemple() {
areaTable[RR_FOREST_TEMPLE_SOUTH_CORRIDOR] = Region("Forest Temple South Corridor", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, []{return true;}),
Entrance(RR_FOREST_TEMPLE_LOBBY, []{return logic->CanAttack() || logic->CanUse(RG_NUTS);}),
Entrance(RR_FOREST_TEMPLE_LOBBY, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
});
areaTable[RR_FOREST_TEMPLE_LOBBY] = Region("Forest Temple Lobby", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {

View file

@ -28,7 +28,7 @@ void RegionTable_Init_GanonsCastle() {
Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, []{return true;}),
Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, []{return true;}),
Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);}),
Entrance(RR_GANONS_TOWER_FLOOR_1, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
@ -61,7 +61,7 @@ void RegionTable_Init_GanonsCastle() {
EventAccess(&logic->ForestTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE));}),
}, {
//Locations
LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanDamage()),
LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS)),
LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_POT_1, logic->CanBreakPots() && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE))),
LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_POT_2, logic->CanBreakPots() && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE))),
}, {});
@ -78,7 +78,7 @@ void RegionTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->BlueFireAccess, []{return logic->BlueFireAccess || logic->HasBottle();}),
EventAccess(&logic->BlueFireAccess, []{return true;}),
EventAccess(&logic->FairyPot, []{return logic->FairyPot || (logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD));}),
EventAccess(&logic->WaterTrialClear, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}),
}, {
@ -112,7 +112,7 @@ void RegionTable_Init_GanonsCastle() {
EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->CanUse(RG_BOMBCHU_5) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}),
}, {
//Locations
LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->CanJumpslashExceptHammer()),
LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanJumpslashExceptHammer() || logic->CanUse(RG_BOMBCHU_5))),
LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))),
LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_1, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))),
LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_2, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))),
@ -162,7 +162,7 @@ void RegionTable_Init_GanonsCastle() {
Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, []{return true;}),
Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return Here(RR_GANONS_CASTLE_MQ_MAIN, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);});}),
//RANDOTODO could we just set these events automatically based on the setting?
Entrance(RR_GANONS_TOWER_FLOOR_1, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
@ -431,9 +431,16 @@ void RegionTable_Init_GanonsCastle() {
#pragma region Tower and Escape
areaTable[RR_GANONS_TOWER_ENTRYWAY] = Region("Ganon's Tower Entryway", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_GANONS_CASTLE_LOBBY, []{return ctx->GetDungeon(GANONS_CASTLE)->IsVanilla();}),
Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return ctx->GetDungeon(GANONS_CASTLE)->IsMQ();}),
Entrance(RR_GANONS_TOWER_FLOOR_1, []{return true;}),
});
areaTable[RR_GANONS_TOWER_FLOOR_1] = Region("Ganon's Tower Floor 1", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_GANONS_CASTLE_LOBBY, []{return Here(RR_GANONS_TOWER_FLOOR_1, []{return logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2);});}),
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return Here(RR_GANONS_TOWER_FLOOR_1, []{return logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2);});}),
Entrance(RR_GANONS_TOWER_FLOOR_2, []{return Here(RR_GANONS_TOWER_FLOOR_1, []{return logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2);});}),
});

View file

@ -17,8 +17,8 @@ void RegionTable_Init_GerudoTrainingGround() {
areaTable[RR_GERUDO_TRAINING_GROUND_LOBBY] = Region("Gerudo Training Ground Lobby", "Gerudo Training Ground", {RA_GERUDO_TRAINING_GROUND}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)),
LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)),
LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanHitEyeTargets()),
LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanHitEyeTargets()),
LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)),
LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true)),
LOCATION(RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)),

View file

@ -21,18 +21,18 @@ void RegionTable_Init_IceCavern() {
}, {
//Exits
Entrance(RR_ICE_CAVERN_ENTRYWAY, []{return true;}),
Entrance(RR_ICE_CAVERN_MAIN, []{return Here(RR_ICE_CAVERN_BEGINNING, []{return (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives() || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE);});}),
Entrance(RR_ICE_CAVERN_MAIN, []{return Here(RR_ICE_CAVERN_BEGINNING, []{return logic->CanKillEnemy(RE_FREEZARD, ED_CLOSE, true, 4);});}),
});
areaTable[RR_ICE_CAVERN_MAIN] = Region("Ice Cavern", "Ice Cavern", {RA_ICE_CAVERN}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->BlueFireAccess, []{return logic->BlueFireAccess || (logic->IsAdult && logic->HasBottle());}),
EventAccess(&logic->BlueFireAccess, []{return logic->IsAdult;}),
}, {
//Locations
LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && logic->IsAdult),
LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, logic->BlueFire()),
LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, logic->BlueFire() && (logic->CanJumpslash() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE))),
LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->BlueFire() && (logic->CanJumpslash() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE)) && logic->IsAdult),
LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS)),
LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS) && logic->IsAdult),
LOCATION(RC_ICE_CAVERN_FREESTANDING_POH, logic->BlueFire()),
LOCATION(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, logic->HookshotOrBoomerang()),
LOCATION(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, logic->BlueFire() && logic->HookshotOrBoomerang()),
@ -125,7 +125,7 @@ void RegionTable_Init_IceCavern() {
LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->CanKillEnemy(RE_STALFOS)),
}, {
//Exits
Entrance(RR_ICE_CAVERN_MQ_SCARECROW_ROOM, []{return logic->BlueFire() && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
Entrance(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, []{return Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
Entrance(RR_ICE_CAVERN_MQ_BEGINNING, []{return logic->CanUse(RG_IRON_BOOTS) && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
});

View file

@ -24,7 +24,6 @@ void RegionTable_Init_JabuJabusBelly() {
//Combines Lift room middle and lower, 1F holes room, the forked corridor, and it's side rooms
areaTable[RR_JABU_JABUS_BELLY_MAIN] = Region("Jabu Jabus Belly Main", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->JabuRutoInB1, []{return true;}),
EventAccess(&logic->JabuWestTentacle, []{return logic->JabuRutoIn1F && logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}),
}, {
//Locations
@ -263,7 +262,7 @@ void RegionTable_Init_JabuJabusBelly() {
areaTable[RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS] = Region("Jabu Jabus Belly MQ West Forked Rooms", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->JabuWestTentacle, []{return logic->CanUse(RG_BOOMERANG);}),
EventAccess(&logic->JabuWestTentacle, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}),
}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, Here(RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS, []{return logic->HasExplosives();}) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),

View file

@ -79,8 +79,8 @@ void RegionTable_Init_ShadowTemple() {
areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Region("Shadow Temple Wind Tunnel", "Shadow Temple", {RA_SHADOW_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, true),
LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanJumpslashExceptHammer()),
LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, true),
LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2)),
LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives()),
LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, logic->CanUse(RG_LONGSHOT) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5)),
LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_1, logic->CanBreakPots()),
@ -96,7 +96,7 @@ void RegionTable_Init_ShadowTemple() {
//Locations
LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)),
LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)),
LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, logic->CanJumpslashExceptHammer()),
LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, logic->CanKillEnemy(RE_FLOORMASTER)),
//RANDOTODO check if child can reach the token
LOCATION(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, logic->IsAdult && logic->CanAttack()),
LOCATION(RC_SHADOW_TEMPLE_AFTER_BOAT_POT_1, logic->CanBreakPots()),
@ -181,7 +181,7 @@ void RegionTable_Init_ShadowTemple() {
//Room exists for if it's ever possible to go backwards or void warp into the middle of shadow
areaTable[RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR] = Region("Shadow Temple MQ B2 to B3 Corridor", "Shadow Temple", {RA_SHADOW_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return logic->HasExplosives() && logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, []{return true;}),
//bunnyhovers + lens lets you go from the very top of upper pit to the stationary invisible platform below quite easily
});

View file

@ -79,7 +79,7 @@ void RegionTable_Init_CastleGrounds() {
LOCATION(RC_HC_STORMS_GROTTO_POT_4, logic->CanBreakPots()),
}, {
//Exits
Entrance(RR_CASTLE_GROUNDS, []{return true;}),
Entrance(RR_HC_STORMS_GROTTO, []{return true;}),
});
areaTable[RR_GANONS_CASTLE_GROUNDS] = Region("Ganon's Castle Grounds", "Castle Grounds", {RA_OUTSIDE_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {

View file

@ -50,7 +50,7 @@ void RegionTable_Init_Graveyard() {
LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_8, true),
}, {
//Exits
Entrance(RR_THE_GRAVEYARD, []{return true;}),
Entrance(RR_GRAVEYARD_SHIELD_GRAVE, []{return true;}),
});
areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Region("Graveyard Heart Piece Grave", "Graveyard Heart Piece Grave", {}, NO_DAY_NIGHT_CYCLE, {}, {

View file

@ -992,7 +992,7 @@ void Rando::StaticData::InitLocationTable() { //
locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, "Open Grotto Gossip Stone");
locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, "Open Grotto Gossip Stone");
locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, "Open Grotto Gossip Stone");
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, "Near Shortcuts Gossip Stone");
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, "Near Shortcuts Grotto Gossip Stone");
locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, "Storms Grotto Gossip Stone");
locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, "Upper Grotto Gossip Stone");

View file

@ -673,7 +673,7 @@ namespace Rando {
}
return killed;
case RE_BIG_OCTO:
//If chasing octo is annoying but with rolls you can catch him, and you need rang to get into this room without shenanigains anyway. Bunny makes it free
//If chasing octo is annoying but with rolls you can catch him, and you need rang to get into this room without shenanigans anyway. Bunny makes it free
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_STICKS) || CanUse(RG_MASTER_SWORD);
case RE_GOHMA:
return HasBossSoul(RG_GOHMA_SOUL) && CanJumpslash() &&
@ -1783,7 +1783,7 @@ namespace Rando {
case ITEMTYPE_EQUIP:
{
RandomizerGet itemRG = item.GetRandomizerGet();
if (itemRG == RG_GIANTS_KNIFE) {
if (itemRG == RG_GIANTS_KNIFE || itemRG == RG_DEKU_SHIELD || itemRG == RG_HYLIAN_SHIELD) {
return;
}
uint32_t equipId = RandoGetToEquipFlag.find(itemRG)->second;
@ -2339,7 +2339,6 @@ namespace Rando {
MQSpiritMapRoomEnemies = false;
MQSpirit3SunsEnemies = false;
Spirit1FSilverRupees = false;
JabuRutoInB1 = false;
JabuRutoIn1F = false;
StopPerformanceTimer(PT_LOGIC_RESET);

View file

@ -179,7 +179,6 @@ class Logic {
bool MQSpiritTimeTravelChest = false;
bool MQSpirit3SunsEnemies = false;
bool Spirit1FSilverRupees = false;
bool JabuRutoInB1 = false;
bool JabuRutoIn1F = false;
/* --- END OF HELPERS AND LOCATION ACCESS --- */

View file

@ -2,7 +2,9 @@
#include "libultraship/bridge.h"
#include <Context.h>
#include <imgui.h>
#include "soh/SohGui/SohGui.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include <soh/cvar_prefixes.h>
namespace Rando {
Option Option::Bool(RandomizerSettingKey key_, std::string name_, std::vector<std::string> options_,
@ -130,11 +132,10 @@ void Option::Enable() {
disabled = false;
}
void Option::Disable(std::string text, const UIWidgets::CheckboxGraphics graphic) {
if (!disabled || disabledText != text || disabledGraphic != graphic) {
void Option::Disable(std::string text) {
if (!disabled || disabledText != text) {
disabled = true;
disabledText = std::move(text);
disabledGraphic = graphic;
}
}
@ -149,9 +150,6 @@ bool Option::RenderImGui() {
case WidgetType::Checkbox:
changed = RenderCheckbox();
break;
case WidgetType::TristateCheckbox:
changed = RenderTristateCheckbox();
break;
case WidgetType::Combobox:
changed = RenderCombobox();
break;
@ -159,7 +157,6 @@ bool Option::RenderImGui() {
changed = RenderSlider();
break;
}
UIWidgets::Spacer(0);
ImGui::EndGroup();
return changed;
}
@ -213,50 +210,19 @@ Option::Option(size_t key_, std::string name_, std::vector<std::string> options_
bool Option::RenderCheckbox() {
bool changed = false;
if (disabled) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
bool val = static_cast<bool>(CVarGetInteger(cvarName.c_str(), defaultOption));
if (CustomCheckbox(name.c_str(), &val, disabled, disabledGraphic)) {
UIWidgets::CheckboxOptions widgetOptions = static_cast<UIWidgets::CheckboxOptions>(UIWidgets::CheckboxOptions().Color(THEME_COLOR).Tooltip(description.c_str()));
widgetOptions.disabled = disabled;
if (UIWidgets::Checkbox(name.c_str(), &val, widgetOptions)) {
CVarSetInteger(cvarName.c_str(), val);
changed = true;
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
if (!description.empty()) {
UIWidgets::InsertHelpHoverText(description.c_str());
}
if (disabled) {
UIWidgets::ReEnableComponent(disabledText.c_str());
}
return changed;
}
bool Option::RenderTristateCheckbox() {
bool changed = false;
if (disabled) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
int val = CVarGetInteger(cvarName.c_str(), defaultOption);
if (CustomCheckboxTristate(name.c_str(), &val, disabled, disabledGraphic)) {
CVarSetInteger(cvarName.c_str(), val);
changed = true;
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
if (!description.empty()) {
UIWidgets::InsertHelpHoverText(description.c_str());
}
if (disabled) {
UIWidgets::ReEnableComponent(disabledText.c_str());
}
return changed;
}
bool Option::RenderCombobox() {
bool changed = false;
if (disabled) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
ImGui::Text("%s", name.c_str());
uint8_t selected = CVarGetInteger(cvarName.c_str(), defaultOption);
if (selected >= options.size()) {
selected = options.size();
@ -264,26 +230,16 @@ bool Option::RenderCombobox() {
changed = true;
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
if (!description.empty()) {
UIWidgets::InsertHelpHoverText(description.c_str());
UIWidgets::ComboboxOptions widgetOptions = UIWidgets::ComboboxOptions().Color(THEME_COLOR).Tooltip(description.c_str());
if (this->GetKey() == RSK_LOGIC_RULES) {
widgetOptions = widgetOptions.LabelPosition(UIWidgets::LabelPositions::None).ComponentAlignment(UIWidgets::ComponentAlignments::Right);
}
const std::string comboName = std::string("##") + std::string(cvarName);
if (ImGui::BeginCombo(comboName.c_str(), options[selected].c_str())) {
for (size_t i = 0; i < options.size(); i++) {
if (!options[i].empty()) {
if (ImGui::Selectable(options[i].c_str(), i == selected)) {
CVarSetInteger(cvarName.c_str(), static_cast<int>(i));
widgetOptions.disabled = disabled;
if(UIWidgets::Combobox(name.c_str(), &selected, options, widgetOptions)) {
CVarSetInteger(cvarName.c_str(), static_cast<int>(selected));
changed = true;
selected = i;
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
}
}
ImGui::EndCombo();
}
if (disabled) {
UIWidgets::ReEnableComponent(disabledText.c_str());
}
return changed;
}
@ -295,40 +251,11 @@ bool Option::RenderSlider() {
CVarSetInteger(cvarName.c_str(), val);
changed = true;
}
if (disabled) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
const std::string formatName = name + ": %s";
ImGui::Text(formatName.c_str(), options[val].c_str());
if (!description.empty()) {
UIWidgets::InsertHelpHoverText(description.c_str());
}
UIWidgets::Spacer(0);
ImGui::BeginGroup();
const std::string MinusBTNName = " - ##" + cvarName;
if (ImGui::Button(MinusBTNName.c_str())) {
val--;
UIWidgets::IntSliderOptions widgetOptions = UIWidgets::IntSliderOptions().Color(THEME_COLOR).Min(0).Max(options.size() - 1).Tooltip(description.c_str()).Format(options[val].c_str()).DefaultValue(defaultOption);
widgetOptions.disabled = disabled;
if (UIWidgets::SliderInt(name.c_str(), &val, widgetOptions)) {
changed = true;
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
ImGui::PushItemWidth(std::min(ImGui::GetContentRegionAvail().x - 30.0f, 260.0f));
const std::string id = "##Slider" + cvarName;
if (ImGui::SliderInt(id.c_str(), &val, 0, static_cast<int>(options.size()) - 1, "", ImGuiSliderFlags_AlwaysClamp)) {
changed = true;
}
ImGui::PopItemWidth();
const std::string PlusBTNName = " + ##" + cvarName;
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
if (ImGui::Button(PlusBTNName.c_str())) {
val++;
changed = true;
}
ImGui::EndGroup();
if (disabled) {
UIWidgets::ReEnableComponent(disabledText.c_str());
}
if (val < 0) {
val = 0;
changed = true;
@ -465,7 +392,7 @@ bool OptionGroup::RenderImGui() const { // NOLINT(*-no-recursion)
ImGui::TableSetColumnIndex(i);
ImGui::TableHeader(mSubGroups[i]->GetName().c_str());
if (!mSubGroups[i]->GetDescription().empty()) {
UIWidgets::SetLastItemHoverText(mSubGroups[i]->GetDescription().c_str());
UIWidgets::Tooltip(mSubGroups[i]->GetDescription().c_str());
}
}
ImGui::PopItemFlag();
@ -473,12 +400,10 @@ bool OptionGroup::RenderImGui() const { // NOLINT(*-no-recursion)
}
}
if (mContainerType == WidgetContainerType::SECTION && !mName.empty()) {
UIWidgets::PaddedSeparator();
ImGui::Text("%s", mName.c_str());
ImGui::SeparatorText(mName.c_str());
if (!mDescription.empty()) {
UIWidgets::InsertHelpHoverText(mDescription.c_str());
UIWidgets::Tooltip(mDescription.c_str());
}
UIWidgets::PaddedSeparator();
}
if (mContainerType == WidgetContainerType::COLUMN) {
ImGui::TableNextColumn();
@ -507,9 +432,6 @@ bool OptionGroup::RenderImGui() const { // NOLINT(*-no-recursion)
if (option->HasFlag(IMFLAG_UNINDENT)) {
ImGui::Unindent();
}
if (option->HasFlag(IMFLAG_SEPARATOR_BOTTOM)) {
UIWidgets::PaddedSeparator(false, true);
}
}
}
if (mContainerType == WidgetContainerType::COLUMN) {

View file

@ -1,6 +1,7 @@
#pragma once
#include "soh/SohGui/UIWidgets.hpp"
#ifndef RANDOPTION_H
#define RANDOPTION_H
#include <cstdint>
#include <set>
@ -35,7 +36,6 @@ enum class OptionCategory {
*/
enum class WidgetType {
Checkbox, /** Default for Bools, not compatible if options.size() > 2. */
TristateCheckbox, /** Compatible with U8s, not compatible if options.size() != 3. */
Combobox, /** Default for U8s, works with U8s and Bools. */
Slider, /** Compatible with U8s. If constructed with NumOpts, consider using this. Technically can be used for Bool or non-NumOpts options but it would be a bit weird semantically. */
};
@ -312,7 +312,7 @@ class Option {
* @param graphic What graphic to display in a disabled checkbox. Defaults to an
* "X" symbol.
*/
void Disable(std::string text, UIWidgets::CheckboxGraphics graphic = UIWidgets::CheckboxGraphics::Cross);
void Disable(std::string text);
bool IsCategory(OptionCategory category) const;
/**
@ -339,7 +339,6 @@ protected:
private:
bool RenderCheckbox();
bool RenderTristateCheckbox();
bool RenderCombobox();
bool RenderSlider();
void PopulateTextToNum();
@ -357,7 +356,6 @@ protected:
bool defaultHidden = false;
int imFlags = IMFLAG_NONE;
bool disabled = false;
UIWidgets::CheckboxGraphics disabledGraphic = UIWidgets::CheckboxGraphics::Cross;
std::string disabledText;
std::unordered_map<std::string, uint8_t> optionsTextToVar = {};
};
@ -547,3 +545,5 @@ class OptionGroup {
bool mDisabled = false;
};
} // namespace Rando
#endif //RANDOPTION_H

View file

@ -11,9 +11,8 @@
#include "3drando/rando_main.hpp"
#include "3drando/random.hpp"
#include "soh/ResourceManagerHelpers.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "3drando/custom_messages.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include <imgui.h>
#include <imgui_internal.h>
#include "../custom-message/CustomMessageTypes.h"
@ -27,6 +26,7 @@
#include <tuple>
#include <functional>
#include "draw.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "static_data.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include <boost_custom/container_hash/hash_32.hpp>
@ -1807,7 +1807,6 @@ PotIdentity Randomizer::IdentifyPot(s32 sceneNum, s32 posX, s32 posZ) {
if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) {
LUSLOG_WARN("IdentifyPot did not receive a valid RC value (%d).", location->GetRandomizerCheck());
assert(false);
} else {
potIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
potIdentity.randomizerCheck = location->GetRandomizerCheck();
@ -1924,6 +1923,16 @@ bool GenerateRandomizer(std::string seed /*= ""*/) {
return false;
}
static const std::unordered_map<int32_t, const char*> randomizerPresetList = {
{ RANDOMIZER_PRESET_DEFAULT, "Default" },
{ RANDOMIZER_PRESET_SPOCK_RACE, "Spock Race" },
{ RANDOMIZER_PRESET_SPOCK_RACE_NO_LOGIC, "Spock Race (No Logic)" },
{ RANDOMIZER_PRESET_S6, "S6" },
{ RANDOMIZER_PRESET_HELL_MODE, "Hell Mode" },
{ RANDOMIZER_PRESET_BENCHMARK, "Benchmark" }
};
static int32_t randomizerPresetSelected = RANDOMIZER_PRESET_DEFAULT;
void RandomizerSettingsWindow::DrawElement() {
auto ctx = Rando::Context::GetInstance();
if (generated) {
@ -1931,30 +1940,62 @@ void RandomizerSettingsWindow::DrawElement() {
randoThread.join();
}
bool disableEditingRandoSettings = CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) || CVarGetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
if (disableEditingRandoSettings) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) || disableEditingRandoSettings);
const PresetTypeDefinition presetTypeDef = presetTypes.at(PRESET_TYPE_RANDOMIZER);
std::string comboboxTooltip = "";
for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
if (iter->first != 0) comboboxTooltip += "\n\n";
comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description);
}
const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(PRESET_TYPE_RANDOMIZER);
randomizerPresetSelected = CVarGetInteger(presetTypeCvar.c_str(), RANDOMIZER_PRESET_DEFAULT);
if (UIWidgets::Combobox("Randomizer Presets", &randomizerPresetSelected, randomizerPresetList, UIWidgets::ComboboxOptions()
.DefaultIndex(RANDOMIZER_PRESET_DEFAULT)
.Tooltip(comboboxTooltip.c_str())
.Color(THEME_COLOR))
) {
CVarSetInteger(presetTypeCvar.c_str(), randomizerPresetSelected);
}
ImGui::SameLine();
ImGui::SetCursorPosY(ImGui::GetCursorPos().y + 35.f);
if (UIWidgets::Button("Apply Preset##Randomizer", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline).Padding(ImVec2(10.f, 6.f)))) {
if (randomizerPresetSelected >= presetTypeDef.presets.size()) {
randomizerPresetSelected = 0;
}
const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(randomizerPresetSelected);
for(const char* block : presetTypeDef.blocksToClear) {
CVarClearBlock(block);
}
if (randomizerPresetSelected != 0) {
applyPreset(selectedPresetDef.entries);
}
CVarSetInteger(presetTypeCvar.c_str(), randomizerPresetSelected);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
DrawPresetSelector(PRESET_TYPE_RANDOMIZER);
ImGui::EndDisabled();
UIWidgets::Spacer(0);
UIWidgets::EnhancementCheckbox("Manual seed entry", CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), false, "");
UIWidgets::CVarCheckbox("Manual seed entry", CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), UIWidgets::CheckboxOptions().Color(THEME_COLOR));
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0)) {
ImGui::Text("Seed");
UIWidgets::PushStyleInput(THEME_COLOR);
ImGui::InputText("##RandomizerSeed", seedString, MAX_SEED_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum);
UIWidgets::Tooltip(
"Characters from a-z, A-Z, and 0-9 are supported.\n"
"Character limit is 1023, after which the seed will be truncated.\n"
);
ImGui::SameLine();
if (ImGui::Button("New Seed")) {
if (strnlen(seedString, MAX_SEED_STRING_SIZE) == 0) {
ImGui::SameLine(17.0f);
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.4f), "Leave blank for random seed");
}
UIWidgets::PopStyleInput();
ImGui::SameLine(0.f, 50.f);
if (UIWidgets::Button(ICON_FA_RANDOM, UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR).Padding(ImVec2(10.f, 6.f)).Tooltip(
"Creates a new random seed value to be used when generating a randomizer"
))) {
SohUtils::CopyStringToCharArray(seedString, std::to_string(rand() & 0xFFFFFFFF), MAX_SEED_STRING_SIZE);
}
UIWidgets::Tooltip("Creates a new random seed value to be used when generating a randomizer");
ImGui::SameLine();
if (ImGui::Button("Clear Seed")) {
if (UIWidgets::Button(ICON_FA_ERASER, UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR).Padding(ImVec2(10.f, 6.f)))) {
memset(seedString, 0, MAX_SEED_STRING_SIZE);
}
}
@ -1962,13 +2003,13 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::Spacer(0);
ImGui::BeginDisabled((CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0) && gSaveContext.gameMode != GAMEMODE_FILE_SELECT) ||
GameInteractor::IsSaveLoaded());
if (ImGui::Button("Generate Randomizer")) {
if (UIWidgets::Button("Generate Randomizer", UIWidgets::ButtonOptions().Size(ImVec2(250.f, 0.f)).Color(THEME_COLOR))) {
ctx->SetSpoilerLoaded(false);
GenerateRandomizer(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0) ? seedString : "");
}
ImGui::EndDisabled();
UIWidgets::Spacer(0);
ImGui::SameLine();
if (!CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) {
std::string spoilerfilepath = CVarGetString(CVAR_GENERAL("SpoilerLog"), "");
ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str());
@ -1978,13 +2019,13 @@ void RandomizerSettingsWindow::DrawElement() {
// std::string presetfilepath = CVarGetString(CVAR_RANDOMIZER_SETTING("LoadedPreset"), "");
// ImGui::Text("Settings File: %s", presetfilepath.c_str());
UIWidgets::PaddedSeparator();
UIWidgets::Separator(true, true, 0.f, 0.f);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
ImGuiWindow* window = ImGui::GetCurrentWindow();
static ImVec2 cellPadding(8.0f, 8.0f);
UIWidgets::PushStyleTabs(THEME_COLOR);
if (ImGui::BeginTabBar("Randomizer Settings", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
if (ImGui::BeginTabItem("World")) {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding);
@ -2048,7 +2089,9 @@ void RandomizerSettingsWindow::DrawElement() {
window->DC.CurrLineTextBaseOffset = 0.0f;
static ImGuiTextFilter locationSearch;
UIWidgets::PushStyleInput(THEME_COLOR);
locationSearch.Draw();
UIWidgets::PopStyleInput();
ImGui::BeginChild("ChildIncludedLocations", ImVec2(0, -8));
for (auto& [rcArea, locations] : RandomizerCheckObjects::GetAllRCObjectsByArea()) {
@ -2068,7 +2111,7 @@ void RandomizerSettingsWindow::DrawElement() {
for (auto& location : locations) {
if (ctx->GetItemLocation(location)->IsVisible() && !excludedLocations.count(location) &&
locationSearch.PassFilter(Rando::StaticData::GetLocation(location)->GetName().c_str())) {
UIWidgets::PushStyleButton(THEME_COLOR, ImVec2(7.f, 5.f));
if (ImGui::ArrowButton(std::to_string(location).c_str(), ImGuiDir_Right)) {
excludedLocations.insert(location);
// todo: this efficently when we build out cvar array support
@ -2080,6 +2123,7 @@ void RandomizerSettingsWindow::DrawElement() {
CVarSetString(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), excludedLocationString.c_str());
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
UIWidgets::PopStyleButton();
ImGui::SameLine();
ImGui::Text("%s", Rando::StaticData::GetLocation(location)->GetShortName().c_str());
}
@ -2110,6 +2154,7 @@ void RandomizerSettingsWindow::DrawElement() {
for (auto& location : locations) {
auto elfound = excludedLocations.find(location);
if (ctx->GetItemLocation(location)->IsVisible() && elfound != excludedLocations.end()) {
UIWidgets::PushStyleButton(THEME_COLOR, ImVec2(7.f, 5.f));
if (ImGui::ArrowButton(std::to_string(location).c_str(), ImGuiDir_Left)) {
excludedLocations.erase(elfound);
// todo: this efficently when we build out cvar array support
@ -2125,6 +2170,7 @@ void RandomizerSettingsWindow::DrawElement() {
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
UIWidgets::PopStyleButton();
ImGui::SameLine();
ImGui::Text("%s", Rando::StaticData::GetLocation(location)->GetShortName().c_str());
}
@ -2272,10 +2318,12 @@ void RandomizerSettingsWindow::DrawElement() {
//{ Rando::Tricks::Tag::GLITCH, false },
};
static ImGuiTextFilter trickSearch;
UIWidgets::PushStyleInput(THEME_COLOR);
trickSearch.Draw("Filter (inc,-exc)", 490.0f);
UIWidgets::PopStyleInput();
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) {
ImGui::SameLine();
if (ImGui::Button("Disable All")) {
if (UIWidgets::Button("Disable All", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(250.f, 0.f)))) {
for (int i = 0; i < RT_MAX; i++) {
auto etfound = enabledTricks.find(static_cast<RandomizerTrick>(i));
if (etfound != enabledTricks.end()) {
@ -2291,7 +2339,7 @@ void RandomizerSettingsWindow::DrawElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
ImGui::SameLine();
if (ImGui::Button("Enable All")) {
if (UIWidgets::Button("Enable All", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(250.f, 0.f)))) {
for (int i = 0; i < RT_MAX; i++) {
if (!enabledTricks.count(static_cast<RandomizerTrick>(i))) {
enabledTricks.insert(static_cast<RandomizerTrick>(i));
@ -2334,19 +2382,19 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::TableNextColumn();
window->DC.CurrLineTextBaseOffset = 0.0f;
if (ImGui::Button("Collapse All##disabled")) {
if (UIWidgets::Button("Collapse All##disabled", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.f, 0.f)))) {
for (int i = 0; i < RA_MAX; i++) {
areaTreeDisabled[static_cast<RandomizerArea>(i)] = false;
}
}
ImGui::SameLine();
if (ImGui::Button("Open All##disabled")) {
if (UIWidgets::Button("Open All##disabled", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.f, 0.f)))) {
for (int i = 0; i < RA_MAX; i++) {
areaTreeDisabled[static_cast<RandomizerArea>(i)] = true;
}
}
ImGui::SameLine();
if (ImGui::Button("Enable Visible")) {
if (UIWidgets::Button("Enable Visible", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.f, 0.f)))) {
for (int i = 0; i < RT_MAX; i++) {
auto option = mSettings->GetTrickOption(static_cast<RandomizerTrick>(i));
if (!enabledTricks.count(static_cast<RandomizerTrick>(i)) &&
@ -2387,6 +2435,7 @@ void RandomizerSettingsWindow::DrawElement() {
!enabledTricks.count(rt) && Rando::Tricks::CheckTags(showTag, option.GetTags())) {
ImGui::TreeNodeSetOpen(ImGui::GetID((Rando::Tricks::GetAreaName(option.GetArea()) + "##disabled").c_str()), areaTreeDisabled[option.GetArea()]);
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
UIWidgets::PushStyleButton(THEME_COLOR, ImVec2(7.f, 5.f));
if (ImGui::ArrowButton(std::to_string(rt).c_str(), ImGuiDir_Right)) {
enabledTricks.insert(rt);
std::string enabledTrickString = "";
@ -2397,10 +2446,11 @@ void RandomizerSettingsWindow::DrawElement() {
CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str());
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
Rando::Tricks::DrawTagChips(option.GetTags());
UIWidgets::PopStyleButton();
Rando::Tricks::DrawTagChips(option.GetTags(), option.GetName());
ImGui::SameLine();
ImGui::Text("%s", option.GetName().c_str());
UIWidgets::InsertHelpHoverText(option.GetDescription().c_str());
UIWidgets::Tooltip(option.GetDescription().c_str());
}
}
areaTreeDisabled[area] = true;
@ -2416,19 +2466,19 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::TableNextColumn();
window->DC.CurrLineTextBaseOffset = 0.0f;
if (ImGui::Button("Collapse All##enabled")) {
if (UIWidgets::Button("Collapse All##enabled", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.f, 0.f)))) {
for (int i = 0; i < RA_MAX; i++) {
areaTreeEnabled[static_cast<RandomizerArea>(i)] = false;
}
}
ImGui::SameLine();
if (ImGui::Button("Open All##enabled")) {
if (UIWidgets::Button("Open All##enabled", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.f, 0.f)))) {
for (int i = 0; i < RA_MAX; i++) {
areaTreeEnabled[static_cast<RandomizerArea>(i)] = true;
}
}
ImGui::SameLine();
if (ImGui::Button("Disable Visible")) {
if (UIWidgets::Button("Disable Visible", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.f, 0.f)))) {
for (int i = 0; i < RT_MAX; i++) {
auto option = mSettings->GetTrickOption(static_cast<RandomizerTrick>(i));
if (enabledTricks.count(static_cast<RandomizerTrick>(i)) &&
@ -2473,6 +2523,7 @@ void RandomizerSettingsWindow::DrawElement() {
enabledTricks.count(rt) && Rando::Tricks::CheckTags(showTag, option.GetTags())) {
ImGui::TreeNodeSetOpen(ImGui::GetID((Rando::Tricks::GetAreaName(option.GetArea()) + "##enabled").c_str()), areaTreeEnabled[option.GetArea()]);
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
UIWidgets::PushStyleButton(THEME_COLOR, ImVec2(7.f, 5.f));
if (ImGui::ArrowButton(std::to_string(rt).c_str(), ImGuiDir_Left)) {
enabledTricks.erase(rt);
std::string enabledTrickString = "";
@ -2487,10 +2538,11 @@ void RandomizerSettingsWindow::DrawElement() {
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
Rando::Tricks::DrawTagChips(option.GetTags());
UIWidgets::PopStyleButton();
Rando::Tricks::DrawTagChips(option.GetTags(), option.GetName());
ImGui::SameLine();
ImGui::Text("%s", option.GetName().c_str());
UIWidgets::InsertHelpHoverText(option.GetDescription().c_str());
UIWidgets::Tooltip(option.GetDescription().c_str());
}
}
areaTreeEnabled[area] = true;
@ -2532,12 +2584,10 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::EndTabBar();
}
UIWidgets::PopStyleTabs();
ImGui::EndDisabled();
if (disableEditingRandoSettings) {
UIWidgets::ReEnableComponent("");
}
ImGui::EndDisabled();
}
void RandomizerSettingsWindow::UpdateElement() {
@ -2698,10 +2748,10 @@ CustomMessage Randomizer::GetMapGetItemMessageWithHint(GetItemEntry itemEntry) {
}
template<size_t N>
void CreateGetItemMessages(const std::array<GetItemMessage, N>* messageEntries) {
void CreateGetItemMessages(const std::array<GetItemMessage, N>& messageEntries) {
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
customMessageManager->AddCustomMessageTable(Randomizer::getItemMessageTableID);
for (const GetItemMessage& messageEntry : *messageEntries) {
for (const GetItemMessage& messageEntry : messageEntries) {
customMessageManager->CreateGetItemMessage(
Randomizer::getItemMessageTableID, messageEntry.giid, messageEntry.iid,
CustomMessage(messageEntry.english, messageEntry.german, messageEntry.french, TEXTBOX_TYPE_BLUE,
@ -3418,144 +3468,140 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE(RG_GUARD_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gGuard House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus der Wachen%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison des Gardes%w!"),
"Vous obtenez la %rClé %wde la&%gMaison des Gardes%w!"),
GIMESSAGE(RG_MARKET_BAZAAR_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gMarket Bazaar%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar des Marktes%w!",
"Vous obtenez une %rPetite Clé %w&du %gMarché%w!"),
"Vous obtenez la %rClé %wdu %gBazar&de la Place du Marché%w!"),
GIMESSAGE(RG_MARKET_POTION_SHOP_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gMarket Potion Shop%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden des Marktes%w!",
"Vous obtenez une %rPetite Clé %w&du %gMarché%w!"),
"Vous obtenez la %rClé %wde la&%gPlace du Marché%w!"),
GIMESSAGE(RG_MASK_SHOP_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gMask Shop%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %gMaskenladen%w!",
"Vous obtenez une %rPetite Clé %w&du %gMagasin de Masques%w!"),
"Vous obtenez la %rClé %wde la&%gFoire aux Masques%w!"),
GIMESSAGE(RG_MARKET_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gMarket Shooting Gallery%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude des Marktes%w!",
"Vous obtenez une %rPetite Clé %w&du %gStand de Tir%w!"),
"Vous obtenez la %rClé %wdu %gStand de&Tir de la Place du Marché%w!"),
GIMESSAGE(RG_BOMBCHU_BOWLING_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gBombchu Bowling Alley%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für die %gMinenbowlingbahn%w!",
"Vous obtenez une %rPetite Clé %w&du %gBowling Bombchu%w!"),
"Vous obtenez la %rClé %wdu %gBowling&Teigneux%w!"),
GIMESSAGE(RG_TREASURE_CHEST_GAME_BUILDING_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gTreasure Chest Game Building%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Schatzkisten-Pokers%w!",
"Vous obtenez une %rPetite Clé %w&du %gJeu de la Chasse au Trésor%w!"),
"Vous obtenez la %rClé %wdu %gJeu de la&Chasse au Trésor%w!"),
GIMESSAGE(RG_BOMBCHU_SHOP_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gBombchu Shop%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %gKrabbelminenladen%w!",
"Vous obtenez une %rPetite Clé %w&du %gMagasin de Bombchu%w!"),
"Vous obtenez la %rClé %wdu %gMagasin&de Missiles%w!"),
GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to&%gRichard's House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison de Richard%w!"),
GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to&%gRichard's House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison de Richard%w!"),
"Vous obtenez la %rClé %wde la %gMaison&de Kiki%w!"),
GIMESSAGE(RG_ALLEY_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to&the %gAlley House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus in der Gasse%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison de la Ruelle%w!"),
"Vous obtenez la %rClé %wde la %gMaison&de la Ruelle%w!"),
GIMESSAGE(RG_KAK_BAZAAR_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gKakariko Bazaar%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar von Kakariko%w!",
"Vous obtenez une %rPetite Clé %w&du %gMarché de Cocorico%w!"),
"Vous obtenez la %rClé %wdu %gBazar&de Cocorico%w!"),
GIMESSAGE(RG_KAK_POTION_SHOP_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gKakariko Potion Shop%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden von Kakariko%w!",
"Vous obtenez une %rPetite Clé %w&du %gMagasin de Potions de Cocorico%w!"),
"Vous obtenez la %rClé %wdu %gMagasin de&Potions de Cocorico%w!"),
GIMESSAGE(RG_BOSS_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gBoss's House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Chefs%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison du Boss%w!"),
"Vous obtenez la %rClé %wde la %gMaison&du chef des ouvriers%w!"),
GIMESSAGE(RG_GRANNYS_POTION_SHOP_KEY, ITEM_KEY_SMALL,
"You found the key to&%gGranny's Potion Shop%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für %gAsas Hexenladen%w!",
"Vous obtenez une %rPetite Clé %w&du %gMagasin de Potions de Grand-mère%w!"),
"Vous obtenez la %rClé %wde&l'%gApothicaire%w!"),
GIMESSAGE(RG_SKULLTULA_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gSkulltula House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gSkulltula-Haus%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison des Skulltulas%w!"),
"Vous obtenez la %rClé %wde la %gMaison&des Araignées%w!"),
GIMESSAGE(RG_IMPAS_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to&%gImpa's House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Impa%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison d'Impa%w!"),
"Vous obtenez la %rClé %wde la %gMaison&d'Impa%w!"),
GIMESSAGE(RG_WINDMILL_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gWindmill%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für die %gWindmühle%w!",
"Vous obtenez une %rPetite Clé %w&du %gMoulin à Vent%w!"),
"Vous obtenez la %rClé %w du %gMoulin%w!"),
GIMESSAGE(RG_KAK_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gKakariko Shooting Gallery%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude von Kakariko%w!",
"Vous obtenez une %rPetite Clé %w&du %gStand de Tir de Cocorico%w!"),
"Vous obtenez la %rClé %w du %gStand de&Tir de Cocorico%w!"),
GIMESSAGE(RG_DAMPES_HUT_KEY, ITEM_KEY_SMALL,
"You found the key to&%gDampe's Hut%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für die %gHütte von Boris%w!",
"Vous obtenez une %rPetite Clé %w&du %gChalet de Dampe%w!"),
"Vous obtenez la %rClé %wde la %gCabane&d'Igor%w!"),
GIMESSAGE(RG_TALONS_HOUSE_KEY, ITEM_KEY_SMALL,
"You found the key to&%gTalon's House%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Talon%w!",
"Vous obtenez une %rPetite Clé %w&de la %gMaison de Talon%w!"),
"Vous obtenez la %rClé %wde la %gMaison&de Talon%w!"),
GIMESSAGE(RG_STABLES_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gStables%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für die %gStälle%w!",
"Vous obtenez une %rPetite Clé %w&des %gÉcuries%w!"),
"Vous obtenez la %rClé %wdes %gÉcuries%w!"),
GIMESSAGE(RG_BACK_TOWER_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gBack Tower%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %ghinteren Turm%w!",
"Vous obtenez une %rPetite Clé %w&du %gTour Arrière%w!"),
"Vous obtenez la %rClé %wdu %gSilo%w!"),
GIMESSAGE(RG_HYLIA_LAB_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gHylia Laboratory%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für das %gHylia-Labor%w!",
"Vous obtenez une %rPetite Clé %w&du %gLaboratoire d'Hylia%w!"),
"Vous obtenez la %rClé %wdu %gLaboratoire&du Lac Hylia%w!"),
GIMESSAGE(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL,
"You found the key to the&%gFishing Hole%w!",
"You found the key to the&%gPond%w!",
"Du erhältst einen %rkleinen&Schlüssel%w für den %gFischweiher%w!",
"Vous obtenez une %rPetite Clé %w&du %gTrou de Pêche%w!"),
"Vous obtenez la %rClé %wde l'%gÉtang%w!"),
GIMESSAGE(RG_GERUDO_FORTRESS_KEY_RING, ITEM_KEY_SMALL,
"You found a %yThieves Hideout&%wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für das %yDiebesversteck%w!",
"Vous obtenez un trousseau de&clés du %yRepaire des Voleurs%w!"),
"Vous obtenez le trousseau de&clés du %yRepaire des Voleurs%w!"),
GIMESSAGE(RG_FOREST_TEMPLE_KEY_RING, ITEM_KEY_SMALL,
"You found a %gForest Temple&%wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für den %gWaldtempel%w!",
"Vous obtenez un trousseau de&clés du %gTemple de la Forêt%w!"),
"Vous obtenez le trousseau de&clés du %gTemple de la Forêt%w!"),
GIMESSAGE(RG_FIRE_TEMPLE_KEY_RING, ITEM_KEY_SMALL,
"You found a %rFire Temple&%wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für den %rFeuertempel%w!",
"Vous obtenez un trousseau de&clés du %rTemple du Feu%w!"),
"Vous obtenez le trousseau de&clés du %rTemple du Feu%w!"),
GIMESSAGE(RG_WATER_TEMPLE_KEY_RING, ITEM_KEY_SMALL,
"You found a %bWater Temple&%wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für den %bWassertempel%w!",
"Vous obtenez un trousseau de&clés du %bTemple de l'Eau%w!"),
"Vous obtenez le trousseau de&clés du %bTemple de l'Eau%w!"),
GIMESSAGE(RG_SPIRIT_TEMPLE_KEY_RING, ITEM_KEY_SMALL,
"You found a %ySpirit Temple&%wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für den %yGeistertempel%w!",
"Vous obtenez un trousseau de&clés du %yTemple de l'Esprit%w!"),
"Vous obtenez le trousseau de&clés du %yTemple de l'Esprit%w!"),
GIMESSAGE(RG_SHADOW_TEMPLE_KEY_RING, ITEM_KEY_SMALL,
"You found a %pShadow Temple&%wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für den %pSchattentempel%w!",
"Vous obtenez un trousseau de&clés du %pTemple de l'Ombre%w!"),
"Vous obtenez le trousseau de&clés du %pTemple de l'Ombre%w!"),
GIMESSAGE(RG_BOTTOM_OF_THE_WELL_KEY_RING, ITEM_KEY_SMALL,
"You found a %pBottom of the&Well %wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für den %pGrund des Brunnens%w!",
"Vous obtenez un trousseau de&clés du %pPuits%w!"),
"Vous obtenez le trousseau de&clés du %pPuits%w!"),
GIMESSAGE(RG_GERUDO_TRAINING_GROUND_KEY_RING, ITEM_KEY_SMALL,
"You found a %yGerudo Training&Grounds %wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für die %yGerudo-Trainingsarena%w!",
"Vous obtenez un trousseau de&clés du %yGymnase Gerudo%w!"),
"Vous obtenez le trousseau de&clés du %yGymnase Gerudo%w!"),
GIMESSAGE(RG_GANONS_CASTLE_KEY_RING, ITEM_KEY_SMALL,
"You found a %rGanon's Castle&%wKeyring!",
"Du erhältst ein %rSchlüsselbund%w&für %rGanons Schloß%w!",
"Vous obtenez un trousseau de&clés du %rChâteau de Ganon%w!"),
"Vous obtenez le trousseau de&clés du %rChâteau de Ganon%w!"),
GIMESSAGE(RG_TREASURE_GAME_KEY_RING, ITEM_KEY_SMALL,
"You found a %rTreasure Chest Game&%wKeyring!",
"!!!",
"!!!"),
"Vous obtenez le trousseau de&clés du %rJeu de la Chasse au Trésor%w!"),
GIMESSAGE(RG_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS,
"You found the %gForest Temple&%wBoss Key!",
@ -3688,7 +3734,7 @@ void Randomizer::CreateCustomMessages() {
"Vous obtenez l'âme de %bBarinade%w!"),
GIMESSAGE_NO_GERMAN(RG_PHANTOM_GANON_SOUL, ITEM_BIG_POE,
"You found the soul for %gPhantom&Ganon%w!",
"Vous obtenez l'âme de %gGanon Spectral%w!"),
"Vous obtenez l'âme de %gGanon&Spectral%w!"),
GIMESSAGE_NO_GERMAN(RG_VOLVAGIA_SOUL, ITEM_BIG_POE,
"You found the soul for %rVolvagia%w!",
"Vous obtenez l'âme de %rVulcania%w!"),
@ -3697,10 +3743,10 @@ void Randomizer::CreateCustomMessages() {
"Vous obtenez l'âme de %bMorpha%w!"),
GIMESSAGE_NO_GERMAN(RG_BONGO_BONGO_SOUL, ITEM_BIG_POE,
"You found the soul for %pBongo&Bongo%w!",
"Vous obtenez l'âme de %pBongo Bongo%w!"),
"Vous obtenez l'âme de %pBongo&Bongo%w!"),
GIMESSAGE_NO_GERMAN(RG_TWINROVA_SOUL, ITEM_BIG_POE,
"You found the soul for %yTwinrova%w!",
"Vous obtenez l'âme du %yDuo Maléfique%w!"),
"Vous obtenez l'âme du %yDuo&Maléfique%w!"),
GIMESSAGE_NO_GERMAN(RG_GANON_SOUL, ITEM_BIG_POE,
"You found the soul for %cGanon%w!",
"Vous obtenez l'âme de %cGanon%w!"),
@ -3708,68 +3754,68 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE(RG_OCARINA_A_BUTTON, ITEM_OCARINA_TIME,
"You got the %b\x9f%r button for the&Ocarina%w! You can now use it&while playing songs!",
"Der %b\x9f%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
"Vous trouvez la %rtouche %b\x9f%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
"Vous obtenez la %rtouche %b\x9f%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
GIMESSAGE(RG_OCARINA_C_LEFT_BUTTON, ITEM_OCARINA_TIME,
"You got the %y\xa7%r button for the&Ocarina%w! You can now use it&while playing songs!",
"Der %y\xa7%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
"Vous trouvez la %rtouche %y\xa7%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
"Vous obtenez la %rtouche %y\xa7%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
GIMESSAGE(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME,
"You got the %y\xa8%r button for the&Ocarina%w! You can now use it&while playing songs!",
"Der %y\xa8%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
"Vous trouvez la %rtouche %y\xa8%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
"Vous obtenez la %rtouche %y\xa8%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
GIMESSAGE(RG_OCARINA_C_UP_BUTTON, ITEM_OCARINA_TIME,
"You got the %y\xa5%r button for the&Ocarina%w! You can now use it&while playing songs!",
"Der %y\xa5%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
"Vous trouvez la %rtouche %y\xa5%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
"Vous obtenez la %rtouche %y\xa5%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
GIMESSAGE(RG_OCARINA_C_DOWN_BUTTON, ITEM_OCARINA_TIME,
"You got the %y\xa6%r button for the&Ocarina%w! You can now use it&while playing songs!",
"Der %y\xa6%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
"Vous trouvez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
"Vous obtenez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
GIMESSAGE_NO_GERMAN(RG_BRONZE_SCALE, ITEM_SCALE_SILVER,
"You got the %rBronze Scale%w!&The power of buoyancy is yours!",
"Vous avez obtenu l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est à vous!"),
"Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"),
GIMESSAGE_NO_GERMAN(RG_FISHING_POLE, ITEM_FISHING_POLE,
"You found a lost %rFishing Pole%w!&Time to hit the pond!",
"Vous avez trouvé une %rCanne à pêche%w perdue!&Il est temps d'aller à l'étang!"),
"Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"),
GIMESSAGE_NO_GERMAN(RG_BOMBCHU_BAG, ITEM_BOMBCHU,
"You found the %rBombchu Bag%w!",
"!!!"),
"Vous obtenez un %rSac de Missiles&Teigneux%w!"),
GIMESSAGE_NO_GERMAN(RG_BOMB_BAG_INF, ITEM_BOMB_BAG_40,
"You got an %rInfinite Bomb Bag%w!&Now you have %yinfinite bombs%w!",
"Vous avez obtenu un %rSac à bombes à l'infini%w!&Vous avez maintenant des %ybombes à l'infini%w!"),
"Vous obtenez un %rSac de Bombes&sans fond%w!&Vous avez maintenant des %ybombes&en quantité illimitée%w!"),
GIMESSAGE_NO_GERMAN(RG_QUIVER_INF, ITEM_QUIVER_50,
"You got an %rInfinite Quiver%w!&Now you have %yinfinite arrows%w!",
"Vous avez obtenu un %rCarquois à l'infini%w!&Vous avez maintenant des %yflèches à l'infini%w!"),
"Vous obtenez un %rCarquois Infini%w!&Vous avez maintenant des %yflèches&de manière illimitée%w!"),
GIMESSAGE_NO_GERMAN(RG_BULLET_BAG_INF, ITEM_BULLET_BAG_50,
"You got an %rInfinite Bullet Bag%w!&Now you have %yinfinite&slingshot seeds%w!",
"Vous avez obtenu un %rSac de Graine à l'infini%w!&Vous avez maintenant des %ygraines de lance-pierres à l'infini%w!"),
"Vous obtenez un %rSac de Graines&sans fond%w!&Vous avez maintenant des %ygraines&de lance-pierres à l'infini%w!"),
GIMESSAGE_NO_GERMAN(RG_STICK_UPGRADE_INF, ITEM_STICK,
"You now have %yinfinite%w %rDeku Sticks%w!",
"Vous avez maintenant des %yBâtons Mojo à l'infini%w!"),
"Vous avez maintenant des %yBâtons&Mojo de manière illimitée%w!"),
GIMESSAGE_NO_GERMAN(RG_NUT_UPGRADE_INF, ITEM_NUT,
"You now have %yinfinite%w %rDeku Nuts%w!",
"Vous avez maintenant des %yNoix Mojo à l'infini%w!"),
"Vous avez maintenant des %yNoix&Mojo de manière illimitée%w!"),
GIMESSAGE_NO_GERMAN(RG_MAGIC_INF, ITEM_MAGIC_LARGE,
"You now have %yinfinite%w %rMagic%w!",
"Vous avez maintenant de la %ymagie à l'infini%w!"),
"Vous avez maintenant une quantité&de %ymagie illimitée%w!"),
GIMESSAGE_NO_GERMAN(RG_BOMBCHU_INF, ITEM_BOMBCHU,
"You now have %yinfinite%w %rBombchus%w!",
"Vous avez maintenant des %Missiles Teigneux à l'infini%w!"),
"Vous avez maintenant des %yMissiles&Teigneux en quantité illimités%w!"),
GIMESSAGE_NO_GERMAN(RG_WALLET_INF, ITEM_WALLET_GIANT,
"You now have %yinfinite%w %rmoney%w!",
"Vous avez maintenant de l'%yargent à l'infini%w!"),
"Vous avez maintenant des %yRubis en& quantité illimitée%w!"),
GIMESSAGE_NO_GERMAN(RG_SKELETON_KEY, ITEM_KEY_SMALL,
"You found the %rSkeleton Key%w!",
"Vous avez trouvé la %rClé Squelette%w!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_STICK_BAG, ITEM_STICK,
"You found the %rDeku Stick Bag%w!&You can now hold deku sticks!",
"Vous avez trouvé le %rSac de Bâtons Mojo%w!&Vous pouvez maintenant porter des Bâtons Mojo!"),
"Vous avez trouvé le %rSac de Bâtons&Mojo%w!&Vous pouvez maintenant porter des&Bâtons Mojo!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_NUT_BAG, ITEM_NUT,
"You found the %rDeku Nut Bag%w!&You can now hold deku nuts!",
"Vous avez trouvé le %rSac de Noix Mojo%w!&Vous pouvez maintenant porter des Noix Mojo!"),
"Vous avez trouvé le %rSac de Noix& Mojo%w!&Vous pouvez maintenant porter des&Noix Mojo!"),
}};
CreateGetItemMessages(&getItemMessages);
CreateGetItemMessages(getItemMessages);
CreateRupeeMessages();
CreateTriforcePieceMessages();
CreateNaviRandoMessages();

View file

@ -1013,7 +1013,6 @@ typedef enum {
RR_GANONS_CASTLE_SHADOW_TRIAL,
RR_GANONS_CASTLE_SPIRIT_TRIAL,
RR_GANONS_CASTLE_LIGHT_TRIAL,
RR_GANONS_CASTLE_TOWER,
RR_GANONS_CASTLE_MQ_LOBBY,
RR_GANONS_CASTLE_MQ_MAIN,
@ -1042,6 +1041,7 @@ typedef enum {
RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_BACK,
RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_FINAL_ROOM,
RR_GANONS_TOWER_ENTRYWAY,
RR_GANONS_TOWER_FLOOR_1,
RR_GANONS_TOWER_FLOOR_2,
RR_GANONS_TOWER_FLOOR_3,
@ -3393,6 +3393,8 @@ typedef enum {
RG_HOOKSHOT,
RG_LONGSHOT,
RG_SCARECROW,
//Overworld keys
RG_GUARD_HOUSE_KEY,
RG_MARKET_BAZAAR_KEY,
RG_MARKET_POTION_SHOP_KEY,
@ -5450,7 +5452,6 @@ typedef enum {
RO_GANON_BOSS_KEY_LACS_DUNGEONS,
RO_GANON_BOSS_KEY_LACS_TOKENS,
RO_GANON_BOSS_KEY_KAK_TOKENS,
RO_GANON_BOSS_KEY_TRIFORCE_HUNT,
} RandoOptionGanonsBossKey;
typedef enum {

View file

@ -7,6 +7,7 @@
#include "soh/SaveManager.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "dungeon.h"
#include "location_access.h"
@ -482,9 +483,13 @@ void CheckTrackerLoadGame(int32_t fileNum) {
for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) {
if (!IsAreaSpoiled(static_cast<RandomizerCheckArea>(i)) && (RandomizerCheckObjects::AreaIsOverworld(static_cast<RandomizerCheckArea>(i)) || !IS_RANDO ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_NONE ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SELECTION ||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SELECTION &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(static_cast<RandomizerSettingKey>(RSK_MQ_DEKU_TREE + (i - RCAREA_DEKU_TREE))) != RO_MQ_SET_RANDOM) ||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_SET) == RO_GENERIC_ON &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(static_cast<RandomizerSettingKey>(RSK_MQ_DEKU_TREE + (i - RCAREA_DEKU_TREE))) != RO_MQ_SET_RANDOM) ||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SET_NUMBER &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12))) {
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12 ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 0)))) {
SetAreaSpoiled(static_cast<RandomizerCheckArea>(i));
}
}
@ -821,6 +826,7 @@ void LoadFile() {
SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled, (uint32_t)0);
UpdateAllOrdering();
UpdateAllAreas();
RegionTable_Init();
}
void Teardown() {
@ -844,6 +850,37 @@ void SetAreaSpoiled(RandomizerCheckArea rcArea) {
}
void CheckTrackerWindow::DrawElement() {
Color_Background = CVarGetColor(CVAR_TRACKER_CHECK("BgColor.Value"), Color_Bg_Default);
Color_Area_Incomplete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor.Value"), Color_Main_Default);
Color_Area_Incomplete_Extra = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor.Value"), Color_Area_Incomplete_Extra_Default);
Color_Area_Complete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.MainColor.Value"), Color_Main_Default);
Color_Area_Complete_Extra = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.ExtraColor.Value"), Color_Area_Complete_Extra_Default);
Color_Unchecked_Main = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.MainColor.Value"), Color_Main_Default);
Color_Unchecked_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.ExtraColor.Value"), Color_Unchecked_Extra_Default);
Color_Skipped_Main = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.MainColor.Value"), Color_Main_Default);
Color_Skipped_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor.Value"), Color_Skipped_Extra_Default);
Color_Seen_Main = CVarGetColor(CVAR_TRACKER_CHECK("Seen.MainColor.Value"), Color_Main_Default);
Color_Seen_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Seen.ExtraColor.Value"), Color_Seen_Extra_Default);
Color_Hinted_Main = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.MainColor.Value"), Color_Main_Default);
Color_Hinted_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.ExtraColor.Value"), Color_Hinted_Extra_Default);
Color_Collected_Main = CVarGetColor(CVAR_TRACKER_CHECK("Collected.MainColor.Value"), Color_Main_Default);
Color_Collected_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Collected.ExtraColor.Value"), Color_Collected_Extra_Default);
Color_Scummed_Main = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.MainColor.Value"), Color_Main_Default);
Color_Scummed_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.ExtraColor.Value"), Color_Scummed_Extra_Default);
Color_Saved_Main = CVarGetColor(CVAR_TRACKER_CHECK("Saved.MainColor.Value"), Color_Main_Default);
Color_Saved_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Saved.ExtraColor.Value"), Color_Saved_Extra_Default);
hideUnchecked = CVarGetInteger(CVAR_TRACKER_CHECK("Unchecked.Hide"), 0);
hideScummed = CVarGetInteger(CVAR_TRACKER_CHECK("Scummed.Hide"), 0);
hideSeen = CVarGetInteger(CVAR_TRACKER_CHECK("Seen.Hide"), 0);
hideSkipped = CVarGetInteger(CVAR_TRACKER_CHECK("Skipped.Hide"), 0);
hideSaved = CVarGetInteger(CVAR_TRACKER_CHECK("Saved.Hide"), 0);
hideCollected = CVarGetInteger(CVAR_TRACKER_CHECK("Collected.Hide"), 0);
showHidden = CVarGetInteger(CVAR_TRACKER_CHECK("ShowHidden"), 0);
mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0);
showLogicTooltip = CVarGetInteger(CVAR_TRACKER_CHECK("ShowLogic"), 0);
hideShopUnshuffledChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), 1);
alwaysShowGS = CVarGetInteger(CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), 0);
if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) {
if (CVarGetInteger(CVAR_TRACKER_CHECK("ShowOnlyPaused"), 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) {
return;
@ -863,7 +900,6 @@ void CheckTrackerWindow::DrawElement() {
}
ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver);
BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar);
if (!GameInteractor::IsSaveLoaded() || !initialized) {
@ -892,32 +928,33 @@ void CheckTrackerWindow::DrawElement() {
ImGui::TableNextRow(0, headerHeight);
ImGui::TableNextColumn();
UIWidgets::EnhancementCheckbox(
"Show Hidden Items", CVAR_TRACKER_CHECK("ShowHidden"), false,
"When active, items will show hidden checks by default when updated to this state.");
UIWidgets::CVarCheckbox(
"Show Hidden Items", CVAR_TRACKER_CHECK("ShowHidden"), UIWidgets::CheckboxOptions({{ .tooltip = "When active, items will show hidden checks by default when updated to this state." }})
.Color(THEME_COLOR));
UIWidgets::PaddedSeparator();
if (ImGui::Button("Expand All")) {
if (UIWidgets::Button("Expand All", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
optCollapseAll = false;
optExpandAll = true;
doAreaScroll = true;
}
ImGui::SameLine();
if (ImGui::Button("Collapse All")) {
if (UIWidgets::Button("Collapse All", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
optExpandAll = false;
optCollapseAll = true;
}
ImGui::SameLine();
if (ImGui::Button("Clear")) {
if (UIWidgets::Button("Clear", UIWidgets::ButtonOptions({{ .tooltip = "Clear the search field" }}).Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
checkSearch.Clear();
UpdateFilters();
doAreaScroll = true;
}
UIWidgets::Tooltip("Clear the search field");
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (checkSearch.Draw()) {
UpdateFilters();
}
UIWidgets::PopStyleCombobox();
UIWidgets::PaddedSeparator();
ImGui::Separator();
ImGui::Text("Total Checks: %d / %d", totalChecksGotten, totalChecks);
@ -946,16 +983,17 @@ void CheckTrackerWindow::DrawElement() {
bool doingCollapseOrExpand = optExpandAll || optCollapseAll;
bool isThisAreaSpoiled;
RandomizerCheckArea lastArea = RCAREA_INVALID;
Color_RGBA8 areaCompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.MainColor"), Color_Main_Default);
Color_RGBA8 areaIncompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), Color_Main_Default);
Color_RGBA8 extraCompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default);
Color_RGBA8 extraIncompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default);
Color_RGBA8 areaCompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.MainColor.Value"), Color_Main_Default);
Color_RGBA8 areaIncompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor.Value"), Color_Main_Default);
Color_RGBA8 extraCompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.ExtraColor.Value"), Color_Area_Complete_Extra_Default);
Color_RGBA8 extraIncompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor.Value"), Color_Area_Incomplete_Extra_Default);
Color_RGBA8 mainColor;
Color_RGBA8 extraColor;
std::string stemp;
bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f));
for (auto& [rcArea, checks] : checksByArea) {
RandomizerCheckArea thisArea = currentArea;
@ -1039,6 +1077,7 @@ void CheckTrackerWindow::DrawElement() {
}
}
}
ImGui::PopStyleVar();
ImGui::EndTable(); //Checks Lead-out
ImGui::EndTable(); //Quick Options Lead-out
@ -1099,7 +1138,7 @@ void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flag
windowFlags |= ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar;
if (!CVarGetInteger(CVAR_TRACKER_CHECK("Draggable"), 0)) {
if (!CVarGetInteger(CVAR_TRACKER_CHECK("Draggable"), 1)) {
windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove;
}
}
@ -1468,54 +1507,54 @@ void DrawLocation(RandomizerCheck rc) {
}
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? Color_Collected_Extra_Default
? Color_Collected_Extra
: Color_Collected_Main;
extraColor = Color_Collected_Extra_Default;
extraColor = Color_Collected_Extra;
} else if (status == RCSHOW_SAVED) {
if (!showHidden && hideSaved) {
return;
}
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? Color_Saved_Extra_Default
? Color_Saved_Extra
: Color_Saved_Main;
extraColor = Color_Saved_Extra_Default;
extraColor = Color_Saved_Extra;
} else if (skipped) {
if (!showHidden && hideSkipped) {
return;
}
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? Color_Skipped_Extra_Default
? Color_Skipped_Extra
: Color_Skipped_Main;
extraColor = Color_Skipped_Extra_Default;
extraColor = Color_Skipped_Extra;
} else if (status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED) {
if (!showHidden && hideSeen) {
return;
}
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? Color_Seen_Extra_Default
? Color_Seen_Extra
: Color_Seen_Main;
extraColor = Color_Seen_Extra_Default;
extraColor = Color_Seen_Extra;
} else if (status == RCSHOW_SCUMMED) {
if (!showHidden && hideScummed) {
return;
}
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? Color_Scummed_Extra_Default
? Color_Scummed_Extra
: Color_Scummed_Main;
extraColor = Color_Scummed_Extra_Default;
extraColor = Color_Scummed_Extra;
} else if (status == RCSHOW_UNCHECKED) {
if (!showHidden && hideUnchecked) {
return;
}
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? Color_Unchecked_Extra_Default
? Color_Unchecked_Extra
: Color_Unchecked_Main;
extraColor = Color_Unchecked_Extra_Default;
extraColor = Color_Unchecked_Extra;
}
//Main Text
@ -1530,8 +1569,10 @@ void DrawLocation(RandomizerCheck rc) {
}
// Draw button - for Skipped/Seen/Scummed/Unchecked only
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {4.0f, 3.0f});
float sz = ImGui::GetFrameHeight();
if (status == RCSHOW_UNCHECKED || status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED || status == RCSHOW_SCUMMED || skipped) {
if (UIWidgets::StateButton(std::to_string(rc).c_str(), skipped ? ICON_FA_PLUS : ICON_FA_TIMES)) {
if (UIWidgets::StateButton(std::to_string(rc).c_str(), skipped ? ICON_FA_PLUS : ICON_FA_TIMES, ImVec2(sz, sz), UIWidgets::ButtonOptions().Color(THEME_COLOR))) {
if (skipped) {
OTRGlobals::Instance->gRandoContext->GetItemLocation(rc)->SetIsSkipped(false);
areaChecksGotten[loc->GetArea()]--;
@ -1546,8 +1587,10 @@ void DrawLocation(RandomizerCheck rc) {
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
}
} else {
ImGui::Dummy(ImVec2(20.0f, 10.0f));
ImGui::Dummy(ImVec2(sz, sz));
}
ImGui::PopStyleVar();
ImGui::SameLine();
//Draw
@ -1621,7 +1664,7 @@ void DrawLocation(RandomizerCheck rc) {
if (locationInRegion.GetLocation() == rc) {
std::string conditionStr = locationInRegion.GetConditionStr();
if (conditionStr != "true") {
UIWidgets::InsertHelpHoverText(conditionStr);
UIWidgets::Tooltip(conditionStr.c_str());
}
return;
}
@ -1645,7 +1688,7 @@ int hue = 0;
void RainbowTick() {
float freqHue = hue * 2 * M_PI / (360 * CVarGetFloat(CVAR_COSMETIC("RainbowSpeed"), 0.6f));
for (auto& cvar : rainbowCVars) {
if (CVarGetInteger((cvar + "RBM").c_str(), 0) == 0) {
if (CVarGetInteger((cvar + ".Rainbow").c_str(), 0) == 0) {
continue;
}
@ -1655,7 +1698,7 @@ void RainbowTick() {
newColor.b = sin(freqHue + (4 * M_PI / 3)) * 127 + 128;
newColor.a = 255;
CVarSetColor(cvar.c_str(), newColor);
CVarSetColor((cvar + ".Value").c_str(), newColor);
}
hue++;
@ -1664,46 +1707,33 @@ void RainbowTick() {
void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName, const char* cvarExtraName,
Color_RGBA8& main_color, Color_RGBA8& extra_color, Color_RGBA8& main_default_color,
Color_RGBA8& extra_default_color, const char* cvarHideName, const char* tooltip) {
Color_RGBA8& extra_default_color, const char* cvarHideName, const char* tooltip, UIWidgets::Colors theme) {
Color_RGBA8 cvarMainColor = CVarGetColor(cvarMainName, main_default_color);
Color_RGBA8 cvarExtraColor = CVarGetColor(cvarExtraName, extra_default_color);
main_color = cvarMainColor;
extra_color = cvarExtraColor;
UIWidgets::PushStyleCombobox(theme);
if (ImGui::CollapsingHeader(text)) {
if (*cvarHideName != '\0') {
std::string label = cvarHideName;
label += "##Hidden";
ImGui::PushID(label.c_str());
UIWidgets::EnhancementCheckbox("Hidden", cvarHideName, false,
"When active, checks will hide by default when updated to this state. Can "
"be overriden with the \"Show Hidden Items\" option.");
UIWidgets::CVarCheckbox("Hidden", cvarHideName,
UIWidgets::CheckboxOptions({{ .tooltip = "When active, checks will hide by default when updated to this state. Can "
"be overriden with the \"Show Hidden Items\" option." }}).Color(theme));
ImGui::PopID();
}
if (ImGui::BeginTable(text, 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV | ImGuiTableFlags_Hideable)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
if (UIWidgets::EnhancementColor("Check", cvarMainName,
ImVec4(main_color.r, main_color.g, main_color.b, main_color.a),
ImVec4(main_default_color.r, main_default_color.g, main_default_color.b, main_default_color.a)))
{
std::string mainLabel = "Name##" + std::string(cvarMainName);
if (UIWidgets::CVarColorPicker(mainLabel.c_str(), cvarMainName, main_default_color, false,
UIWidgets::ColorPickerRandomButton | UIWidgets::ColorPickerResetButton | UIWidgets::ColorPickerRainbowCheck, theme)) {
main_color = CVarGetColor(cvarMainName, main_default_color);
};
ImGui::PopItemWidth();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
if (UIWidgets::EnhancementColor("Details", cvarExtraName,
ImVec4(extra_color.r, extra_color.g, extra_color.b, extra_color.a),
ImVec4(extra_default_color.r, extra_default_color.g, extra_default_color.b, extra_default_color.a)))
{
extra_color = CVarGetColor(cvarExtraName, extra_default_color);
}
ImGui::PopItemWidth();
ImGui::EndTable();
std::string extraLabel = "Details##" + std::string(cvarExtraName);
if (UIWidgets::CVarColorPicker(extraLabel.c_str(), cvarExtraName, extra_default_color, false,
UIWidgets::ColorPickerRandomButton | UIWidgets::ColorPickerResetButton | UIWidgets::ColorPickerRainbowCheck, theme)) {
extra_color = CVarGetColor(cvarExtraName, extra_default_color);
}
}
if (tooltip != NULL && strlen(tooltip) != 0) {
@ -1711,6 +1741,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName,
ImGui::Text(" ?");
UIWidgets::Tooltip(tooltip);
}
UIWidgets::PopStyleCombobox();
}
void CheckTrackerWindow::Draw() {
@ -1722,72 +1753,81 @@ void CheckTrackerWindow::Draw() {
SyncVisibilityConsoleVariable();
}
static const char* windowType[] = { "Floating", "Window" };
static const char* displayType[] = { "Always", "Combo Button Hold" };
static const char* buttonStrings[] = { "A Button", "B Button", "C-Up", "C-Down", "C-Left", "C-Right", "L Button",
"Z Button", "R Button", "Start", "D-Up", "D-Down", "D-Left", "D-Right" };
static std::unordered_map<int32_t, const char*> windowType = {{ TRACKER_WINDOW_FLOATING, "Floating" }, { TRACKER_WINDOW_WINDOW, "Window" }};
static std::unordered_map<int32_t, const char*> displayType = {{ 0, "Always" }, { 1, "Combo Button Hold" }};
static std::unordered_map<int32_t, const char*> buttonStrings = {
{ TRACKER_COMBO_BUTTON_A, "A Button" }, { TRACKER_COMBO_BUTTON_B, "B Button" }, { TRACKER_COMBO_BUTTON_C_UP, "C-Up" },
{ TRACKER_COMBO_BUTTON_C_DOWN, "C-Down" }, { TRACKER_COMBO_BUTTON_C_LEFT, "C-Left" }, { TRACKER_COMBO_BUTTON_C_RIGHT, "C-Right" },
{ TRACKER_COMBO_BUTTON_L, "L Button" }, { TRACKER_COMBO_BUTTON_Z, "Z Button" }, { TRACKER_COMBO_BUTTON_R, "R Button" },
{ TRACKER_COMBO_BUTTON_START, "Start" }, { TRACKER_COMBO_BUTTON_D_UP, "D-Up" }, { TRACKER_COMBO_BUTTON_D_DOWN, "D-Down" },
{ TRACKER_COMBO_BUTTON_D_LEFT, "D-Left" }, { TRACKER_COMBO_BUTTON_D_RIGHT, "D-Right" }};
void CheckTrackerSettingsWindow::DrawElement() {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
ImGui::BeginTable("CheckTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV);
if (ImGui::BeginTable("CheckTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) {
ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::TableSetupColumn("Section settings", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
if (UIWidgets::EnhancementColor("BG Color", CVAR_TRACKER_CHECK("BgColor"),
ImVec4(Color_Background.r, Color_Background.g, Color_Background.b, Color_Background.a),
ImVec4(Color_Bg_Default.r, Color_Bg_Default.g, Color_Bg_Default.b, Color_Bg_Default.a),
false, true))
{
Color_Background = CVarGetColor(CVAR_TRACKER_CHECK("BgColor"), Color_Bg_Default);
}
UIWidgets::CVarColorPicker("BG Color", CVAR_TRACKER_CHECK("BgColor"), Color_Bg_Default, true,
UIWidgets::ColorPickerResetButton | UIWidgets::ColorPickerRandomButton, THEME_COLOR);
ImGui::PopItemWidth();
UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", CVAR_TRACKER_CHECK("WindowType"), windowType, TRACKER_WINDOW_WINDOW);
UIWidgets::CVarCombobox("Window Type", CVAR_TRACKER_CHECK("WindowType"), windowType,
UIWidgets::ComboboxOptions().LabelPosition(UIWidgets::LabelPositions::Far).ComponentAlignment(UIWidgets::ComponentAlignments::Right)
.Color(THEME_COLOR).DefaultIndex(TRACKER_WINDOW_WINDOW));
if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) {
UIWidgets::EnhancementCheckbox("Enable Dragging", CVAR_TRACKER_CHECK("Draggable"));
UIWidgets::EnhancementCheckbox("Only enable while paused", CVAR_TRACKER_CHECK("ShowOnlyPaused"));
UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", CVAR_TRACKER_CHECK("DisplayType"), displayType, 0);
UIWidgets::CVarCheckbox("Enable Dragging", CVAR_TRACKER_CHECK("Draggable"), UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Only enable while paused", CVAR_TRACKER_CHECK("ShowOnlyPaused"), UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCombobox("Display Mode", CVAR_TRACKER_CHECK("DisplayType"), displayType,
UIWidgets::ComboboxOptions().LabelPosition(UIWidgets::LabelPositions::Far).ComponentAlignment(UIWidgets::ComponentAlignments::Right)
.Color(THEME_COLOR).DefaultIndex(0));
if (CVarGetInteger(CVAR_TRACKER_CHECK("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) {
UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", CVAR_TRACKER_CHECK("ComboButton1"), buttonStrings, TRACKER_COMBO_BUTTON_L);
UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", CVAR_TRACKER_CHECK("ComboButton2"), buttonStrings, TRACKER_COMBO_BUTTON_R);
UIWidgets::CVarCombobox("Combo Button 1", CVAR_TRACKER_CHECK("ComboButton1"), buttonStrings,
UIWidgets::ComboboxOptions().LabelPosition(UIWidgets::LabelPositions::Far).ComponentAlignment(UIWidgets::ComponentAlignments::Right)
.Color(THEME_COLOR).DefaultIndex(TRACKER_COMBO_BUTTON_L));
UIWidgets::CVarCombobox("Combo Button 2", CVAR_TRACKER_CHECK("ComboButton2"), buttonStrings,
UIWidgets::ComboboxOptions().LabelPosition(UIWidgets::LabelPositions::Far).ComponentAlignment(UIWidgets::ComponentAlignments::Right)
.Color(THEME_COLOR).DefaultIndex(TRACKER_COMBO_BUTTON_L));
}
}
UIWidgets::EnhancementCheckbox("Vanilla/MQ Dungeon Spoilers", CVAR_TRACKER_CHECK("MQSpoilers"));
UIWidgets::Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. Otherwise, Vanilla/MQ dungeon locations must be unlocked.");
if (UIWidgets::EnhancementCheckbox("Hide unshuffled shop item checks", CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), false, "", UIWidgets::CheckboxGraphics::Cross, false)) {
UIWidgets::CVarCheckbox("Vanilla/MQ Dungeon Spoilers", CVAR_TRACKER_CHECK("MQSpoilers"), UIWidgets::CheckboxOptions()
.Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. Otherwise, Vanilla/MQ dungeon locations must be unlocked.").Color(THEME_COLOR));
if (UIWidgets::CVarCheckbox("Hide unshuffled shop item checks", CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"),
UIWidgets::CheckboxOptions().Tooltip("If enabled, will prevent the tracker from displaying slots with non-shop-item shuffles.").Color(THEME_COLOR))) {
hideShopUnshuffledChecks = !hideShopUnshuffledChecks;
UpdateFilters();
}
UIWidgets::Tooltip("If enabled, will prevent the tracker from displaying slots with non-shop-item shuffles.");
if (UIWidgets::EnhancementCheckbox("Always show gold skulltulas", CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), false, "")) {
if (UIWidgets::CVarCheckbox("Always show gold skulltulas", CVAR_TRACKER_CHECK("AlwaysShowGSLocs"),
UIWidgets::CheckboxOptions().Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings.").Color(THEME_COLOR))) {
alwaysShowGS = !alwaysShowGS;
UpdateFilters();
}
UIWidgets::Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings.");
UIWidgets::EnhancementCheckbox("Show Logic", "gCheckTrackerOptionShowLogic");
UIWidgets::Tooltip("If enabled, will show a check's logic when hovering over it.");
UIWidgets::CVarCheckbox("Show Logic", CVAR_TRACKER_CHECK("ShowLogic"),
UIWidgets::CheckboxOptions().Tooltip("If enabled, will show a check's logic when hovering over it.").Color(THEME_COLOR));
// Filtering settings
UIWidgets::PaddedSeparator();
UIWidgets::EnhancementCheckbox("Filter Empty Areas", CVAR_TRACKER_CHECK("HideFilteredAreas"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true);
UIWidgets::Tooltip("If enabled, will hide area headers that have no locations matching filter");
UIWidgets::CVarCheckbox("Filter Empty Areas", CVAR_TRACKER_CHECK("HideFilteredAreas"),
UIWidgets::CheckboxOptions().Tooltip("If enabled, will hide area headers that have no locations matching filter").Color(THEME_COLOR).DefaultValue(true));
ImGui::TableNextColumn();
CheckTracker::ImGuiDrawTwoColorPickerSection("Area Incomplete", CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Main, Color_Area_Incomplete_Extra, Color_Main_Default, Color_Area_Incomplete_Extra_Default, CVAR_TRACKER_CHECK("AreaIncomplete.Hide"), "");
CheckTracker::ImGuiDrawTwoColorPickerSection("Area Complete", CVAR_TRACKER_CHECK("AreaComplete.MainColor"), CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), Color_Area_Complete_Main, Color_Area_Complete_Extra, Color_Main_Default, Color_Area_Complete_Extra_Default, CVAR_TRACKER_CHECK("AreaComplete.Hide"), "");
CheckTracker::ImGuiDrawTwoColorPickerSection("Unchecked", CVAR_TRACKER_CHECK("Unchecked.MainColor"), CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Main, Color_Unchecked_Extra, Color_Main_Default, Color_Unchecked_Extra_Default, CVAR_TRACKER_CHECK("Unchecked.Hide"), "Checks you have not interacted with at all.");
CheckTracker::ImGuiDrawTwoColorPickerSection("Skipped", CVAR_TRACKER_CHECK("Skipped.MainColor"), CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Main, Color_Skipped_Extra, Color_Main_Default, Color_Skipped_Extra_Default, CVAR_TRACKER_CHECK("Skipped.Hide"), "");
CheckTracker::ImGuiDrawTwoColorPickerSection("Seen", CVAR_TRACKER_CHECK("Seen.MainColor"), CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Main, Color_Seen_Extra, Color_Main_Default, Color_Seen_Extra_Default, CVAR_TRACKER_CHECK("Seen.Hide"), "Used for shops. Shows item names for shop slots when walking in, and prices when highlighting them in buy mode.");
CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", CVAR_TRACKER_CHECK("Scummed.MainColor"), CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, CVAR_TRACKER_CHECK("Scummed.Hide"), "Checks you collect, but then reload before saving so you no longer have them.");
//CheckTracker::ImGuiDrawTwoColorPickerSection("Hinted (WIP)", CVAR_TRACKER_CHECK("Hinted.MainColor"), CVAR_TRACKER_CHECK("Hinted.ExtraColor"), Color_Hinted_Main, Color_Hinted_Extra, Color_Main_Default, Color_Hinted_Extra_Default, CVAR_TRACKER_CHECK("Hinted.Hide"), "");
CheckTracker::ImGuiDrawTwoColorPickerSection("Collected", CVAR_TRACKER_CHECK("Collected.MainColor"), CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Main, Color_Collected_Extra, Color_Main_Default, Color_Collected_Extra_Default, CVAR_TRACKER_CHECK("Collected.Hide"), "Checks you have collected without saving or reloading yet.");
CheckTracker::ImGuiDrawTwoColorPickerSection("Saved", CVAR_TRACKER_CHECK("Saved.MainColor"), CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Main, Color_Saved_Extra, Color_Main_Default, Color_Saved_Extra_Default, CVAR_TRACKER_CHECK("Saved.Hide"), "Checks that you saved the game while having collected.");
CheckTracker::ImGuiDrawTwoColorPickerSection("Area Incomplete", CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Main, Color_Area_Incomplete_Extra, Color_Main_Default, Color_Area_Incomplete_Extra_Default, CVAR_TRACKER_CHECK("AreaIncomplete.Hide"), "", THEME_COLOR);
CheckTracker::ImGuiDrawTwoColorPickerSection("Area Complete", CVAR_TRACKER_CHECK("AreaComplete.MainColor"), CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), Color_Area_Complete_Main, Color_Area_Complete_Extra, Color_Main_Default, Color_Area_Complete_Extra_Default, CVAR_TRACKER_CHECK("AreaComplete.Hide"), "", THEME_COLOR);
CheckTracker::ImGuiDrawTwoColorPickerSection("Unchecked", CVAR_TRACKER_CHECK("Unchecked.MainColor"), CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Main, Color_Unchecked_Extra, Color_Main_Default, Color_Unchecked_Extra_Default, CVAR_TRACKER_CHECK("Unchecked.Hide"), "Checks you have not interacted with at all.", THEME_COLOR);
CheckTracker::ImGuiDrawTwoColorPickerSection("Skipped", CVAR_TRACKER_CHECK("Skipped.MainColor"), CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Main, Color_Skipped_Extra, Color_Main_Default, Color_Skipped_Extra_Default, CVAR_TRACKER_CHECK("Skipped.Hide"), "", THEME_COLOR);
CheckTracker::ImGuiDrawTwoColorPickerSection("Seen", CVAR_TRACKER_CHECK("Seen.MainColor"), CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Main, Color_Seen_Extra, Color_Main_Default, Color_Seen_Extra_Default, CVAR_TRACKER_CHECK("Seen.Hide"), "Used for shops. Shows item names for shop slots when walking in, and prices when highlighting them in buy mode.", THEME_COLOR);
CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", CVAR_TRACKER_CHECK("Scummed.MainColor"), CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, CVAR_TRACKER_CHECK("Scummed.Hide"), "Checks you collect, but then reload before saving so you no longer have them.", THEME_COLOR);
//CheckTracker::ImGuiDrawTwoColorPickerSection("Hinted (WIP)", CVAR_TRACKER_CHECK("Hinted.MainColor"), CVAR_TRACKER_CHECK("Hinted.ExtraColor"), Color_Hinted_Main, Color_Hinted_Extra, Color_Main_Default, Color_Hinted_Extra_Default, CVAR_TRACKER_CHECK("Hinted.Hide"), "", THEME_COLOR);
CheckTracker::ImGuiDrawTwoColorPickerSection("Collected", CVAR_TRACKER_CHECK("Collected.MainColor"), CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Main, Color_Collected_Extra, Color_Main_Default, Color_Collected_Extra_Default, CVAR_TRACKER_CHECK("Collected.Hide"), "Checks you have collected without saving or reloading yet.", THEME_COLOR);
CheckTracker::ImGuiDrawTwoColorPickerSection("Saved", CVAR_TRACKER_CHECK("Saved.MainColor"), CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Main, Color_Saved_Extra, Color_Main_Default, Color_Saved_Extra_Default, CVAR_TRACKER_CHECK("Saved.Hide"), "Checks that you saved the game while having collected.", THEME_COLOR);
ImGui::PopStyleVar(1);
}
ImGui::EndTable();
}
@ -1807,36 +1847,5 @@ void CheckTrackerWindow::InitElement() {
}
void CheckTrackerWindow::UpdateElement() {
Color_Background = CVarGetColor(CVAR_TRACKER_CHECK("BgColor"), Color_Bg_Default);
Color_Area_Incomplete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), Color_Main_Default);
Color_Area_Incomplete_Extra = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default);
Color_Area_Complete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.MainColor"), Color_Main_Default);
Color_Area_Complete_Extra = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default);
Color_Unchecked_Main = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.MainColor"), Color_Main_Default);
Color_Unchecked_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default);
Color_Skipped_Main = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.MainColor"), Color_Main_Default);
Color_Skipped_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Extra_Default);
Color_Seen_Main = CVarGetColor(CVAR_TRACKER_CHECK("Seen.MainColor"), Color_Main_Default);
Color_Seen_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Extra_Default);
Color_Hinted_Main = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.MainColor"), Color_Main_Default);
Color_Hinted_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.ExtraColor"), Color_Hinted_Extra_Default);
Color_Collected_Main = CVarGetColor(CVAR_TRACKER_CHECK("Collected.MainColor"), Color_Main_Default);
Color_Collected_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Extra_Default);
Color_Scummed_Main = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.MainColor"), Color_Main_Default);
Color_Scummed_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Extra_Default);
Color_Saved_Main = CVarGetColor(CVAR_TRACKER_CHECK("Saved.MainColor"), Color_Main_Default);
Color_Saved_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Extra_Default);
hideUnchecked = CVarGetInteger(CVAR_TRACKER_CHECK("Unchecked.Hide"), 0);
hideScummed = CVarGetInteger(CVAR_TRACKER_CHECK("Scummed.Hide"), 0);
hideSeen = CVarGetInteger(CVAR_TRACKER_CHECK("Seen.Hide"), 0);
hideSkipped = CVarGetInteger(CVAR_TRACKER_CHECK("Skipped.Hide"), 0);
hideSaved = CVarGetInteger(CVAR_TRACKER_CHECK("Saved.Hide"), 0);
hideCollected = CVarGetInteger(CVAR_TRACKER_CHECK("Collected.Hide"), 0);
showHidden = CVarGetInteger(CVAR_TRACKER_CHECK("ShowHidden"), 0);
mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0);
showLogicTooltip = CVarGetInteger("gCheckTrackerOptionShowLogic", 0);
hideShopUnshuffledChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), 1);
alwaysShowGS = CVarGetInteger(CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), 0);
}
} // namespace CheckTracker

View file

@ -2,6 +2,7 @@
#include <nlohmann/json.hpp>
#include "randomizerTypes.h"
#include "randomizer_check_objects.h"
#include "soh/SohGui/UIWidgets.hpp"
#include <libultraship/libultraship.h>

View file

@ -201,12 +201,12 @@ void Entrance_Init(void) {
}
// Overwrite grotto related indices
if (originalIndex >= ENTRANCE_GROTTO_EXIT_START) {
if (originalIndex >= ENTRANCE_GROTTO_EXIT_START && originalIndex < ENTRANCE_GROTTO_EXIT_START + NUM_GROTTOS) {
Grotto_SetExitOverride(originalIndex, overrideIndex);
continue;
}
if (originalIndex >= ENTRANCE_GROTTO_LOAD_START && originalIndex < ENTRANCE_GROTTO_EXIT_START) {
if (originalIndex >= ENTRANCE_GROTTO_LOAD_START && originalIndex < ENTRANCE_GROTTO_LOAD_START + NUM_GROTTOS) {
Grotto_SetLoadOverride(originalIndex, overrideIndex);
continue;
}

View file

@ -1,7 +1,7 @@
#include "randomizer_entrance_tracker.h"
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include <map>
#include <string>
@ -659,65 +659,60 @@ void InitEntranceTrackingData() {
}
void EntranceTrackerSettingsWindow::DrawElement() {
if (ImGui::BeginTable("entranceTrackerSettings", 1, ImGuiTableFlags_BordersInnerH)) {
ImGui::TableNextColumn();
UIWidgets::Spacer(0);
ImGui::TextWrapped("The entrance tracker will only track shuffled entrances");
UIWidgets::Spacer(0);
ImGui::TableNextColumn();
if (ImGui::BeginTable("entranceTrackerSubSettings", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("column 1", ImGuiTableColumnFlags_WidthStretch, 150.0f);
ImGui::TableSetupColumn("column 2", ImGuiTableColumnFlags_WidthStretch, 150.0f);
ImGui::TableNextColumn();
ImGui::Text("Sort By");
UIWidgets::EnhancementRadioButton("To", CVAR_TRACKER_ENTRANCE("SortBy"), 0);
UIWidgets::Tooltip("Sort entrances by the original source entrance");
UIWidgets::EnhancementRadioButton("From", CVAR_TRACKER_ENTRANCE("SortBy"), 1);
UIWidgets::Tooltip("Sort entrances by the overrided destination");
UIWidgets::Spacer(2.0f);
UIWidgets::CVarRadioButton("To", CVAR_TRACKER_ENTRANCE("SortBy"), 0,
UIWidgets::RadioButtonsOptions()
.Color(THEME_COLOR).Tooltip("Sort entrances by the original source entrance"));
UIWidgets::CVarRadioButton("From", CVAR_TRACKER_ENTRANCE("SortBy"), 1,
UIWidgets::RadioButtonsOptions()
.Color(THEME_COLOR).Tooltip("Sort entrances by the overrided destination"));
ImGui::Text("List Items");
UIWidgets::PaddedEnhancementCheckbox("Auto scroll", CVAR_TRACKER_ENTRANCE("AutoScroll"), true, false);
UIWidgets::Tooltip("Automatically scroll to the first aviable entrance in the current scene");
UIWidgets::PaddedEnhancementCheckbox("Highlight previous", CVAR_TRACKER_ENTRANCE("HighlightPrevious"), true, false);
UIWidgets::Tooltip("Highlight the previous entrance that Link came from");
UIWidgets::PaddedEnhancementCheckbox("Highlight available", CVAR_TRACKER_ENTRANCE("HighlightAvailable"), true, false);
UIWidgets::Tooltip("Highlight available entrances in the current scene");
UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"), true, false);
UIWidgets::Tooltip("Collapse undiscovered entrances towards the bottom of each group");
UIWidgets::CVarCheckbox("Auto scroll", CVAR_TRACKER_ENTRANCE("AutoScroll"),
UIWidgets::CheckboxOptions().Tooltip("Automatically scroll to the first aviable entrance in the current scene").Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Highlight previous", CVAR_TRACKER_ENTRANCE("HighlightPrevious"),
UIWidgets::CheckboxOptions().Tooltip("Highlight the previous entrance that Link came from").Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Highlight available", CVAR_TRACKER_ENTRANCE("HighlightAvailable"),
UIWidgets::CheckboxOptions().Tooltip("Highlight available entrances in the current scene").Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Hide undiscovered", CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"),
UIWidgets::CheckboxOptions().Tooltip("Collapse undiscovered entrances towards the bottom of each group").Color(THEME_COLOR));
bool disableHideReverseEntrances = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_ON;
static const char* disableHideReverseEntrancesText = "This option is disabled because \"Decouple Entrances\" is enabled.";
UIWidgets::PaddedEnhancementCheckbox("Hide reverse", CVAR_TRACKER_ENTRANCE("HideReverseEntrances"), true, false,
disableHideReverseEntrances, disableHideReverseEntrancesText, UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Hide reverse entrance transitions when Decouple Entrances is off");
UIWidgets::Spacer(0);
UIWidgets::CVarCheckbox("Hide reverse", CVAR_TRACKER_ENTRANCE("HideReverseEntrances"),
UIWidgets::CheckboxOptions({ {.disabled = disableHideReverseEntrances, .disabledTooltip = disableHideReverseEntrancesText }})
.Tooltip("Hide reverse entrance transitions when Decouple Entrances is off").DefaultValue(true).Color(THEME_COLOR));
ImGui::TableNextColumn();
ImGui::Text("Group By");
UIWidgets::EnhancementRadioButton("Area", CVAR_TRACKER_ENTRANCE("GroupBy"), 0);
UIWidgets::Tooltip("Group entrances by their area");
UIWidgets::EnhancementRadioButton("Type", CVAR_TRACKER_ENTRANCE("GroupBy"), 1);
UIWidgets::Tooltip("Group entrances by their entrance type");
UIWidgets::Spacer(2.0f);
UIWidgets::CVarRadioButton(
"Area", CVAR_TRACKER_ENTRANCE("GroupBy"), 0,
UIWidgets::RadioButtonsOptions().Color(THEME_COLOR).Tooltip("Group entrances by their area"));
UIWidgets::CVarRadioButton(
"Type", CVAR_TRACKER_ENTRANCE("GroupBy"), 1,
UIWidgets::RadioButtonsOptions().Color(THEME_COLOR).Tooltip("Group entrances by their entrance type"));
ImGui::Text("Spoiler Reveal");
UIWidgets::PaddedEnhancementCheckbox("Show Source", CVAR_TRACKER_ENTRANCE("ShowFrom"), true, false);
UIWidgets::Tooltip("Reveal the sourcefor undiscovered entrances");
UIWidgets::PaddedEnhancementCheckbox("Show Destination", CVAR_TRACKER_ENTRANCE("ShowTo"), true, false);
UIWidgets::Tooltip("Reveal the destination for undiscovered entrances");
UIWidgets::CVarCheckbox("Show Source", CVAR_TRACKER_ENTRANCE("ShowFrom"),
UIWidgets::CheckboxOptions().Tooltip("Reveal the sourcefor undiscovered entrances").Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show Destination", CVAR_TRACKER_ENTRANCE("ShowTo"),
UIWidgets::CheckboxOptions().Tooltip("Reveal the destination for undiscovered entrances").Color(THEME_COLOR));
ImGui::EndTable();
}
ImGui::TableNextColumn();
ImGui::SetNextItemOpen(false, ImGuiCond_Once);
if (ImGui::TreeNode("Legend")) {
ImGui::TextColored(ImColor(COLOR_ORANGE), "Last Entrance");
@ -725,11 +720,6 @@ void EntranceTrackerSettingsWindow::DrawElement() {
ImGui::TextColored(ImColor(COLOR_GRAY), "Undiscovered Entrances");
ImGui::TreePop();
}
UIWidgets::Spacer(0);
ImGui::EndTable();
}
}
void EntranceTrackerWindow::Draw() {
@ -752,24 +742,26 @@ void EntranceTrackerWindow::DrawElement() {
static ImGuiTextFilter locationSearch;
uint8_t nextTreeState = 0;
if (ImGui::Button("Collapse All")) {
if (UIWidgets::Button("Collapse All", UIWidgets::ButtonOptions({{ .tooltip = "Collapse all entrance groups" }})
.Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
nextTreeState = 1;
}
UIWidgets::Tooltip("Collapse all entrance groups");
ImGui::SameLine();
if (ImGui::Button("Expand All")) {
if (UIWidgets::Button("Expand All", UIWidgets::ButtonOptions({{ .tooltip = "Expand all entrance groups" }})
.Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
nextTreeState = 2;
}
UIWidgets::Tooltip("Expand all entrance groups");
ImGui::SameLine();
if (ImGui::Button("Clear")) {
if (UIWidgets::Button("Clear", UIWidgets::ButtonOptions({{ .tooltip = "Clear the search field" }})
.Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
locationSearch.Clear();
}
UIWidgets::Tooltip("Clear the search field");
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (locationSearch.Draw()) {
nextTreeState = 2;
}
UIWidgets::PopStyleCombobox();
uint8_t destToggle = CVarGetInteger(CVAR_TRACKER_ENTRANCE("SortBy"), 0);
uint8_t groupToggle = CVarGetInteger(CVAR_TRACKER_ENTRANCE("GroupBy"), 0);
@ -940,7 +932,6 @@ void EntranceTrackerWindow::DrawElement() {
}
}
ImGui::EndChild();
ImGui::End();
}

View file

@ -100,8 +100,8 @@ class EntranceTrackerSettingsWindow : public Ship::GuiWindow {
class EntranceTrackerWindow : public Ship::GuiWindow {
public:
using GuiWindow::GuiWindow;
void Draw() override;
void InitElement() override;
void DrawElement() override;
void UpdateElement() override {};

View file

@ -5,6 +5,7 @@
#include "soh/SaveManager.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "randomizerTypes.h"
#include <map>
@ -35,6 +36,8 @@ void DrawSong(ItemTrackerItem item);
int itemTrackerSectionId;
using namespace UIWidgets;
bool shouldUpdateVectors = true;
std::vector<ItemTrackerItem> mainWindowItems = {};
@ -111,6 +114,35 @@ std::vector<ItemTrackerItem> ocarinaButtonItems = {
ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem),
};
std::vector<ItemTrackerItem> overworldKeyItems = {
// Hack for right now, just gonna overworld keys as dungeon keys.
// Will replace with other macro once we have a custom texture
ITEM_TRACKER_ITEM_CUSTOM(RG_GUARD_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_MARKET_BAZAAR_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_MARKET_POTION_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_MASK_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_MARKET_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_BOMBCHU_BOWLING_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_TREASURE_CHEST_GAME_BUILDING_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_BOMBCHU_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_ALLEY_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_KAK_BAZAAR_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_KAK_POTION_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_BOSS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_GRANNYS_POTION_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_SKULLTULA_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_IMPAS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_WINDMILL_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_KAK_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_DAMPES_HUT_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_TALONS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_STABLES_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_BACK_TOWER_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_HYLIA_LAB_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
ITEM_TRACKER_ITEM_CUSTOM(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem),
};
std::vector<ItemTrackerItem> fishingPoleItems = {
ITEM_TRACKER_ITEM(ITEM_FISHING_POLE, 0, DrawItem)
};
@ -205,6 +237,33 @@ std::map<uint16_t, std::string> itemTrackerOcarinaButtonShortNames = {
{ RG_OCARINA_C_RIGHT_BUTTON, "C-R"},
};
std::map<uint16_t, std::string> itemTrackerOverworldKeyShortNames = {
{ RG_GUARD_HOUSE_KEY, "GUARD" },
{ RG_MARKET_BAZAAR_KEY, "MKBAZ" },
{ RG_MARKET_POTION_SHOP_KEY, "MKPOT" },
{ RG_MASK_SHOP_KEY, "MASK" },
{ RG_MARKET_SHOOTING_GALLERY_KEY, "MKSHO" },
{ RG_BOMBCHU_BOWLING_KEY, "BOWL" },
{ RG_TREASURE_CHEST_GAME_BUILDING_KEY, "TREASU" },
{ RG_BOMBCHU_SHOP_KEY, "CHUSHO" },
{ RG_RICHARDS_HOUSE_KEY, "RICH" },
{ RG_ALLEY_HOUSE_KEY, "ALLEY" },
{ RG_KAK_BAZAAR_KEY, "KAKBAZ" },
{ RG_KAK_POTION_SHOP_KEY, "KAKPO" },
{ RG_BOSS_HOUSE_KEY, "BOSS" },
{ RG_GRANNYS_POTION_SHOP_KEY, "GRANNY" },
{ RG_SKULLTULA_HOUSE_KEY, "SKULL" },
{ RG_IMPAS_HOUSE_KEY, "IMPAS" },
{ RG_WINDMILL_KEY, "WIND" },
{ RG_KAK_SHOOTING_GALLERY_KEY, "KAKSHO" },
{ RG_DAMPES_HUT_KEY, "DAMPES" },
{ RG_TALONS_HOUSE_KEY, "TALONS" },
{ RG_STABLES_KEY, "STABLE" },
{ RG_BACK_TOWER_KEY, "TOWER" },
{ RG_HYLIA_LAB_KEY, "LAB" },
{ RG_FISHING_HOLE_KEY, "FISH" },
};
std::vector<ItemTrackerItem> dungeonItems = {};
std::unordered_map<uint32_t, ItemTrackerItem> actualItemTrackerItemMap = {
@ -616,7 +675,7 @@ void DrawEquip(ItemTrackerItem item) {
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id));
Tooltip(SohUtils::GetItemName(item.id).c_str());
}
void DrawQuest(ItemTrackerItem item) {
@ -632,7 +691,7 @@ void DrawQuest(ItemTrackerItem item) {
ImGui::EndGroup();
UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(item.id));
Tooltip(SohUtils::GetQuestItemName(item.id).c_str());
};
void DrawItem(ItemTrackerItem item) {
@ -642,7 +701,9 @@ void DrawItem(ItemTrackerItem item) {
bool hasItem = actualItemId != ITEM_NONE;
std::string itemName = "";
if (item.id == ITEM_NONE) {
// Hack fix as RG_MARKET_SHOOTING_GALLERY_KEY is RandomizerGet #255 which collides
// with ITEM_NONE (ItemId #255) due to the lack of a modid to separate them
if (item.name != "ITEM_KEY_SMALL" && item.id == ITEM_NONE) {
return;
}
@ -729,7 +790,6 @@ void DrawItem(ItemTrackerItem item) {
actualItemId = item.id;
hasItem = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BOSS_SOULS) == RO_BOSS_SOULS_ON_PLUS_GANON ?
Flags_GetRandomizerInf(RAND_INF_GANON_SOUL) : true;
itemName = "Ganon's Soul";
break;
@ -763,6 +823,127 @@ void DrawItem(ItemTrackerItem item) {
hasItem = IS_RANDO && Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND);
itemName = "Fishing Pole";
break;
case RG_GUARD_HOUSE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_GUARD_HOUSE_KEY_OBTAINED);
itemName = "Guard House Key";
break;
case RG_MARKET_BAZAAR_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_MARKET_BAZAAR_KEY_OBTAINED);
itemName = "Market Bazaar Key";
break;
case RG_MARKET_POTION_SHOP_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED);
itemName = "Market Potion Shop Key";
break;
case RG_MASK_SHOP_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_MASK_SHOP_KEY_OBTAINED);
itemName = "Mask Shop Key";
break;
case RG_MARKET_SHOOTING_GALLERY_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED);
itemName = "Market Shooting Gallery Key";
break;
case RG_BOMBCHU_BOWLING_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED);
itemName = "Bombchu Bowling Key";
break;
case RG_TREASURE_CHEST_GAME_BUILDING_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED);
itemName = "Treasure Chest Game Building Key";
break;
case RG_BOMBCHU_SHOP_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED);
itemName = "Bombchu Shop Key";
break;
case RG_RICHARDS_HOUSE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED);
itemName = "Richards House Key";
break;
case RG_ALLEY_HOUSE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_ALLEY_HOUSE_KEY_OBTAINED);
itemName = "Alley House Key";
break;
case RG_KAK_BAZAAR_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_KAK_BAZAAR_KEY_OBTAINED);
itemName = "Kak Bazaar Key";
break;
case RG_KAK_POTION_SHOP_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED);
itemName = "Kak Potion Shop Key";
break;
case RG_BOSS_HOUSE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_BOSS_HOUSE_KEY_OBTAINED);
itemName = "Boss House Key";
break;
case RG_GRANNYS_POTION_SHOP_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED);
itemName = "Granny's Potion Shop Key";
break;
case RG_SKULLTULA_HOUSE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED);
itemName = "Skulltula House Key";
break;
case RG_IMPAS_HOUSE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_IMPAS_HOUSE_KEY_OBTAINED);
itemName = "Impa's House Key";
break;
case RG_WINDMILL_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_WINDMILL_KEY_OBTAINED);
itemName = "Windmill Key";
break;
case RG_KAK_SHOOTING_GALLERY_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED);
itemName = "Kak Shooting Gallery Key";
break;
case RG_DAMPES_HUT_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_DAMPES_HUT_KEY_OBTAINED);
itemName = "Dampé's Hut Key";
break;
case RG_TALONS_HOUSE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_TALONS_HOUSE_KEY_OBTAINED);
itemName = "Talon's House Key";
break;
case RG_STABLES_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_STABLES_KEY_OBTAINED);
itemName = "Stables Key";
break;
case RG_BACK_TOWER_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_BACK_TOWER_KEY_OBTAINED);
itemName = "Back Tower Key";
break;
case RG_HYLIA_LAB_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_HYLIA_LAB_KEY_OBTAINED);
itemName = "Hylia Lab Key";
break;
case RG_FISHING_HOLE_KEY:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_FISHING_HOLE_KEY_OBTAINED);
itemName = "Fishing Hole Key";
break;
}
if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) {
@ -794,13 +975,22 @@ void DrawItem(ItemTrackerItem item) {
ImGui::PopStyleColor();
}
if (item.id >= RG_GUARD_HOUSE_KEY && item.id <= RG_FISHING_HOLE_KEY) {
ImVec2 p = ImGui::GetCursorScreenPos();
std::string overworldKeyName = itemTrackerOverworldKeyShortNames[item.id];
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(overworldKeyName.c_str()).x / 2), p.y - (iconSize + 13)));
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE);
ImGui::Text("%s", overworldKeyName.c_str());
ImGui::PopStyleColor();
}
ImGui::EndGroup();
if (itemName == "") {
itemName = SohUtils::GetItemName(item.id);
}
UIWidgets::SetLastItemHoverText(itemName);
Tooltip(itemName.c_str());
}
void DrawBottle(ItemTrackerItem item) {
@ -815,7 +1005,7 @@ void DrawBottle(ItemTrackerItem item) {
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id));
Tooltip(SohUtils::GetItemName(item.id).c_str());
};
void DrawDungeonItem(ItemTrackerItem item) {
@ -864,7 +1054,7 @@ void DrawDungeonItem(ItemTrackerItem item) {
}
ImGui::EndGroup();
UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id));
Tooltip(SohUtils::GetItemName(item.id).c_str());
}
void DrawSong(ItemTrackerItem item) {
@ -874,7 +1064,7 @@ void DrawSong(ItemTrackerItem item) {
ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSong && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize / 1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1));
UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(item.id));
Tooltip(SohUtils::GetQuestItemName(item.id).c_str());
}
void DrawNotes(bool resizeable = false) {
@ -931,7 +1121,6 @@ void DrawTotalChecks() {
}
// Windowing stuff
ImVec4 ChromaKeyBackground = { 0, 0, 0, 0 }; // Float value, 1 = 255 in rgb value.
void BeginFloatingWindows(std::string UniqueName, ImGuiWindowFlags flags = 0) {
ImGuiWindowFlags windowFlags = flags;
@ -947,7 +1136,7 @@ void BeginFloatingWindows(std::string UniqueName, ImGuiWindowFlags flags = 0) {
windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove;
}
}
ImGui::PushStyleColor(ImGuiCol_WindowBg, ChromaKeyBackground);
ImGui::PushStyleColor(ImGuiCol_WindowBg, VecFromRGBA8(CVarGetColor(CVAR_TRACKER_ITEM("BgColor.Value"), {0, 0, 0, 0})));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
ImGui::Begin(UniqueName.c_str(), nullptr, windowFlags);
@ -1187,6 +1376,17 @@ void UpdateVectors() {
mainWindowItems.insert(mainWindowItems.end(), ocarinaButtonItems.begin(), ocarinaButtonItems.end());
}
//If we're adding overworld keys to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) {
//...add empty items on the main window to get the keys on their own row. (Too many to sit with Greg/Triforce pieces/boss souls/ocarina buttons)
while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
}
//Add overworld keys
mainWindowItems.insert(mainWindowItems.end(), overworldKeyItems.begin(), overworldKeyItems.end());
}
shouldUpdateVectors = false;
}
@ -1214,9 +1414,11 @@ void ItemTrackerWindow::Draw() {
if (!IsVisible()) {
return;
}
ImGui::PushFont(OTRGlobals::Instance->fontMono);
DrawElement();
// Sync up the IsVisible flag if it was changed by ImGui
SyncVisibilityConsoleVariable();
ImGui::PopFont();
}
void ItemTrackerWindow::DrawElement() {
@ -1329,6 +1531,12 @@ void ItemTrackerWindow::DrawElement() {
EndFloatingWindows();
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) {
BeginFloatingWindows("Overworld Key Tracker");
DrawItemsInRows(overworldKeyItems);
EndFloatingWindows();
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.FishingPole"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) {
BeginFloatingWindows("Fishing Pole Tracker");
DrawItemsInRows(fishingPoleItems);
@ -1352,15 +1560,23 @@ void ItemTrackerWindow::DrawElement() {
}
}
static const char* itemTrackerCapacityTrackOptions[5] = { "No Numbers", "Current Capacity", "Current Ammo", "Current Capacity / Max Capacity", "Current Ammo / Current Capacity" };
static const char* itemTrackerKeyTrackOptions[3] = { "Collected / Max", "Current / Collected / Max", "Current / Max" };
static const char* itemTrackerTriforcePieceTrackOptions[2] = { "Collected / Required", "Collected / Required / Max" };
static const char* windowTypes[2] = { "Floating", "Window" };
static const char* displayModes[2] = { "Always", "Combo Button Hold" };
static const char* buttons[14] = { "A", "B", "C-Up", "C-Down", "C-Left", "C-Right", "L", "Z", "R", "Start", "D-Up", "D-Down", "D-Left", "D-Right" };
static const char* displayTypes[3] = { "Hidden", "Main Window", "Separate" };
static const char* extendedDisplayTypes[4] = { "Hidden", "Main Window", "Misc Window", "Separate" };
static const char* minimalDisplayTypes[2] = { "Hidden", "Separate" };
static std::unordered_map<int32_t, const char*> itemTrackerCapacityTrackOptions = {
{ ITEM_TRACKER_NUMBER_NONE, "No Numbers" }, { ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY, "Current Capacity" }, { ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY, "Current Ammo" },
{ ITEM_TRACKER_NUMBER_CAPACITY, "Current Capacity / Max Capacity" }, { ITEM_TRACKER_NUMBER_AMMO, "Current Ammo / Current Capacity" }};
static std::unordered_map<int32_t, const char*> itemTrackerKeyTrackOptions = {
{ KEYS_COLLECTED_MAX, "Collected / Max" }, { KEYS_CURRENT_COLLECTED_MAX, "Current / Collected / Max" }, { KEYS_CURRENT_MAX, "Current / Max" }};
static std::unordered_map<int32_t, const char*> itemTrackerTriforcePieceTrackOptions = {
{ TRIFORCE_PIECE_COLLECTED_REQUIRED, "Collected / Required" }, { TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX, "Collected / Required / Max" }};
static std::unordered_map<int32_t, const char*> windowTypes = {{ TRACKER_WINDOW_FLOATING, "Floating" }, { TRACKER_WINDOW_WINDOW, "Window" }};
static std::unordered_map<int32_t, const char*> displayModes = {{ TRACKER_DISPLAY_ALWAYS, "Always" }, { TRACKER_DISPLAY_COMBO_BUTTON, "Combo Button Hold" }};
static std::unordered_map<int32_t, const char*> buttons = {{ TRACKER_COMBO_BUTTON_A, "A" }, { TRACKER_COMBO_BUTTON_B, "B"}, { TRACKER_COMBO_BUTTON_C_UP, "C-Up"},
{ TRACKER_COMBO_BUTTON_C_DOWN, "C-Down" }, { TRACKER_COMBO_BUTTON_C_LEFT, "C-Left" }, { TRACKER_COMBO_BUTTON_C_RIGHT, "C-Right" }, { TRACKER_COMBO_BUTTON_L, "L" },
{ TRACKER_COMBO_BUTTON_Z, "Z" }, { TRACKER_COMBO_BUTTON_R, "R" }, { TRACKER_COMBO_BUTTON_START, "Start" }, { TRACKER_COMBO_BUTTON_D_UP, "D-Up" },
{ TRACKER_COMBO_BUTTON_D_DOWN, "D-Down" }, { TRACKER_COMBO_BUTTON_D_LEFT, "D-Left" }, { TRACKER_COMBO_BUTTON_D_RIGHT, "D-Right" }};
static std::unordered_map<int32_t, const char*> displayTypes = {{ SECTION_DISPLAY_HIDDEN, "Hidden" }, { SECTION_DISPLAY_MAIN_WINDOW, "Main Window" }, { SECTION_DISPLAY_SEPARATE, "Separate" }};
static std::unordered_map<int32_t, const char*> extendedDisplayTypes = {{ SECTION_DISPLAY_EXTENDED_HIDDEN, "Hidden" },
{ SECTION_DISPLAY_EXTENDED_MAIN_WINDOW, "Main Window" }, { SECTION_DISPLAY_EXTENDED_MISC_WINDOW, "Misc Window" }, { SECTION_DISPLAY_EXTENDED_SEPARATE, "Separate" }};
static std::unordered_map<int32_t, const char*> minimalDisplayTypes = {{ SECTION_DISPLAY_MINIMAL_HIDDEN, "Hidden" }, { SECTION_DISPLAY_MINIMAL_SEPARATE, "Separate" }};
void ItemTrackerSettingsWindow::DrawElement() {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
@ -1370,154 +1586,173 @@ void ItemTrackerSettingsWindow::DrawElement() {
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("BG Color");
ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::ColorEdit4("BG Color##gItemTrackerBgColor", (float*)&ChromaKeyBackground, ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_NoLabel)) {
CVarSetFloat(CVAR_TRACKER_ITEM("BgColorR"), ChromaKeyBackground.x);
CVarSetFloat(CVAR_TRACKER_ITEM("BgColorG"), ChromaKeyBackground.y);
CVarSetFloat(CVAR_TRACKER_ITEM("BgColorB"), ChromaKeyBackground.z);
CVarSetFloat(CVAR_TRACKER_ITEM("BgColorA"), ChromaKeyBackground.w);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
ImGui::PopItemWidth();
CVarColorPicker("Background Color##gItemTrackerBgColor", CVAR_TRACKER_ITEM("BgColor"), { 0, 0, 0, 0 }, true,
ColorPickerRandomButton | ColorPickerResetButton, THEME_COLOR);
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", CVAR_TRACKER_ITEM("WindowType"), windowTypes, TRACKER_WINDOW_FLOATING)) {
ImGui::PopItemWidth();
if (CVarCombobox("Window Type", CVAR_TRACKER_ITEM("WindowType"), windowTypes, ComboboxOptions()
.DefaultIndex(TRACKER_WINDOW_FLOATING).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) {
if (UIWidgets::PaddedEnhancementCheckbox("Enable Dragging", CVAR_TRACKER_ITEM("Draggable"))) {
if (CVarCheckbox("Enable Dragging", CVAR_TRACKER_ITEM("Draggable"), CheckboxOptions().Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::PaddedEnhancementCheckbox("Only enable while paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"))) {
if (CVarCheckbox("Only enable while paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"), CheckboxOptions().Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", CVAR_TRACKER_ITEM("DisplayType.Main"), displayModes, TRACKER_DISPLAY_ALWAYS)) {
if (CVarCombobox("Display Mode", CVAR_TRACKER_ITEM("DisplayType.Main"), displayModes, ComboboxOptions()
.DefaultIndex(TRACKER_DISPLAY_ALWAYS).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) {
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", CVAR_TRACKER_ITEM("ComboButton1"), buttons, TRACKER_COMBO_BUTTON_L)) {
if (CVarCombobox("Combo Button 1", CVAR_TRACKER_ITEM("ComboButton1"), buttons, ComboboxOptions()
.DefaultIndex(TRACKER_COMBO_BUTTON_L).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", CVAR_TRACKER_ITEM("ComboButton2"), buttons, TRACKER_COMBO_BUTTON_R)) {
if (CVarCombobox("Combo Button 2", CVAR_TRACKER_ITEM("ComboButton2"), buttons, ComboboxOptions()
.DefaultIndex(TRACKER_COMBO_BUTTON_R).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
}
}
UIWidgets::PaddedSeparator();
UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", CVAR_TRACKER_ITEM("IconSize"), 25, 128, "", 36);
UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", CVAR_TRACKER_ITEM("IconSpacing"), -5, 50, "", 12);
UIWidgets::EnhancementSliderInt("Text size : %dpx", "##ITEMTRACKERTEXTSIZE", CVAR_TRACKER_ITEM("TextSize"), 1, 30, "", 13);
ImGui::Separator();
CVarSliderInt("Icon size : %dpx", CVAR_TRACKER_ITEM("IconSize"), IntSliderOptions().Min(25).Max(128).DefaultValue(36).Color(THEME_COLOR));
CVarSliderInt("Icon margins : %dpx", CVAR_TRACKER_ITEM("IconSpacing"), IntSliderOptions().Min(-5).Max(50).DefaultValue(12).Color(THEME_COLOR));
CVarSliderInt("Text size : %dpx", CVAR_TRACKER_ITEM("TextSize"), IntSliderOptions().Min(1).Max(30).DefaultValue(13).Color(THEME_COLOR));
UIWidgets::Spacer(0);
ImGui::Text("Ammo/Capacity Tracking");
UIWidgets::EnhancementCombobox(CVAR_TRACKER_ITEM("ItemCountType"), itemTrackerCapacityTrackOptions, ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY);
UIWidgets::InsertHelpHoverText("Customize what the numbers under each item are tracking."
"\n\nNote: items without capacity upgrades will track ammo even in capacity mode");
ImGui::NewLine();
CVarCombobox("Ammo/Capacity Tracking", CVAR_TRACKER_ITEM("ItemCountType"), itemTrackerCapacityTrackOptions, ComboboxOptions()
.DefaultIndex(ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY).ComponentAlignment(ComponentAlignments::Left)
.LabelPosition(LabelPositions::Above).Color(THEME_COLOR)
.Tooltip("Customize what the numbers under each item are tracking."
"\n\nNote: items without capacity upgrades will track ammo even in capacity mode"));
if (CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) {
if (UIWidgets::PaddedEnhancementCheckbox("Align count to left side", CVAR_TRACKER_ITEM("ItemCountAlignLeft"))) {
if (CVarCheckbox("Align count to left side", CVAR_TRACKER_ITEM("ItemCountAlignLeft"), CheckboxOptions().Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
}
UIWidgets::Spacer(0);
CVarCombobox("Key Count Tracking", CVAR_TRACKER_ITEM("KeyCounts"), itemTrackerKeyTrackOptions, ComboboxOptions()
.DefaultIndex(KEYS_COLLECTED_MAX).ComponentAlignment(ComponentAlignments::Left)
.LabelPosition(LabelPositions::Above).Color(THEME_COLOR)
.Tooltip("Customize what numbers are shown for key tracking."));
ImGui::Text("Key Count Tracking");
UIWidgets::EnhancementCombobox(CVAR_TRACKER_ITEM("KeyCounts"), itemTrackerKeyTrackOptions, KEYS_COLLECTED_MAX);
UIWidgets::InsertHelpHoverText("Customize what numbers are shown for key tracking.");
UIWidgets::Spacer(0);
ImGui::Text("Triforce Piece Count Tracking");
UIWidgets::EnhancementCombobox(CVAR_TRACKER_ITEM("TriforcePieceCounts"), itemTrackerTriforcePieceTrackOptions, TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX);
UIWidgets::InsertHelpHoverText("Customize what numbers are shown for triforce piece tracking.");
CVarCombobox("Triforce Piece Count Tracking", CVAR_TRACKER_ITEM("TriforcePieceCounts"), itemTrackerTriforcePieceTrackOptions, ComboboxOptions()
.DefaultIndex(TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX).ComponentAlignment(ComponentAlignments::Left)
.LabelPosition(LabelPositions::Above).Color(THEME_COLOR)
.Tooltip("Customize what numbers are shown for triforce piece tracking."));
ImGui::TableNextColumn();
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Inventory", CVAR_TRACKER_ITEM("DisplayType.Inventory"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) {
if (CVarCombobox("Inventory", CVAR_TRACKER_ITEM("DisplayType.Inventory"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Equipment", CVAR_TRACKER_ITEM("DisplayType.Equipment"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) {
if (CVarCombobox("Equipment", CVAR_TRACKER_ITEM("DisplayType.Equipment"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Misc", CVAR_TRACKER_ITEM("DisplayType.Misc"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) {
if (CVarCombobox("Misc", CVAR_TRACKER_ITEM("DisplayType.Misc"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Rewards", CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) {
if (CVarCombobox("Dungeon Rewards", CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) {
if (UIWidgets::PaddedEnhancementCheckbox("Circle display", CVAR_TRACKER_ITEM("DungeonRewardsLayout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, false)) {
if (CVarCheckbox("Circle display", CVAR_TRACKER_ITEM("DungeonRewardsLayout"))) {
shouldUpdateVectors = true;
}
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Songs", CVAR_TRACKER_ITEM("DisplayType.Songs"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) {
if (CVarCombobox("Songs", CVAR_TRACKER_ITEM("DisplayType.Songs"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_MAIN_WINDOW).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Items", CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), displayTypes, SECTION_DISPLAY_HIDDEN)) {
if (CVarCombobox("Dungeon Items", CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != SECTION_DISPLAY_HIDDEN) {
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) {
if (UIWidgets::PaddedEnhancementCheckbox("Horizontal display", CVAR_TRACKER_ITEM("DungeonItems.Layout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) {
if (CVarCheckbox("Horizontal display", CVAR_TRACKER_ITEM("DungeonItems.Layout"), CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
}
if (UIWidgets::PaddedEnhancementCheckbox("Maps and compasses", CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) {
if (CVarCheckbox("Maps and compasses", CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Greg", CVAR_TRACKER_ITEM("DisplayType.Greg"), extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) {
if (CVarCombobox("Greg", CVAR_TRACKER_ITEM("DisplayType.Greg"), extendedDisplayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, SECTION_DISPLAY_HIDDEN)) {
if (CVarCombobox("Triforce Pieces", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Boss Souls", CVAR_TRACKER_ITEM("DisplayType.BossSouls"), displayTypes, SECTION_DISPLAY_HIDDEN)) {
if (CVarCombobox("Boss Souls", CVAR_TRACKER_ITEM("DisplayType.BossSouls"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes, SECTION_DISPLAY_HIDDEN)) {
if (CVarCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Fishing Pole", CVAR_TRACKER_ITEM("DisplayType.FishingPole"), extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) {
if (CVarCombobox("Overworld Keys", CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Total Checks", "gTrackers.ItemTracker.TotalChecks.DisplayType", minimalDisplayTypes, SECTION_DISPLAY_MINIMAL_HIDDEN)) {
if (CVarCombobox("Fishing Pole", CVAR_TRACKER_ITEM("DisplayType.FishingPole"), extendedDisplayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (CVarCombobox("Total Checks", "gTrackers.ItemTracker.TotalChecks.DisplayType", minimalDisplayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_MINIMAL_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) {
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Personal notes", CVAR_TRACKER_ITEM("DisplayType.Notes"), displayTypes, SECTION_DISPLAY_HIDDEN)) {
if (CVarCombobox("Personal notes", CVAR_TRACKER_ITEM("DisplayType.Notes"), displayTypes, ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN).ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far).Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
}
UIWidgets::EnhancementCheckbox("Show Hookshot Identifiers", CVAR_TRACKER_ITEM("HookshotIdentifier"));
UIWidgets::InsertHelpHoverText("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot.");
UIWidgets::Spacer(0);
CVarCheckbox("Show Hookshot Identifiers", CVAR_TRACKER_ITEM("HookshotIdentifier"), CheckboxOptions()
.Tooltip("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot.").Color(THEME_COLOR));
ImGui::PopStyleVar(1);
ImGui::EndTable();
}
void ItemTrackerWindow::InitElement() {
float trackerBgR = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorR"), 0);
float trackerBgG = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorG"), 0);
float trackerBgB = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorB"), 0);
float trackerBgA = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorA"), 1);
ChromaKeyBackground = {
trackerBgR,
trackerBgG,
trackerBgB,
trackerBgA
}; // Float value, 1 = 255 in rgb value.
// Crashes when the itemTrackerNotes is empty, so add an empty character to it
if (itemTrackerNotes.empty()) {
itemTrackerNotes.push_back(0);

View file

@ -1,3 +1,5 @@
#pragma once
#include <libultraship/libultraship.h>
namespace Rando {

View file

@ -237,7 +237,7 @@ void Settings::CreateOptions() {
OPT_U8(RSK_KEYSANITY, "Small Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Keysanity"), mOptionDescriptions[RSK_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
OPT_U8(RSK_GERUDO_KEYS, "Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoKeys"), mOptionDescriptions[RSK_GERUDO_KEYS], WidgetType::Combobox, RO_GERUDO_KEYS_VANILLA);
OPT_U8(RSK_BOSS_KEYSANITY, "Boss Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BossKeysanity"), mOptionDescriptions[RSK_BOSS_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
OPT_U8(RSK_GANONS_BOSS_KEY, "Ganon's Boss Key", {"Vanilla", "Own Dungeon", "Start With", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Stones", "LACS-Medallions", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "100 GS Reward", "Triforce Hunt"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), mOptionDescriptions[RSK_GANONS_BOSS_KEY], WidgetType::Combobox, RO_GANON_BOSS_KEY_VANILLA);
OPT_U8(RSK_GANONS_BOSS_KEY, "Ganon's Boss Key", {"Vanilla", "Own Dungeon", "Start With", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Stones", "LACS-Medallions", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "100 GS Reward"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), mOptionDescriptions[RSK_GANONS_BOSS_KEY], WidgetType::Combobox, RO_GANON_BOSS_KEY_VANILLA);
OPT_U8(RSK_LACS_STONE_COUNT, "GCBK Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsStoneCount"), "", WidgetType::Slider, 3, true);
OPT_U8(RSK_LACS_MEDALLION_COUNT, "GCBK Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), "", WidgetType::Slider, 6, true);
OPT_U8(RSK_LACS_REWARD_COUNT, "GCBK Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WidgetType::Slider, 9, true);
@ -246,15 +246,15 @@ void Settings::CreateOptions() {
OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD);
OPT_U8(RSK_KEYRINGS, "Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF);
OPT_U8(RSK_KEYRINGS_RANDOM_COUNT, "Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8);
OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_FOREST_TEMPLE, "Forest Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_FIRE_TEMPLE, "Fire Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_WATER_TEMPLE, "Water Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_SPIRIT_TEMPLE, "Spirit Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_SHADOW_TEMPLE, "Shadow Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_BOTTOM_OF_THE_WELL, "Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_GTG, "Gerudo Training Ground Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_GANONS_CASTLE, "Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WidgetType::TristateCheckbox, 0);
OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_FOREST_TEMPLE, "Forest Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_FIRE_TEMPLE, "Fire Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_WATER_TEMPLE, "Water Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_SPIRIT_TEMPLE, "Spirit Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_SHADOW_TEMPLE, "Shadow Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_BOTTOM_OF_THE_WELL, "Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_GTG, "Gerudo Training Ground Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WidgetType::Combobox, 0);
OPT_U8(RSK_KEYRINGS_GANONS_CASTLE, "Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WidgetType::Combobox, 0);
//Dummied out due to redundancy with TimeSavers.SkipChildStealth until such a time that logic needs to consider child stealth e.g. because it's freestanding checks are added to freestanding shuffle.
//To undo this dummying, readd this setting to an OptionGroup so it appears in the UI, then edit the timesaver check hooks to look at this, and the timesaver setting to lock itself as needed.
OPT_BOOL(RSK_SKIP_CHILD_STEALTH, "Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
@ -1674,7 +1674,7 @@ void Settings::UpdateOptionProperties() {
}
// Shuffle 100 GS Reward - Force-Enabled if Ganon's Boss Key is on the 100 GS Reward
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS) {
mOptions[RSK_SHUFFLE_100_GS_REWARD].Disable("This option is force-enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward.\"", UIWidgets::CheckboxGraphics::Checkmark);
mOptions[RSK_SHUFFLE_100_GS_REWARD].Disable("This option is force-enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward.\"");
} else {
mOptions[RSK_SHUFFLE_100_GS_REWARD].Enable();
}
@ -1856,10 +1856,6 @@ void Context::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocation
mOptions[RSK_STARTING_AGE].Set(RO_AGE_CHILD);
}
if (mOptions[RSK_TRIFORCE_HUNT]) {
mOptions[RSK_GANONS_BOSS_KEY].Set(RO_GANON_BOSS_KEY_TRIFORCE_HUNT);
}
// Force 100 GS Shuffle if that's where Ganon's Boss Key is
if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
mOptions[RSK_SHUFFLE_100_GS_REWARD].Set(1);

View file

@ -1,4 +1,5 @@
#include "tricks.h"
#include "soh/SohGui/UIWidgets.hpp"
#include <unordered_map>
namespace Rando {
@ -71,7 +72,6 @@ namespace Rando {
const ImVec4 Tricks::GetTextColor(const Tag tag) {
switch(tag) {
case Tag::EXPERIMENTAL:
case Tag::GLITCH:
return { 0.00f, 0.00f, 0.00f, 1.0f };
default:
@ -82,32 +82,33 @@ namespace Rando {
const ImVec4 Tricks::GetTagColor(const Tag tag) {
switch(tag) {
case Tag::NOVICE:
return { 0.09f, 0.55f, 0.37f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::Green);
case Tag::INTERMEDIATE:
return { 0.95f, 0.52f, 0.00f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::Orange);
case Tag::ADVANCED:
return { 0.00f, 0.29f, 0.71f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::Blue);
case Tag::EXPERT:
return { 0.53f, 0.05f, 0.14f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::Red);
case Tag::EXTREME:
return { 0.27f, 0.00f, 0.27f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::Purple);
case Tag::EXPERIMENTAL:
return { 0.00f, 1.00f, 1.00f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::LightBlue);
case Tag::GLITCH:
return { 1.00f, 1.00f, 1.00f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::White);
default:
assert(false);
return { 0.50f, 0.50f, 0.50f, 1.00f };
return UIWidgets::ColorValues.at(UIWidgets::Colors::Gray);
}
}
void Tricks::DrawTagChips(const std::set<Tag>& rtTags) {
void Tricks::DrawTagChips(const std::set<Tag>& rtTags, std::string trickName) {
for (const Tag rtTag : rtTags) {
std::string tagId = GetTagName(rtTag) + "##" + trickName;
ImGui::SameLine();
ImGui::BeginDisabled();
ImGui::PushStyleColor(ImGuiCol_Button, GetTagColor(rtTag));
ImGui::SmallButton(GetTagName(rtTag).c_str());
ImGui::PopStyleColor();
UIWidgets::PushStyleButton(GetTagColor(rtTag));
ImGui::SmallButton(tagId.c_str());
UIWidgets::PopStyleButton();
ImGui::EndDisabled();
}
}

View file

@ -28,7 +28,7 @@ namespace Rando {
static const std::string GetTagName(Tag tag);
static const ImVec4 GetTextColor(Tag tag);
static const ImVec4 GetTagColor(Tag tag);
static void DrawTagChips(const std::set<Tag>& rtTags);
static void DrawTagChips(const std::set<Tag>& rtTags, std::string trickName = "");
};
}

View file

@ -1,489 +0,0 @@
#include "ResolutionEditor.h"
#include <imgui.h>
#include <libultraship/libultraship.h>
#include "soh/SohGui/UIWidgets.hpp"
#include <graphic/Fast3D/gfx_pc.h>
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
/* Console Variables are grouped under gAdvancedResolution. (e.g. CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled")
The following cvars are used in Libultraship and can be edited here:
- Enabled - Turns Advanced Resolution Mode on.
- AspectRatioX, AspectRatioY - Aspect ratio controls. To toggle off, set either to zero.
- VerticalPixelCount, VerticalResolutionToggle - Resolution controls.
- PixelPerfectMode, IntegerScale.Factor - Pixel Perfect Mode a.k.a. integer scaling controls.
- IntegerScale.FitAutomatically - Automatic resizing for Pixel Perfect Mode.
- IntegerScale.NeverExceedBounds - Prevents manual resizing from exceeding screen bounds.
The following cvars are also implemented in LUS for niche use cases:
- IgnoreAspectCorrection - Stretch framebuffer to fill screen.
This is something of a power-user setting for niche setups that most people won't need or care about,
but may be useful if playing the Switch/Wii U ports on a 4:3 television.
- IntegerScale.ExceedBoundsBy - Offset the max screen bounds, usually by +1.
This isn't that useful at the moment, so it's unused here.
*/
namespace AdvancedResolutionSettings {
enum setting { UPDATE_aspectRatioX, UPDATE_aspectRatioY, UPDATE_verticalPixelCount };
const char* aspectRatioPresetLabels[] = {
"Off", "Custom", "Original (4:3)", "Widescreen (16:9)", "Nintendo 3DS (5:3)", "16:10 (8:5)", "Ultrawide (21:9)"
};
const float aspectRatioPresetsX[] = { 0.0f, 16.0f, 4.0f, 16.0f, 5.0f, 16.0f, 21.0f };
const float aspectRatioPresetsY[] = { 0.0f, 9.0f, 3.0f, 9.0f, 3.0f, 10.0f, 9.0f };
const int default_aspectRatio = 1; // Default combo list option
const char* pixelCountPresetLabels[] = { "Custom", "Native N64 (240p)", "2x (480p)", "3x (720p)", "4x (960p)",
"5x (1200p)", "6x (1440p)", "Full HD (1080p)", "4K (2160p)" };
const int pixelCountPresets[] = { 480, 240, 480, 720, 960, 1200, 1440, 1080, 2160 };
const int default_pixelCount = 0; // Default combo list option
// Resolution clamp values as hardcoded in LUS::Gui::ApplyResolutionChanges()
const uint32_t minVerticalPixelCount = SCREEN_HEIGHT;
const uint32_t maxVerticalPixelCount = 4320; // 18x native, or 8K TV resolution
const unsigned short default_maxIntegerScaleFactor = 6; // Default size of Integer scale factor slider.
enum messageType { MESSAGE_ERROR, MESSAGE_WARNING, MESSAGE_QUESTION, MESSAGE_INFO, MESSAGE_GRAY_75 };
const ImVec4 messageColor[]{
{ 0.85f, 0.0f, 0.0f, 1.0f }, // MESSAGE_ERROR
{ 0.85f, 0.85f, 0.0f, 1.0f }, // MESSAGE_WARNING
{ 0.0f, 0.85f, 0.85f, 1.0f }, // MESSAGE_QUESTION
{ 0.0f, 0.85f, 0.55f, 1.0f }, // MESSAGE_INFO
{ 0.75f, 0.75f, 0.75f, 1.0f } // MESSAGE_GRAY_75
};
const float enhancementSpacerHeight = 19.0f;
void AdvancedResolutionSettingsWindow::InitElement() {
}
void AdvancedResolutionSettingsWindow::DrawElement() {
// Initialise update flags.
bool update[3];
for (uint8_t i = 0; i < sizeof(update); i++)
update[i] = false;
// Initialise integer scale bounds.
short max_integerScaleFactor = default_maxIntegerScaleFactor; // default value, which may or may not get
// overridden depending on viewport res
short integerScale_maximumBounds = 1; // can change when window is resized
// This is mostly just for UX purposes, as Fit Automatically logic is part of LUS.
if (((float)gfx_current_game_window_viewport.width / gfx_current_game_window_viewport.height) >
((float)gfx_current_dimensions.width / gfx_current_dimensions.height)) {
// Scale to window height
integerScale_maximumBounds = gfx_current_game_window_viewport.height / gfx_current_dimensions.height;
} else {
// Scale to window width
integerScale_maximumBounds = gfx_current_game_window_viewport.width / gfx_current_dimensions.width;
}
// Lower-clamping maximum bounds value to 1 is no-longer necessary as that's accounted for in LUS.
// Letting it go below 1 in this Editor will even allow for checking if screen bounds are being exceeded.
if (default_maxIntegerScaleFactor < integerScale_maximumBounds) {
max_integerScaleFactor =
integerScale_maximumBounds + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0);
}
// Combo List defaults
static int item_aspectRatio = CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.AspectRatio", 3);
static int item_pixelCount = CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.PixelCount", default_pixelCount);
// Stored Values for non-UIWidgets elements
static float aspectRatioX =
CVarGetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioX", aspectRatioPresetsX[item_aspectRatio]);
static float aspectRatioY =
CVarGetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioY", aspectRatioPresetsY[item_aspectRatio]);
static int verticalPixelCount =
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalPixelCount", pixelCountPresets[item_pixelCount]);
// Additional settings
static bool showHorizontalResField = false;
static int horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX;
// Disabling flags
const bool disabled_everything = !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", 0);
const bool disabled_pixelCount = !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0);
#ifdef __APPLE__
// Display HiDPI warning. (Remove this once we can definitively say it's fixed.)
ImGui::TextColored(messageColor[MESSAGE_INFO],
ICON_FA_INFO_CIRCLE " These settings may behave incorrectly on Retina displays.");
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
#endif
if (ImGui::CollapsingHeader("Original Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
// The original resolution slider (for convenience)
const bool disabled_resolutionSlider = (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0) &&
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", 0)) ||
CVarGetInteger(CVAR_LOW_RES_MODE, 0);
if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f%%", "##IMul", CVAR_INTERNAL_RESOLUTION, 0.5f,
2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) {
Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(
CVarGetFloat(CVAR_INTERNAL_RESOLUTION, 1));
}
UIWidgets::Tooltip("Multiplies your output resolution by the value entered.");
// The original MSAA slider (also for convenience)
#ifndef __WIIU__
if (UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", CVAR_MSAA_VALUE, 1, 8, "", 1, true, true,
false)) {
Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger(CVAR_MSAA_VALUE, 1));
};
UIWidgets::Tooltip(
"Activates multi-sample anti-aliasing when above 1x, up to 8x for 8 samples for every pixel.\n\n"
" " ICON_FA_INFO_CIRCLE
" (Higher MSAA with low resolution can approximate an authentic \"real N64\" look!)");
#endif
// N64 Mode toggle (again for convenience)
// UIWidgets::PaddedEnhancementCheckbox("(Enhancements>Graphics) N64 Mode", CVAR_LOW_RES_MODE, false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false);
}
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
// Activator
UIWidgets::PaddedEnhancementCheckbox("Enable advanced settings.", CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", false, false,
false, "", UIWidgets::CheckboxGraphics::Cross, false);
// Error/Warning display
if (!CVarGetInteger(CVAR_LOW_RES_MODE, 0)) {
if (IsDroppingFrames()) { // Significant frame drop warning
ImGui::TextColored(messageColor[MESSAGE_WARNING],
ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occuring.");
UIWidgets::Spacer(2);
} else { // No warnings
UIWidgets::Spacer(enhancementSpacerHeight);
}
} else { // N64 Mode warning
ImGui::TextColored(messageColor[MESSAGE_QUESTION],
ICON_FA_QUESTION_CIRCLE " \"N64 Mode\" is overriding these settings.");
ImGui::SameLine();
if (ImGui::Button("Click to disable")) {
CVarSetInteger(CVAR_LOW_RES_MODE, 0);
CVarSave();
}
}
// Resolution visualiser
ImGui::Text("Viewport dimensions: %d x %d", gfx_current_game_window_viewport.width,
gfx_current_game_window_viewport.height);
ImGui::Text("Internal resolution: %d x %d", gfx_current_dimensions.width, gfx_current_dimensions.height);
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
if (disabled_everything) { // Hide aspect ratio controls.
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
// Aspect Ratio
ImGui::Text("Force aspect ratio:");
ImGui::SameLine();
ImGui::TextColored(messageColor[MESSAGE_GRAY_75], "(Select \"Off\" to disable.)");
// Presets
if (ImGui::Combo(" ", &item_aspectRatio, aspectRatioPresetLabels,
IM_ARRAYSIZE(aspectRatioPresetLabels)) &&
item_aspectRatio != default_aspectRatio) { // don't change anything if "Custom" is selected.
aspectRatioX = aspectRatioPresetsX[item_aspectRatio];
aspectRatioY = aspectRatioPresetsY[item_aspectRatio];
if (showHorizontalResField) {
horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX;
}
CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioX", aspectRatioX);
CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioY", aspectRatioY);
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.AspectRatio", item_aspectRatio);
CVarSave();
}
// Hide aspect ratio input fields if using one of the presets.
if (item_aspectRatio == default_aspectRatio && !showHorizontalResField) {
// Declare input interaction bools outside of IF statement to prevent Y field from disappearing.
const bool input_X = ImGui::InputFloat("X", &aspectRatioX, 0.1f, 1.0f, "%.3f");
const bool input_Y = ImGui::InputFloat("Y", &aspectRatioY, 0.1f, 1.0f, "%.3f");
if (input_X || input_Y) {
item_aspectRatio = default_aspectRatio;
update[UPDATE_aspectRatioX] = true;
update[UPDATE_aspectRatioY] = true;
}
} else if (showHorizontalResField) { // Show calculated aspect ratio
if (item_aspectRatio) {
UIWidgets::Spacer(2);
const float resolvedAspectRatio = (float)gfx_current_dimensions.width / gfx_current_dimensions.height;
ImGui::Text("Aspect ratio: %.2f:1", resolvedAspectRatio);
} else {
UIWidgets::Spacer(enhancementSpacerHeight);
}
}
if (disabled_everything) { // Hide aspect ratio controls.
UIWidgets::ReEnableComponent("disabledTooltipText");
}
UIWidgets::Spacer(0);
// Vertical Resolution
UIWidgets::PaddedEnhancementCheckbox("Set fixed vertical resolution (disables Resolution slider)",
CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", true, false,
disabled_everything, "", UIWidgets::CheckboxGraphics::Cross, false);
UIWidgets::Tooltip(
"Override the resolution scale slider and use the settings below, irrespective of window size.");
if (disabled_pixelCount || disabled_everything) { // Hide pixel count controls.
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
if (ImGui::Combo("Pixel Count Presets", &item_pixelCount, pixelCountPresetLabels,
IM_ARRAYSIZE(pixelCountPresetLabels)) &&
item_pixelCount != default_pixelCount) { // don't change anything if "Custom" is selected.
verticalPixelCount = pixelCountPresets[item_pixelCount];
if (showHorizontalResField) {
horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX;
}
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalPixelCount", verticalPixelCount);
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.PixelCount", item_pixelCount);
CVarSave();
}
// Horizontal Resolution, if visibility is enabled for it.
if (showHorizontalResField) {
// Only show the field if Aspect Ratio is being enforced.
if ((aspectRatioX > 0.0f) && (aspectRatioY > 0.0f)) {
// So basically we're "faking" this one by setting aspectRatioX instead.
if (ImGui::InputInt("Horiz. Pixel Count", &horizontalPixelCount, 8, 320)) {
item_aspectRatio = default_aspectRatio;
if (horizontalPixelCount < SCREEN_WIDTH) {
horizontalPixelCount = SCREEN_WIDTH;
}
aspectRatioX = horizontalPixelCount;
aspectRatioY = verticalPixelCount;
update[UPDATE_aspectRatioX] = true;
update[UPDATE_aspectRatioY] = true;
}
} else { // Display a notice instead.
ImGui::TextColored(messageColor[MESSAGE_QUESTION],
ICON_FA_QUESTION_CIRCLE " \"Force aspect ratio\" required.");
// ImGui::Text(" ");
ImGui::SameLine();
if (ImGui::Button("Click to resolve")) {
item_aspectRatio = default_aspectRatio; // Set it to Custom
aspectRatioX = aspectRatioPresetsX[2]; // but use the 4:3 defaults
aspectRatioY = aspectRatioPresetsY[2];
update[UPDATE_aspectRatioX] = true;
update[UPDATE_aspectRatioY] = true;
horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX;
}
}
}
// Vertical Resolution part 2
if (ImGui::InputInt("Vertical Pixel Count", &verticalPixelCount, 8, 240)) {
item_pixelCount = default_pixelCount;
update[UPDATE_verticalPixelCount] = true;
// Account for the natural instinct to enter horizontal first.
// Ignore vertical resolutions that are below the lower clamp constant.
if (showHorizontalResField && !(verticalPixelCount < minVerticalPixelCount)) {
item_aspectRatio = default_aspectRatio;
aspectRatioX = horizontalPixelCount;
aspectRatioY = verticalPixelCount;
update[UPDATE_aspectRatioX] = true;
update[UPDATE_aspectRatioY] = true;
}
}
if (disabled_pixelCount || disabled_everything) { // Hide pixel count controls.
UIWidgets::ReEnableComponent("disabledTooltipText");
}
UIWidgets::Spacer(0);
// Integer scaling settings group (Pixel-perfect Mode)
static const ImGuiTreeNodeFlags IntegerScalingResolvedImGuiFlag =
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) ? ImGuiTreeNodeFlags_DefaultOpen
: ImGuiTreeNodeFlags_None;
if (ImGui::CollapsingHeader("Integer Scaling Settings", IntegerScalingResolvedImGuiFlag)) {
const bool disabled_pixelPerfectMode =
!CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) || disabled_everything;
// Pixel-perfect Mode
UIWidgets::PaddedEnhancementCheckbox("Pixel-perfect Mode", CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", true,
true, disabled_pixelCount || disabled_everything, "",
UIWidgets::CheckboxGraphics::Cross, false);
UIWidgets::Tooltip("Don't scale image to fill window.");
if (disabled_pixelCount && CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0)) {
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0);
CVarSave();
}
// Integer Scaling
UIWidgets::EnhancementSliderInt(
"Integer scale factor: %d", "##ARSIntScale", CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.Factor", 1,
max_integerScaleFactor, "%d", 1, true,
disabled_pixelPerfectMode || CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", 0));
UIWidgets::Tooltip("Integer scales the image. Only available in pixel-perfect mode.");
// Display warning if size is being clamped or if framebuffer is larger than viewport.
if (!disabled_pixelPerfectMode &&
(CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.NeverExceedBounds", 1) &&
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.Factor", 1) > integerScale_maximumBounds)) {
ImGui::SameLine();
ImGui::TextColored(messageColor[MESSAGE_WARNING], ICON_FA_EXCLAMATION_TRIANGLE " Window exceeded.");
}
UIWidgets::PaddedEnhancementCheckbox(
"Automatically scale image to fit viewport", CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", true,
true, disabled_pixelPerfectMode, "", UIWidgets::CheckboxGraphics::Cross, false);
UIWidgets::Tooltip("Automatically sets scale factor to fit window. Only available in pixel-perfect mode.");
if (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", 0)) {
// This is just here to update the value shown on the slider.
// The function in LUS to handle this setting will ignore IntegerScaleFactor while active.
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.Factor", integerScale_maximumBounds);
// CVarSave();
}
} // End of integer scaling settings
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
// Collapsible panel for additional settings
if (ImGui::CollapsingHeader("Additional Settings")) {
UIWidgets::Spacer(0);
#if defined(__SWITCH__) || defined(__WIIU__)
// Disable aspect correction, stretching the framebuffer to fill the viewport.
// This option is only really needed on systems limited to 16:9 TV resolutions, such as consoles.
// The associated cvar is still functional on PC platforms if you want to use it though.
UIWidgets::PaddedEnhancementCheckbox("Disable aspect correction and stretch the output image.\n"
"(Might be useful for 4:3 televisions!)\n"
"Not available in Pixel Perfect Mode.",
CVAR_PREFIX_ADVANCED_RESOLUTION ".IgnoreAspectCorrection", false, true,
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) ||
disabled_everything,
"", UIWidgets::CheckboxGraphics::Cross, false);
#else
if (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IgnoreAspectCorrection", 0)) {
// This setting is intentionally not exposed on PC platforms,
// but may be accidentally activated for varying reasons.
// Having this button should hopefully prevent support headaches.
ImGui::TextColored(messageColor[MESSAGE_QUESTION], ICON_FA_QUESTION_CIRCLE
" If the image is stretched and you don't know why, click this.");
if (ImGui::Button("Click to reenable aspect correction.")) {
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IgnoreAspectCorrection", 0);
CVarSave();
}
UIWidgets::Spacer(2);
}
#endif
// A requested addition; an alternative way of displaying the resolution field.
if (ImGui::Checkbox("Show a horizontal resolution field, instead of aspect ratio.", &showHorizontalResField)) {
if (!showHorizontalResField && (aspectRatioX > 0.0f)) { // when turning this setting off
// Refresh relevant values
aspectRatioX = aspectRatioY * horizontalPixelCount / verticalPixelCount;
horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX;
} else { // when turning this setting on
item_aspectRatio = default_aspectRatio;
if (aspectRatioX > 0.0f) {
// Refresh relevant values in the opposite order
horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX;
aspectRatioX = aspectRatioY * horizontalPixelCount / verticalPixelCount;
}
}
update[UPDATE_aspectRatioX] = true;
}
// Beginning of Integer Scaling additional settings.
{
// UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
// Integer Scaling - Never Exceed Bounds.
const bool disabled_neverExceedBounds =
!CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) ||
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", 0) || disabled_everything;
const bool checkbox_neverExceedBounds =
UIWidgets::PaddedEnhancementCheckbox("Prevent integer scaling from exceeding screen bounds.\n"
"(Makes screen bounds take priority over specified factor.)",
CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.NeverExceedBounds",
true, false, disabled_neverExceedBounds, "",
UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip(
"Prevents integer scaling factor from exceeding screen bounds.\n\n"
"Enabled: Will clamp the scaling factor and display a gentle warning in the resolution editor.\n"
"Disabled: Will allow scaling to exceed screen bounds, for users who want to crop overscan.\n\n"
" " ICON_FA_INFO_CIRCLE
" Please note that exceeding screen bounds may show a scroll bar on-screen.");
// Initialise the (currently unused) "Exceed Bounds By" cvar if it's been changed.
if (checkbox_neverExceedBounds &&
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0)) {
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0);
CVarSave();
}
// Integer Scaling - Exceed Bounds By 1x/Offset.
// A popular feature in some retro frontends/upscalers, sometimes called "crop overscan" or "1080p 5x".
/*
UIWidgets::PaddedEnhancementCheckbox("Allow integer scale factor to go +1 above maximum screen bounds.", CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", false, false, !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) || disabled_everything, "", UIWidgets::CheckboxGraphics::Cross, false);
*/
// It does actually function as expected, but exceeding the bottom of the screen shows a scroll bar.
// I've ended up commenting this one out because of the scroll bar, and for simplicity.
// Display an info message about the scroll bar.
if (!CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.NeverExceedBounds", 1) ||
CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0)) {
if (disabled_neverExceedBounds) { // Dim this help text accordingly
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
ImGui::TextColored(messageColor[MESSAGE_INFO],
" " ICON_FA_INFO_CIRCLE
" A scroll bar may become visible if screen bounds are exceeded.");
if (disabled_neverExceedBounds) { // Dim this help text accordingly
UIWidgets::ReEnableComponent("disabledTooltipText");
}
// Another support helper button, to disable the unused "Exceed Bounds By" cvar.
// (Remove this button if uncommenting the checkbox.)
if (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0)) {
if (ImGui::Button("Click to reset a console variable that may be causing this.")) {
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0);
CVarSave();
}
}
} else {
ImGui::Text(" ");
}
// UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
} // End of Integer Scaling additional settings.
} // End of additional settings
// Clamp and update the cvars that don't use UIWidgets
if (update[UPDATE_aspectRatioX] || update[UPDATE_aspectRatioY] || update[UPDATE_verticalPixelCount]) {
if (update[UPDATE_aspectRatioX]) {
if (aspectRatioX < 0.0f) {
aspectRatioX = 0.0f;
}
CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioX", aspectRatioX);
}
if (update[UPDATE_aspectRatioY]) {
if (aspectRatioY < 0.0f) {
aspectRatioY = 0.0f;
}
CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioY", aspectRatioY);
}
if (update[UPDATE_verticalPixelCount]) {
// There's a upper and lower clamp on the Libultraship side too,
// so clamping it here is entirely visual, so the vertical resolution field reflects it.
if (verticalPixelCount < minVerticalPixelCount) {
verticalPixelCount = minVerticalPixelCount;
}
if (verticalPixelCount > maxVerticalPixelCount) {
verticalPixelCount = maxVerticalPixelCount;
}
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalPixelCount", verticalPixelCount);
}
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.AspectRatio", item_aspectRatio);
CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.PixelCount", item_pixelCount);
CVarSave();
}
}
void AdvancedResolutionSettingsWindow::UpdateElement() {
}
bool AdvancedResolutionSettingsWindow::IsDroppingFrames() {
// a rather imprecise way of checking for frame drops.
// but it's mostly there to inform the player of large drops.
const short targetFPS = CVarGetInteger(CVAR_SETTING("InterpolationFPS"), 20);
const float threshold = targetFPS / 20.0f + 4.1f;
return ImGui::GetIO().Framerate < targetFPS - threshold;
}
} // namespace AdvancedResolutionSettings

View file

@ -1,16 +0,0 @@
#pragma once
#include <libultraship/libultraship.h>
namespace AdvancedResolutionSettings {
class AdvancedResolutionSettingsWindow : public Ship::GuiWindow {
private:
bool IsDroppingFrames();
public:
using GuiWindow::GuiWindow;
void InitElement() override;
void DrawElement() override;
void UpdateElement() override;
};
} // namespace AdvancedResolutionSettings

View file

@ -23,6 +23,7 @@ extern "C" {
#include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h"
#include "src/overlays/actors/ovl_En_Tk/z_en_tk.h"
#include "src/overlays/actors/ovl_En_Fu/z_en_fu.h"
#include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h"
#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h"
#include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h"
#include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h"
@ -42,6 +43,8 @@ extern void BgSpot03Taki_ApplyOpeningAlpha(BgSpot03Taki* bgSpot03Taki, s32 buffe
extern void EnGo2_CurledUp(EnGo2* enGo2, PlayState* play);
extern void EnRu2_SetEncounterSwitchFlag(EnRu2* enRu2, PlayState* play);
extern void EnDaiku_EscapeSuccess(EnDaiku* enDaiku, PlayState* play);
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
@ -354,6 +357,18 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
!(gPlayState->sceneNum == SCENE_ZORAS_RIVER && IS_RANDO && RAND_GET_OPTION(RSK_FROGS_HINT))) {
*should = false;
}
// If it's near a jailed carpenter, skip it along with introduction of Gerudo mini-boss
if (gPlayState->sceneNum == SCENE_THIEVES_HIDEOUT &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) {
EnWonderTalk2* enWonderTalk = va_arg(args, EnWonderTalk2*);
EnDaiku* enDaiku =
(EnDaiku*)Actor_FindNearby(gPlayState, &enWonderTalk->actor, ACTOR_EN_DAIKU, ACTORCAT_NPC, 999.0f);
if (enDaiku != NULL) {
Flags_SetSwitch(gPlayState, enDaiku->startFightSwitchFlag);
*should = false;
}
}
break;
}
case VB_NAVI_TALK: {
@ -371,6 +386,12 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
}
break;
}
case VB_END_GERUDO_MEMBERSHIP_TALK: {
if (ForcedDialogIsDisabled(FORCED_DIALOG_SKIP_NPC)) {
*should = true;
}
break;
}
case VB_GORON_LINK_BE_SCARED: {
if (ForcedDialogIsDisabled(FORCED_DIALOG_SKIP_NPC)) {
EnGo2* goronLink = va_arg(args, EnGo2*);
@ -551,6 +572,17 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
}
break;
}
case VB_PLAY_CARPENTER_FREE_CS: {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
EnDaiku* enDaiku = va_arg(args, EnDaiku*);
if (enDaiku->subCamActive) {
enDaiku->subCamActive = false;
EnDaiku_EscapeSuccess(enDaiku, gPlayState);
}
*should = false;
}
break;
}
case VB_PLAY_GORON_FREE_CS: {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
*should = false;
@ -1034,6 +1066,11 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) {
static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE;
void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
// Do nothing when in a boss rush
if (IS_BOSS_RUSH) {
return;
}
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
switch (flagType) {
case FLAG_EVENT_CHECK_INF:
@ -1106,13 +1143,19 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
break;
case FLAG_ITEM_GET_INF:
switch (flag) {
case ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE:
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DEKU_STICK_CAPACITY_30).GetGIEntry_Copy();
case ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE: {
RandomizerGet stickUpgrade =
CUR_UPG_VALUE(UPG_STICKS) == 2 ? RG_DEKU_STICK_CAPACITY_30 : RG_DEKU_STICK_CAPACITY_20;
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(stickUpgrade).GetGIEntry_Copy();
break;
case ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE:
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DEKU_NUT_CAPACITY_40).GetGIEntry_Copy();
}
case ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE: {
RandomizerGet nutUpgrade =
CUR_UPG_VALUE(UPG_NUTS) == 2 ? RG_DEKU_NUT_CAPACITY_40 : RG_DEKU_NUT_CAPACITY_30;
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(nutUpgrade).GetGIEntry_Copy();
break;
}
}
break;
}
}

View file

@ -1,5 +1,4 @@
#include "TimeSplits.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/Enhancements/gameplaystats.h"
#include "soh/SaveManager.h"
#include "soh/util.h"
@ -14,12 +13,16 @@
#include "soh/Enhancements/debugger/debugSaveEditor.h"
#include "soh_assets.h"
#include "assets/textures/parameter_static/parameter_static.h"
#include <soh/SohGui/SohGui.hpp>
#include "soh/SohGui/UIWidgets.hpp"
extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
}
using namespace UIWidgets;
// ImVec4 Colors
#define COLOR_WHITE ImVec4(1.00f, 1.00f, 1.00f, 1.00f)
#define COLOR_LIGHT_RED ImVec4(1.0f, 0.05f, 0.0f, 1.0f)
@ -636,7 +639,7 @@ void TimeSplitsDrawSplitsList() {
uint32_t dragIndex = 0;
ImGui::BeginChild("SplitTable", ImVec2(0.0f, ImGui::GetWindowHeight() - 128.0f));
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(4, 0));
ImGui::BeginTable("Splits", 5, ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable);
if (ImGui::BeginTable("Splits", 5, ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable)) {
ImGui::TableSetupColumn("Item Image", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHeaderLabel, 34.0f);
ImGui::TableSetupColumn("Item Name");
ImGui::TableSetupColumn("Current Time");
@ -687,8 +690,9 @@ void TimeSplitsDrawSplitsList() {
TimeSplitsPostDragAndDrop();
ImGui::PopStyleVar(1);
ImGui::EndTable();
}
ImGui::PopStyleVar();
ImGui::EndChild();
}
@ -769,7 +773,7 @@ void TimeSplitsDrawItemList(uint32_t type) {
}
void TimeSplitsUpdateWindowSize() {
timeSplitsWindowSize = CVarGetFloat(CVAR_ENHANCEMENT("TimeSplits.WindowSize"), 0);
timeSplitsWindowSize = CVarGetFloat(CVAR_ENHANCEMENT("TimeSplits.WindowScale"), 0);
if (timeSplitsWindowSize < 1.0f) {
timeSplitsWindowSize = 1.0f;
}
@ -777,24 +781,13 @@ void TimeSplitsUpdateWindowSize() {
void TimeSplitsDrawOptionsMenu() {
ImGui::SeparatorText("Window Options");
if (ImGui::ColorEdit4("Background Color", (float*)&windowColor, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) {
Color_RGBA8 color;
color.r = windowColor.x * 255.0;
color.g = windowColor.y * 255.0;
color.b = windowColor.z * 255.0;
color.a = windowColor.w * 255.0;
CVarSetColor("TimeSplits.WindowColor", color);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
ImGui::SameLine();
if (ImGui::Button("Reset")) {
windowColor = { 0.0f, 0.0f, 0.0f, 1.0f };
CVarSetColor("TimeSplits.WindowColor", {0, 0, 0, 1});
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
Color_RGBA8 defaultColor = { 0, 0, 0, 255 };
if (CVarColorPicker("Background Color", CVAR_ENHANCEMENT("TimeSplits.WindowColor"), defaultColor, true, 0, THEME_COLOR)) {
windowColor = VecFromRGBA8(CVarGetColor(CVAR_ENHANCEMENT("TimeSplits.WindowColor.Value"), defaultColor));
}
if (UIWidgets::PaddedEnhancementSliderFloat("Window Size: %.1fx", "##windowSize",
CVAR_ENHANCEMENT("TimeSplits.WindowSize"), 1.0f, 3.0f, "", 1.0f, false, true, true, false)) {
if (CVarSliderFloat("Window Scale", CVAR_ENHANCEMENT("TimeSplits.WindowScale"),
FloatSliderOptions().Min(1.0f).Max(3.0f).DefaultValue(1.0f).Format("%.1fx").Size({300.0f, 0.0f}).Step(0.1f).Color(THEME_COLOR))) {
TimeSplitsUpdateWindowSize();
}
@ -802,55 +795,44 @@ void TimeSplitsDrawOptionsMenu() {
ImGui::Text("New List Name: ");
ImGui::PushItemWidth(150.0f);
PushStyleInput(THEME_COLOR);
ImGui::InputText("##listName", listNameBuf, 25);
PopStyleInput();
ImGui::PopItemWidth();
ImGui::SameLine();
if (ImGui::Button("Create List")) {
if (Button("Create List", ButtonOptions().Color(THEME_COLOR).Size(Sizes::Inline))) {
TimeSplitsFileManagement(SPLIT_ACTION_SAVE, listNameBuf, splitList);
}
UIWidgets::PaddedSeparator();
TimeSplitsFileManagement(SPLIT_ACTION_COLLECT, "", emptyList);
static uint32_t selectedItem = 0;
static std::string listItem = keys[0];
ImGui::Text("Select List to Load: ");
ImGui::PushItemWidth(150.0f);
if (ImGui::BeginCombo("##listEntries", keys[selectedItem].c_str())) {
for (int i = 0; i < keys.size(); i++) {
bool isSelected = (selectedItem == i);
if (ImGui::Selectable(keys[i].c_str(), isSelected)) {
selectedItem = i;
listItem = keys[i].c_str();
}
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
Combobox("", &selectedItem, keys, ComboboxOptions().Color(THEME_COLOR).LabelPosition(LabelPositions::Near));
ImGui::PopItemWidth();
ImGui::SameLine();
if (ImGui::Button("Load List")) {
if (Button("Load List", ButtonOptions().Color(THEME_COLOR).Size(Sizes::Inline))) {
TimeSplitsFileManagement(SPLIT_ACTION_LOAD, keys[selectedItem].c_str(), emptyList);
}
ImGui::SameLine();
if (ImGui::Button("Save List")) {
if (Button("Save List", ButtonOptions().Color(THEME_COLOR).Size(Sizes::Inline))) {
TimeSplitsFileManagement(SPLIT_ACTION_SAVE, keys[selectedItem].c_str(), splitList);
}
ImGui::SameLine();
if (ImGui::Button("Delete List")) {
if (Button("Delete List", ButtonOptions().Color(THEME_COLOR).Size(Sizes::Inline))) {
TimeSplitsFileManagement(SPLIT_ACTION_DELETE, keys[selectedItem].c_str(), emptyList);
}
UIWidgets::PaddedSeparator();
UIWidgets::Separator(true, true, ImGui::GetStyle().ItemSpacing.y, ImGui::GetStyle().ItemSpacing.y);
if (ImGui::Button("New Attempt")) {
if (Button("New Attempt", ButtonOptions().Color(THEME_COLOR).Size(Sizes::Inline))) {
for (auto& data : splitList) {
data.splitTimeStatus = SPLIT_STATUS_INACTIVE;
}
splitList[0].splitTimeStatus = SPLIT_STATUS_ACTIVE;
}
ImGui::SameLine();
if (ImGui::Button("Update Splits")) {
if (Button("Update Splits", ButtonOptions().Color(THEME_COLOR).Size(Sizes::Inline))) {
TimeSplitsFileManagement(SPLIT_ACTION_UPDATE, keys[selectedItem].c_str(), splitList);
}
}
@ -864,8 +846,10 @@ void TimeSplitsRemoveSplitEntry(uint32_t index) {
void TimeSplitsDrawManageList() {
uint32_t index = 0;
ImGui::BeginTable("List Management", 2, ImGuiTableFlags_BordersInnerV);
ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_WidthFixed, 60.0f);
ImGui::BeginChild("SplitTable", ImVec2(0.0f, ImGui::GetWindowHeight() - 128.0f));
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(4, 0));
if (ImGui::BeginTable("List Management", 2, ImGuiTableFlags_BordersInnerV)) {
ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_WidthFixed, 120.0f);
ImGui::TableSetupColumn("Options", ImGuiTableColumnFlags_NoHeaderLabel);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
@ -934,6 +918,9 @@ void TimeSplitsDrawManageList() {
ImGui::EndTabBar();
ImGui::EndTable();
}
ImGui::PopStyleVar();
ImGui::EndChild();
}
void InitializeSplitDataFile() {
if (!std::filesystem::exists("timesplitdata.json")) {
@ -954,14 +941,8 @@ static bool initialized = false;
void TimeSplitWindow::DrawElement() {
ImGui::SetWindowFontScale(timeSplitsWindowSize);
if (!initialized) {
Color_RGBA8 defaultColour = {0, 0, 0, 255};
Color_RGBA8 color = CVarGetColor("TimeSplits.WindowColor", defaultColour);
windowColor = {(float)color.r / 255.0f, (float)color.g / 255.0f, (float)color.b / 255.0f, (float)color.a / 255.0f};
InitializeSplitDataFile();
initialized = true;
}
PushStyleTabs(THEME_COLOR);
if (ImGui::BeginTabBar("Split Tabs")) {
if (ImGui::BeginTabItem("Splits")) {
TimeSplitsDrawSplitsList();
@ -977,6 +958,7 @@ void TimeSplitWindow::DrawElement() {
}
ImGui::EndTabBar();
}
PopStyleTabs();
}
void TimeSplitWindow::InitElement() {
@ -984,6 +966,9 @@ void TimeSplitWindow::InitElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("SPECIAL_TRIFORCE_PIECE_WHITE", gWTriforcePieceTex, ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("SPECIAL_SPLIT_ENTRANCE", gSplitEntranceTex, ImVec4(1, 1, 1, 1));
Color_RGBA8 defaultColour = {0, 0, 0, 255};
windowColor = VecFromRGBA8(CVarGetColor(CVAR_ENHANCEMENT("TimeSplits.WindowColor.Value"), defaultColour));
InitializeSplitDataFile();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTimestamp>([](u8 item) {
if (item != ITEM_SKULL_TOKEN) {

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