Merge branch 'develop' into check-tracker-totals
|
@ -1 +1 @@
|
|||
libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev ninja-build
|
||||
libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev ninja-build
|
||||
|
|
|
@ -13,22 +13,37 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||
with:
|
||||
key: ${{ runner.os }}-soh-otr-ccache
|
||||
key: ${{ runner.os }}-otr-ccache-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-otr-ccache-${{ github.ref }}
|
||||
${{ runner.os }}-otr-ccache-
|
||||
- name: Install dependencies
|
||||
if: ${{ !vars.LINUX_RUNNER }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt)
|
||||
- name: Cache build folders
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ runner.os }}-otr-build-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-otr-build-${{ github.ref }}
|
||||
${{ runner.os }}-otr-build-
|
||||
path: |
|
||||
build-cmake
|
||||
SDL2-2.28.5
|
||||
- name: Install latest SDL
|
||||
if: ${{ !vars.LINUX_RUNNER }}
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz
|
||||
tar -xzf SDL2-2.26.1.tar.gz
|
||||
cd SDL2-2.26.1
|
||||
./configure
|
||||
if [ ! -d "SDL2-2.28.5" ]; then
|
||||
wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz
|
||||
tar -xzf SDL2-2.28.5.tar.gz
|
||||
fi
|
||||
cd SDL2-2.28.5
|
||||
./configure --enable-hidapi-libusb
|
||||
make -j 10
|
||||
sudo make install
|
||||
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
|
||||
|
@ -37,7 +52,7 @@ jobs:
|
|||
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@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
path: soh.otr
|
||||
|
@ -50,9 +65,12 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||
with:
|
||||
key: ${{ runner.os }}-ccache
|
||||
key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ccache-${{ github.ref }}
|
||||
${{ runner.os }}-ccache-
|
||||
- name: Install gtar wrapper
|
||||
if: ${{ !vars.MAC_RUNNER }}
|
||||
run: |
|
||||
|
@ -74,18 +92,18 @@ jobs:
|
|||
if [ -d /opt/local/ ]; then
|
||||
echo "MacPorts already installed"
|
||||
else
|
||||
wget https://github.com/macports/macports-base/releases/download/v2.7.2/MacPorts-2.7.2-12-Monterey.pkg
|
||||
sudo installer -pkg ./MacPorts-2.7.2-12-Monterey.pkg -target /
|
||||
wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-12-Monterey.pkg
|
||||
sudo installer -pkg ./MacPorts-2.9.3-12-Monterey.pkg -target /
|
||||
fi
|
||||
echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH
|
||||
- name: Install dependencies
|
||||
if: ${{ !vars.MAC_RUNNER }}
|
||||
run: |
|
||||
brew uninstall --ignore-dependencies libpng
|
||||
brew uninstall --ignore-dependencies libpng libzip
|
||||
sudo port install $(cat .github/workflows/macports-deps.txt)
|
||||
brew install ninja
|
||||
- name: Download soh.otr
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
- name: Build SoH
|
||||
|
@ -99,7 +117,7 @@ jobs:
|
|||
mv _packages/*.dmg SoH.dmg
|
||||
mv README.md readme.txt
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: soh-mac
|
||||
path: |
|
||||
|
@ -128,33 +146,80 @@ jobs:
|
|||
sudo apt-get update
|
||||
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt)
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||
with:
|
||||
key: ${{ matrix.os }}-ccache
|
||||
key: ${{ matrix.os }}-ccache-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ matrix.os }}-ccache-${{ github.ref }}
|
||||
${{ matrix.os }}-ccache-
|
||||
- name: Cache build folders
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ matrix.os }}-build-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ matrix.os }}-build-${{ github.ref }}
|
||||
${{ matrix.os }}-build-
|
||||
path: |
|
||||
SDL2-2.28.5
|
||||
SDL2_net-2.2.0
|
||||
- name: Install latest SDL
|
||||
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz
|
||||
tar -xzf SDL2-2.26.1.tar.gz
|
||||
cd SDL2-2.26.1
|
||||
./configure
|
||||
if [ ! -d "SDL2-2.28.5" ]; then
|
||||
wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz
|
||||
tar -xzf SDL2-2.28.5.tar.gz
|
||||
fi
|
||||
cd SDL2-2.28.5
|
||||
./configure --enable-hidapi-libusb
|
||||
make -j 10
|
||||
sudo make install
|
||||
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
|
||||
- name: Install latest libzip
|
||||
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }}
|
||||
run: |
|
||||
sudo apt-get remove libzip-dev zipcmp zipmerge ziptool
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
if [ ! -d "libzip-1.10.1" ]; then
|
||||
wget https://libzip.org/download/libzip-1.10.1.tar.gz
|
||||
tar -xzvf libzip-1.10.1.tar.gz
|
||||
fi
|
||||
cd libzip-1.10.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
sudo make install
|
||||
- name: Install latest nlohmann
|
||||
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }}
|
||||
run: |
|
||||
sudo apt-get remove nlohmann-json3-dev
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
if [ ! -d "json-3.11.3" ]; then
|
||||
wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz
|
||||
tar -xzvf v3.11.3.tar.gz
|
||||
fi
|
||||
cd json-3.11.3
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
sudo make install
|
||||
- name: Install latest SDL_net
|
||||
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
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
|
||||
if [ ! -d "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
|
||||
fi
|
||||
cd SDL2_net-2.2.0
|
||||
./configure
|
||||
make -j 10
|
||||
sudo make install
|
||||
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
|
||||
- name: Download soh.otr
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
- name: Build SoH
|
||||
|
@ -170,7 +235,7 @@ jobs:
|
|||
CC: gcc-${{ matrix.gcc }}
|
||||
CXX: g++-${{ matrix.gcc }}
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: soh-linux-${{ matrix.archive-suffix }}
|
||||
path: |
|
||||
|
@ -180,12 +245,34 @@ jobs:
|
|||
needs: generate-soh-otr
|
||||
runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
|
||||
container:
|
||||
image: devkitpro/devkita64:latest
|
||||
image: devkitpro/devkita64:20240120
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ninja-build
|
||||
sudo apt-get remove -y cmake
|
||||
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh
|
||||
sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir
|
||||
wget https://libzip.org/download/libzip-1.10.1.tar.gz
|
||||
tar -xzvf libzip-1.10.1.tar.gz
|
||||
cd libzip-1.10.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake
|
||||
make
|
||||
make install
|
||||
cd ../..
|
||||
wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz
|
||||
tar -xzvf v3.11.3.tar.gz
|
||||
cd json-3.11.3
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -H.. -B. -DJSON_BuildTests=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake
|
||||
make
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
- name: Fix dubious ownership error
|
||||
if: ${{ vars.LINUX_RUNNER }}
|
||||
run: git config --global --add safe.directory '*'
|
||||
|
@ -193,9 +280,12 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||
with:
|
||||
key: ${{ runner.os }}-switch-ccache
|
||||
key: ${{ runner.os }}-switch-ccache-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-switch-ccache-${{ github.ref }}
|
||||
${{ runner.os }}-switch-ccache-
|
||||
- name: Build SoH
|
||||
run: |
|
||||
cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
|
@ -204,11 +294,11 @@ jobs:
|
|||
mv build-switch/soh/*.nro soh.nro
|
||||
mv README.md readme.txt
|
||||
- name: Download soh.otr
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: soh-switch
|
||||
path: |
|
||||
|
@ -224,15 +314,39 @@ jobs:
|
|||
- name: Install dependencies
|
||||
if: ${{ !vars.LINUX_RUNNER }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ninja-build
|
||||
sudo apt-get remove -y cmake
|
||||
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh
|
||||
sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir
|
||||
wget https://libzip.org/download/libzip-1.10.1.tar.gz
|
||||
tar -xzvf libzip-1.10.1.tar.gz
|
||||
cd libzip-1.10.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake
|
||||
make
|
||||
make install
|
||||
cd ../..
|
||||
wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz
|
||||
tar -xzvf v3.11.3.tar.gz
|
||||
cd json-3.11.3
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -H.. -B. -DJSON_BuildTests=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake
|
||||
make
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||
with:
|
||||
key: ${{ runner.os }}-wiiu-ccache
|
||||
key: ${{ runner.os }}-wiiu-ccache-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-wiiu-ccache-${{ github.ref }}
|
||||
${{ runner.os }}-wiiu-ccache-
|
||||
- name: Build SoH
|
||||
run: |
|
||||
cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
|
@ -245,11 +359,11 @@ jobs:
|
|||
DEVKITPRO: /opt/devkitpro
|
||||
DEVKITPPC: /opt/devkitpro/devkitPPC
|
||||
- name: Download soh.otr
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: soh-wiiu
|
||||
path: |
|
||||
|
@ -270,15 +384,25 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||
with:
|
||||
key: ${{ runner.os }}-ccache
|
||||
- name: vcpkg
|
||||
uses: johnwason/vcpkg-action@v5
|
||||
variant: sccache
|
||||
max-size: "1G"
|
||||
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
|
||||
with:
|
||||
pkgs: zlib bzip2 libpng sdl2 sdl2-net glew glfw3
|
||||
token: ${{ github.token }}
|
||||
triplet: 'x64-windows-static'
|
||||
save-always: true
|
||||
key: ${{ runner.os }}-build-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ github.ref }}
|
||||
${{ runner.os }}-build-
|
||||
path: |
|
||||
build-windows
|
||||
vcpkg
|
||||
- name: Configure Developer Command Prompt
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Build SoH
|
||||
|
@ -286,7 +410,7 @@ jobs:
|
|||
VCPKG_ROOT: ${{github.workspace}}/vcpkg
|
||||
run: |
|
||||
set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH"
|
||||
cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DBUILD_REMOTE_CONTROL=1
|
||||
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
|
||||
|
@ -299,12 +423,12 @@ jobs:
|
|||
mv ./build-windows/gamecontrollerdb.txt ./soh-windows/gamecontrollerdb.txt
|
||||
mv ./x64/Release/assets ./soh-windows
|
||||
- name: Download soh.otr
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
path: soh-windows
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: soh-windows
|
||||
path: soh-windows
|
||||
|
|
|
@ -1 +1 @@
|
|||
libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal
|
||||
libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal nlohmann-json +universal
|
|
@ -0,0 +1,64 @@
|
|||
# todo:
|
||||
# nlohmann
|
||||
|
||||
name: test-builds-on-distros
|
||||
on:
|
||||
workflow_dispatch: # by request
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
image: ["archlinux:base", "opensuse/tumbleweed:latest", "ubuntu:mantic", "debian:bookworm", "fedora:39"]
|
||||
cc: ["gcc", "clang"]
|
||||
include:
|
||||
- cxx: g++
|
||||
cc: gcc
|
||||
- cxx: clang++
|
||||
cc: clang
|
||||
runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
steps:
|
||||
- name: Install dependencies (pacman)
|
||||
if: ${{ matrix.image == 'archlinux:base' }}
|
||||
run: |
|
||||
echo arch
|
||||
echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
|
||||
pacman -Syu --noconfirm
|
||||
pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
|
||||
- name: Install dependencies (dnf)
|
||||
if: ${{ matrix.image == 'fedora:39' }}
|
||||
run: |
|
||||
echo fedora
|
||||
echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
|
||||
dnf -y upgrade
|
||||
dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
|
||||
- name: Install dependencies (apt)
|
||||
if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }}
|
||||
run: |
|
||||
echo debian based
|
||||
echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
|
||||
apt-get update
|
||||
apt-get -y full-upgrade
|
||||
apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
|
||||
- name: Install dependencies (zypper)
|
||||
if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }}
|
||||
run: |
|
||||
echo openSUSE
|
||||
echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
|
||||
zypper --non-interactive dup
|
||||
zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- name: Build SoH
|
||||
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 -DBUILD_REMOTE_CONTROL=1
|
||||
cmake --build build-cmake --config Release -j3
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
CXX: ${{ matrix.cxx }}
|
|
@ -448,5 +448,5 @@ _packages
|
|||
*/extract_assets_cmake*
|
||||
/build*
|
||||
|
||||
soh/build.c
|
||||
soh/src/boot/build.c
|
||||
soh/properties.h
|
||||
|
|
|
@ -8,5 +8,9 @@ if(MSVC)
|
|||
|
||||
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc")
|
||||
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
|
||||
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache")
|
||||
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Z7")
|
||||
else()
|
||||
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
|
||||
endif()
|
||||
endif()
|
|
@ -5,8 +5,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
|||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||
|
||||
project(Ship VERSION 8.0.4 LANGUAGES C CXX)
|
||||
set(PROJECT_BUILD_NAME "MacReady Echo" CACHE STRING "")
|
||||
project(Ship VERSION 8.0.5 LANGUAGES C CXX)
|
||||
set(PROJECT_BUILD_NAME "MacReady Foxtrot" CACHE STRING "")
|
||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
|
||||
|
||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
||||
|
@ -14,13 +14,17 @@ add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
|
|||
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/utf-8>)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
include(CMake/automate-vcpkg.cmake)
|
||||
include(CMake/automate-vcpkg.cmake)
|
||||
|
||||
set(VCPKG_TRIPLET x64-windows-static)
|
||||
set(VCPKG_TARGET_TRIPLET x64-windows-static)
|
||||
set(VCPKG_TRIPLET x64-windows-static)
|
||||
set(VCPKG_TARGET_TRIPLET x64-windows-static)
|
||||
|
||||
vcpkg_bootstrap()
|
||||
vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3)
|
||||
vcpkg_bootstrap()
|
||||
vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json)
|
||||
|
||||
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache")
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 04b85b95fab07a394b62dcd28a502a3040f08e0c
|
||||
Subproject commit 467434c5666e11a3a7b756ff04401cd54da5c3f2
|
2
ZAPDTR
|
@ -1 +1 @@
|
|||
Subproject commit eff29036118349e142ee8efca80fd975a2a2b6ff
|
||||
Subproject commit 9f9d0be3c914354ecabab3695581f1123c13ac20
|
|
@ -84,41 +84,66 @@ cd "build/x64"
|
|||
```
|
||||
|
||||
## Linux
|
||||
Requires `gcc >= 10, x11, curl, python3, sdl2 >= 2.0.22, libpng, glew >= 2.2, ninja, cmake, lld, pulseaudio-libs`
|
||||
### Install dependencies
|
||||
#### Debian/Ubuntu
|
||||
```sh
|
||||
# using gcc
|
||||
apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
|
||||
|
||||
**Important: For maximum performance make sure you have ninja build tools installed!**
|
||||
# or using clang
|
||||
apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
|
||||
```
|
||||
#### Arch
|
||||
```sh
|
||||
# using gcc
|
||||
pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
|
||||
|
||||
_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
|
||||
# or using clang
|
||||
pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
|
||||
```
|
||||
#### Fedora
|
||||
```sh
|
||||
# using gcc
|
||||
dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
|
||||
|
||||
# or using clang
|
||||
dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
|
||||
```
|
||||
#### openSUSE
|
||||
```sh
|
||||
# using gcc
|
||||
zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
|
||||
|
||||
# or using clang
|
||||
zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
_Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
|
||||
|
||||
```bash
|
||||
# Clone the repo
|
||||
# Clone the repo and enter the directory
|
||||
git clone https://github.com/HarbourMasters/Shipwright.git
|
||||
cd Shipwright
|
||||
# Clone the submodule libultraship
|
||||
|
||||
# Clone the submodules
|
||||
git submodule update --init
|
||||
# Copy the baserom to the OTRExporter folder
|
||||
cp <path to your ROM> OTRExporter
|
||||
|
||||
# Generate Ninja project
|
||||
cmake -H. -Bbuild-cmake -GNinja # -DCMAKE_BUILD_TYPE:STRING=Release (if you're packaging) -DPython3_EXECUTABLE=$(which python3) (if you are using non-standard Python installations such as PyEnv)
|
||||
# Extract assets & generate OTR (run this anytime you need to regenerate OTR)
|
||||
cmake --build build-cmake --target ExtractAssets
|
||||
|
||||
# Generate soh.otr
|
||||
cmake --build build-cmake --target GenerateSohOtr
|
||||
|
||||
# Compile the project
|
||||
cmake --build build-cmake # --config Release (if you're packaging)
|
||||
|
||||
# Now you can run the executable in ./build-cmake/soh/soh.elf
|
||||
# To develop the project open the repository in VSCode (or your preferred editor)
|
||||
|
||||
# If you need to clean the project you can run
|
||||
cmake --build build-cmake --target clean
|
||||
|
||||
# If you need to regenerate the asset headers to check them into source
|
||||
cmake --build build-cmake --target ExtractAssetHeaders
|
||||
|
||||
# If you need a newer soh.otr only
|
||||
cmake --build build-cmake --target GenerateSohOtr
|
||||
```
|
||||
|
||||
### Generating a distributable
|
||||
### Generate a distributable
|
||||
After compiling the project you can generate a distributable by running of the following:
|
||||
```bash
|
||||
# Go to build folder
|
||||
|
@ -129,6 +154,20 @@ cpack -G ZIP
|
|||
cpack -G External (creates appimage)
|
||||
```
|
||||
|
||||
### Additional CMake Targets
|
||||
#### Clean
|
||||
```bash
|
||||
# If you need to clean the project you can run
|
||||
cmake --build build-cmake --target clean
|
||||
```
|
||||
|
||||
#### Regenerate Asset Headers
|
||||
```bash
|
||||
# If you need to regenerate the asset headers to check them into source
|
||||
cp <path to your ROM> OTRExporter
|
||||
cmake --build build-cmake --target ExtractAssetHeaders
|
||||
```
|
||||
|
||||
## macOS
|
||||
Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake` (can be installed via homebrew, macports, etc)
|
||||
|
||||
|
|
|
@ -188,4 +188,4 @@ Assuming all went well, you can now push your changes to your fork with the foll
|
|||
|
||||
```bash
|
||||
git push origin <YOUR BRANCH NAME>
|
||||
```
|
||||
```
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 15d57d806e39d7f19783e26acc1a062d402169c7
|
||||
Subproject commit 6f978e0d237530f304ba2018bbdc539b175c184a
|
|
@ -8,5 +8,9 @@ if(MSVC)
|
|||
|
||||
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc")
|
||||
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
|
||||
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache")
|
||||
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Z7")
|
||||
else()
|
||||
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
|
||||
endif()
|
||||
endif()
|
|
@ -105,8 +105,8 @@ set(PROJECT_NAME soh)
|
|||
################################################################################
|
||||
# Sources
|
||||
################################################################################
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/build.c.in ${CMAKE_BINARY_DIR}/build.c @ONLY)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/properties.h.in ${CMAKE_CURRENT_SOURCE_DIR}/properties.h @ONLY)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/build.c.in ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/build.c @ONLY)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/properties.h.in ${CMAKE_CURRENT_SOURCE_DIR}/properties.h @ONLY)
|
||||
|
||||
set(Header_Files "resource.h")
|
||||
source_group("headers" FILES ${Header_Files})
|
||||
|
@ -217,8 +217,6 @@ source_group("soh\\resource\\importer\\scenecommand" REGULAR_EXPRESSION "soh/res
|
|||
# src (decomp) {{{
|
||||
file(GLOB_RECURSE src__ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.c" "src/*.h")
|
||||
|
||||
list(APPEND src__ ${CMAKE_BINARY_DIR}/build.c)
|
||||
list(APPEND src__ ${CMAKE_CURRENT_SOURCE_DIR}/properties.h)
|
||||
list(APPEND src__ ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc)
|
||||
list(FILTER src__ EXCLUDE REGEX "src/dmadata/*")
|
||||
list(FILTER src__ EXCLUDE REGEX "src/elf_message/*")
|
||||
|
@ -238,7 +236,6 @@ list(REMOVE_ITEM src__ "src/libultra/gu/sqrtf.c")
|
|||
list(REMOVE_ITEM src__ "src/libultra/gu/us2dex.c")
|
||||
|
||||
source_group("src" REGULAR_EXPRESSION "src/*")
|
||||
source_group("src\\build" FILES ${CMAKE_BINARY_DIR}/build.c ${CMAKE_CURRENT_SOURCE_DIR}/properties.h ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc)
|
||||
source_group("src\\boot" REGULAR_EXPRESSION "src/boot/*")
|
||||
source_group("src\\buffers" REGULAR_EXPRESSION "src/buffers/*")
|
||||
source_group("src\\code" REGULAR_EXPRESSION "src/code/*")
|
||||
|
@ -328,7 +325,7 @@ endif()
|
|||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
Boost
|
||||
URL https://sourceforge.net/projects/boost/files/boost/1.81.0/boost_1_81_0.tar.gz
|
||||
URL https://archives.boost.io/release/1.81.0/source/boost_1_81_0.tar.gz
|
||||
URL_HASH SHA256=205666dea9f6a7cfed87c7a6dfbeb52a2c1b9de55712c9c1a87735d7181452b6
|
||||
SOURCE_SUBDIR "null" # Set to a nonexistent directory so boost is not built (we don't need to build it)
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP false # supress timestamp warning, not needed since the url wont change
|
||||
|
@ -356,7 +353,13 @@ set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS})
|
|||
|
||||
if (BUILD_REMOTE_CONTROL)
|
||||
find_package(SDL2_net)
|
||||
set(SDL2-NET-INCLUDE ${SDL_NET_INCLUDE_DIRS})
|
||||
|
||||
if(NOT SDL2_net_FOUND)
|
||||
message(STATUS "SDL2_net not found (it's possible the version installed is too old). Disabling BUILD_REMOTE_CONTROL.")
|
||||
set(BUILD_REMOTE_CONTROL 0)
|
||||
else()
|
||||
set(SDL2-NET-INCLUDE ${SDL_NET_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE assets
|
||||
|
@ -623,6 +626,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
|||
-Wno-parentheses
|
||||
-Wno-narrowing
|
||||
-Wno-missing-braces
|
||||
-Wno-int-conversion
|
||||
-Wno-implicit-int
|
||||
$<$<COMPILE_LANGUAGE:C>:
|
||||
-Werror-implicit-function-declaration
|
||||
-Wno-incompatible-pointer-types
|
||||
|
@ -642,15 +647,6 @@ endif()
|
|||
################################################################################
|
||||
# Pre build events
|
||||
################################################################################
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
add_custom_command_if(
|
||||
TARGET ${PROJECT_NAME}
|
||||
PRE_BUILD
|
||||
COMMANDS
|
||||
COMMAND $<CONFIG:Debug> copy /b $<SHELL_PATH:${CMAKE_BINARY_DIR}/>build.c +,,
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME}
|
||||
|
|
|
@ -28,4 +28,10 @@
|
|||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- legacy -->
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to pm if pmv2 is not available -->
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
*.cfg
|
||||
*.vtx.inc
|
||||
*.dlist.inc
|
||||
*.txt
|
||||
!*.png
|
||||
|
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 946 B |
After Width: | Height: | Size: 984 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 953 B |
After Width: | Height: | Size: 922 B |
After Width: | Height: | Size: 954 B |
After Width: | Height: | Size: 968 B |
After Width: | Height: | Size: 993 B |
After Width: | Height: | Size: 941 B |
Before Width: | Height: | Size: 355 B After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 379 B After Width: | Height: | Size: 992 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 973 B |
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1005 B |
After Width: | Height: | Size: 1.0 KiB |
|
@ -0,0 +1,15 @@
|
|||
Complete triforce:
|
||||
DL name: gTriforcePieceCompletedDL
|
||||
Export Path: objects/object_triforce_completed
|
||||
|
||||
Shard 0:
|
||||
DL name: gTriforcePiece0DL
|
||||
Export Path: objects/object_triforce_piece_0
|
||||
|
||||
Shard 1:
|
||||
DL name: gTriforcePiece1DL
|
||||
Export Path: objects/object_triforce_piece_1
|
||||
|
||||
Shard 2:
|
||||
DL name: gTriforcePiece2DL
|
||||
Export Path: objects/object_triforce_piece_2
|
After Width: | Height: | Size: 660 B |
|
@ -1230,8 +1230,8 @@ Gfx* Gfx_EnvColor(GraphicsContext* gfxCtx, s32 r, s32 g, s32 b, s32 a);
|
|||
void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b);
|
||||
void func_80095974(GraphicsContext* gfxCtx);
|
||||
void func_80095AA0(PlayState* play, Room* room, Input* arg2, UNK_TYPE arg3);
|
||||
void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 mode0,
|
||||
u16 tlutCount, f32 frameX, f32 frameY);
|
||||
void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 tlutMode,
|
||||
u16 tlutCount, f32 offsetX, f32 offsetY);
|
||||
void func_80096FD4(PlayState* play, Room* room);
|
||||
u32 func_80096FE8(PlayState* play, RoomContext* roomCtx);
|
||||
s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum);
|
||||
|
@ -1828,8 +1828,8 @@ MtxF* Matrix_CheckFloats(MtxF* mf, char* file, s32 line);
|
|||
void Matrix_SetTranslateScaleMtx2(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY,
|
||||
f32 translateZ);
|
||||
uintptr_t SysUcode_GetUCodeBoot(void);
|
||||
uintptr_t SysUcode_GetUCodeBootSize(void);
|
||||
uintptr_t SysUcode_GetUCode(void);
|
||||
size_t SysUcode_GetUCodeBootSize(void);
|
||||
uint32_t SysUcode_GetUCode(void);
|
||||
uintptr_t SysUcode_GetUCodeData(void);
|
||||
void func_800D2E30(UnkRumbleStruct* arg0);
|
||||
void func_800D3140(UnkRumbleStruct* arg0);
|
||||
|
@ -2467,6 +2467,10 @@ void Message_DrawText(PlayState* play, Gfx** gfxP);
|
|||
void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH);
|
||||
void Interface_RandoRestoreSwordless(void);
|
||||
|
||||
//Pause Warp
|
||||
void PauseWarp_HandleSelection();
|
||||
void PauseWarp_Execute();
|
||||
|
||||
// #endregion
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -744,7 +744,6 @@ typedef struct {
|
|||
/* 0x0134 */ char** doActionSegment;
|
||||
/* 0x0138 */ u8* iconItemSegment;
|
||||
/* 0x013C */ char** mapSegment;
|
||||
char** mapSegmentName;
|
||||
/* 0x0140 */ u8 mapPalette[32];
|
||||
/* 0x0160 */ DmaRequest dmaRequest_160;
|
||||
/* 0x0180 */ DmaRequest dmaRequest_180;
|
||||
|
@ -815,6 +814,10 @@ typedef struct {
|
|||
/* 0x026C */ u8 dinsNayrus; // "m_magic"; din's fire and nayru's love
|
||||
/* 0x026D */ u8 all; // "another"; enables all item restrictions
|
||||
} restrictions;
|
||||
// #region SOH [General]
|
||||
/* */ char* mapSegmentName[2]; // Tracks the map segment texture by OTR sig name
|
||||
/* */ u8 mapPalettesPulse[40][32]; // Used to have unique pointers per map pulse color for the shader backend. 40 for map pulse timer x2
|
||||
// #endregion
|
||||
} InterfaceContext; // size = 0x270
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -345,7 +345,7 @@ typedef enum {
|
|||
#define PLAYER_LIMB_BUF_COUNT LIMB_BUF_COUNT(PLAYER_LIMB_MAX)
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ f32 unk_00;
|
||||
/* 0x00 */ f32 ceilingCheckHeight;
|
||||
/* 0x04 */ f32 unk_04;
|
||||
/* 0x08 */ f32 unk_08;
|
||||
/* 0x0C */ f32 unk_0C;
|
||||
|
@ -359,7 +359,7 @@ typedef struct {
|
|||
/* 0x2C */ f32 unk_2C;
|
||||
/* 0x30 */ f32 unk_30;
|
||||
/* 0x34 */ f32 unk_34;
|
||||
/* 0x38 */ f32 unk_38;
|
||||
/* 0x38 */ f32 wallCheckRadius;
|
||||
/* 0x3C */ f32 unk_3C;
|
||||
/* 0x40 */ f32 unk_40;
|
||||
/* 0x44 */ Vec3s unk_44;
|
||||
|
@ -489,180 +489,187 @@ typedef s32 (*UpperActionFunc)(struct Player*, struct PlayState*);
|
|||
typedef void (*PlayerFuncA74)(struct PlayState*, struct Player*);
|
||||
|
||||
typedef struct Player {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ s8 currentTunic; // current tunic from `PlayerTunic`
|
||||
/* 0x014D */ s8 currentSwordItemId;
|
||||
/* 0x014E */ s8 currentShield; // current shield from `PlayerShield`
|
||||
/* 0x014F */ s8 currentBoots; // current boots from `PlayerBoots`
|
||||
/* 0x0150 */ s8 heldItemButton; // Button index for the item currently used
|
||||
/* 0x0151 */ s8 heldItemAction; // Item action for the item currently used
|
||||
/* 0x0152 */ u8 heldItemId; // Item id for the item currently used
|
||||
/* 0x0153 */ s8 prevBoots; // previous boots from `PlayerBoots`
|
||||
/* 0x0154 */ s8 itemAction; // the difference between this and heldItemAction is unclear
|
||||
/* 0x0155 */ char unk_155[0x003];
|
||||
/* 0x0158 */ u8 modelGroup;
|
||||
/* 0x0159 */ u8 nextModelGroup;
|
||||
/* 0x015A */ s8 itemChangeType;
|
||||
/* 0x015B */ u8 modelAnimType;
|
||||
/* 0x015C */ u8 leftHandType;
|
||||
/* 0x015D */ u8 rightHandType;
|
||||
/* 0x015E */ u8 sheathType;
|
||||
/* 0x015F */ u8 currentMask; // current mask equipped from `PlayerMask`
|
||||
/* 0x0160 */ Gfx** rightHandDLists;
|
||||
/* 0x0164 */ Gfx** leftHandDLists;
|
||||
/* 0x0168 */ Gfx** sheathDLists;
|
||||
/* 0x016C */ Gfx** waistDLists;
|
||||
/* 0x0170 */ u8 giObjectLoading;
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ s8 currentTunic; // current tunic from `PlayerTunic`
|
||||
/* 0x014D */ s8 currentSwordItemId;
|
||||
/* 0x014E */ s8 currentShield; // current shield from `PlayerShield`
|
||||
/* 0x014F */ s8 currentBoots; // current boots from `PlayerBoots`
|
||||
/* 0x0150 */ s8 heldItemButton; // Button index for the item currently used
|
||||
/* 0x0151 */ s8 heldItemAction; // Item action for the item currently used
|
||||
/* 0x0152 */ u8 heldItemId; // Item id for the item currently used
|
||||
/* 0x0153 */ s8 prevBoots; // previous boots from `PlayerBoots`
|
||||
/* 0x0154 */ s8 itemAction; // the difference between this and heldItemAction is unclear
|
||||
/* 0x0155 */ char unk_155[0x003];
|
||||
/* 0x0158 */ u8 modelGroup;
|
||||
/* 0x0159 */ u8 nextModelGroup;
|
||||
/* 0x015A */ s8 itemChangeType;
|
||||
/* 0x015B */ u8 modelAnimType;
|
||||
/* 0x015C */ u8 leftHandType;
|
||||
/* 0x015D */ u8 rightHandType;
|
||||
/* 0x015E */ u8 sheathType;
|
||||
/* 0x015F */ u8 currentMask; // current mask equipped from `PlayerMask`
|
||||
/* 0x0160 */ Gfx** rightHandDLists;
|
||||
/* 0x0164 */ Gfx** leftHandDLists;
|
||||
/* 0x0168 */ Gfx** sheathDLists;
|
||||
/* 0x016C */ Gfx** waistDLists;
|
||||
/* 0x0170 */ u8 giObjectLoading;
|
||||
/* 0x0174 */ DmaRequest giObjectDmaRequest;
|
||||
/* 0x0194 */ OSMesgQueue giObjectLoadQueue;
|
||||
/* 0x01AC */ OSMesg giObjectLoadMsg;
|
||||
/* 0x01B0 */ void* giObjectSegment; // also used for title card textures
|
||||
/* 0x01B4 */ SkelAnime skelAnime;
|
||||
/* 0x01F8 */ Vec3s jointTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x0288 */ Vec3s morphTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x0318 */ Vec3s blendTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x03A8 */ s16 unk_3A8[2];
|
||||
/* 0x03AC */ Actor* heldActor;
|
||||
/* 0x03B0 */ Vec3f leftHandPos;
|
||||
/* 0x03BC */ Vec3s unk_3BC;
|
||||
/* 0x03C4 */ Actor* unk_3C4;
|
||||
/* 0x03C8 */ Vec3f unk_3C8;
|
||||
/* 0x03D4 */ char unk_3D4[0x058];
|
||||
/* 0x042C */ s8 doorType;
|
||||
/* 0x042D */ s8 doorDirection;
|
||||
/* 0x042E */ s16 doorTimer;
|
||||
/* 0x0430 */ Actor* doorActor;
|
||||
/* 0x0434 */ s16 getItemId; // Upstream TODO: Document why this is s16 while it's s8 upstream
|
||||
/* 0x0436 */ u16 getItemDirection;
|
||||
/* 0x0438 */ Actor* interactRangeActor;
|
||||
/* 0x043C */ s8 mountSide;
|
||||
/* 0x043D */ char unk_43D[0x003];
|
||||
/* 0x0440 */ Actor* rideActor;
|
||||
/* 0x0444 */ u8 csAction;
|
||||
/* 0x0445 */ u8 prevCsAction;
|
||||
/* 0x0446 */ u8 cueId;
|
||||
/* 0x0447 */ u8 unk_447;
|
||||
/* 0x0448 */ Actor* csActor;
|
||||
/* 0x044C */ char unk_44C[0x004];
|
||||
/* 0x0450 */ Vec3f unk_450;
|
||||
/* 0x045C */ Vec3f unk_45C;
|
||||
/* 0x0468 */ char unk_468[0x002];
|
||||
/* 0x046A */ s16 doorBgCamIndex;
|
||||
/* 0x046C */ s16 subCamId;
|
||||
/* 0x046E */ char unk_46E[0x02A];
|
||||
/* 0x01AC */ OSMesg giObjectLoadMsg;
|
||||
/* 0x01B0 */ void* giObjectSegment; // also used for title card textures
|
||||
/* 0x01B4 */ SkelAnime skelAnime;
|
||||
/* 0x01F8 */ Vec3s jointTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x0288 */ Vec3s morphTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x0318 */ Vec3s blendTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x03A8 */ s16 unk_3A8[2];
|
||||
/* 0x03AC */ Actor* heldActor;
|
||||
/* 0x03B0 */ Vec3f leftHandPos;
|
||||
/* 0x03BC */ Vec3s unk_3BC;
|
||||
/* 0x03C4 */ Actor* unk_3C4;
|
||||
/* 0x03C8 */ Vec3f unk_3C8;
|
||||
/* 0x03D4 */ char unk_3D4[0x058];
|
||||
/* 0x042C */ s8 doorType;
|
||||
/* 0x042D */ s8 doorDirection;
|
||||
/* 0x042E */ s16 doorTimer;
|
||||
/* 0x0430 */ Actor* doorActor;
|
||||
/* 0x0434 */ s16 getItemId; // Upstream TODO: Document why this is s16 while it's s8 upstream
|
||||
/* 0x0436 */ u16 getItemDirection;
|
||||
/* 0x0438 */ Actor* interactRangeActor;
|
||||
/* 0x043C */ s8 mountSide;
|
||||
/* 0x043D */ char unk_43D[0x003];
|
||||
/* 0x0440 */ Actor* rideActor;
|
||||
/* 0x0444 */ u8 csAction;
|
||||
/* 0x0445 */ u8 prevCsAction;
|
||||
/* 0x0446 */ u8 cueId;
|
||||
/* 0x0447 */ u8 unk_447;
|
||||
/* 0x0448 */ Actor* csActor; // Actor involved in a `csAction`. Typically the actor that invoked the cutscene.
|
||||
/* 0x044C */ char unk_44C[0x004];
|
||||
/* 0x0450 */ Vec3f unk_450;
|
||||
/* 0x045C */ Vec3f unk_45C;
|
||||
/* 0x0468 */ char unk_468[0x002];
|
||||
/* 0x046A */ s16 doorBgCamIndex;
|
||||
/* 0x046C */ s16 subCamId;
|
||||
/* 0x046E */ char unk_46E[0x02A];
|
||||
/* 0x0498 */ ColliderCylinder cylinder;
|
||||
/* 0x04E4 */ ColliderQuad meleeWeaponQuads[2];
|
||||
/* 0x05E4 */ ColliderQuad shieldQuad;
|
||||
/* 0x0664 */ Actor* unk_664;
|
||||
/* 0x0668 */ char unk_668[0x004];
|
||||
/* 0x066C */ s32 unk_66C;
|
||||
/* 0x0670 */ s32 meleeWeaponEffectIndex;
|
||||
/* 0x0664 */ Actor* unk_664;
|
||||
/* 0x0668 */ char unk_668[0x004];
|
||||
/* 0x066C */ s32 unk_66C;
|
||||
/* 0x0670 */ s32 meleeWeaponEffectIndex;
|
||||
/* 0x0674 */ PlayerActionFunc actionFunc;
|
||||
/* 0x0678 */ PlayerAgeProperties* ageProperties;
|
||||
/* 0x067C */ u32 stateFlags1;
|
||||
/* 0x0680 */ u32 stateFlags2;
|
||||
/* 0x0684 */ Actor* unk_684;
|
||||
/* 0x0688 */ Actor* boomerangActor;
|
||||
/* 0x068C */ Actor* naviActor;
|
||||
/* 0x0690 */ s16 naviTextId;
|
||||
/* 0x0692 */ u8 stateFlags3;
|
||||
/* 0x0693 */ s8 exchangeItemId;
|
||||
/* 0x0694 */ Actor* targetActor;
|
||||
/* 0x0698 */ f32 targetActorDistance;
|
||||
/* 0x069C */ char unk_69C[0x004];
|
||||
/* 0x06A0 */ f32 unk_6A0;
|
||||
/* 0x06A4 */ f32 closestSecretDistSq;
|
||||
/* 0x06A8 */ Actor* unk_6A8;
|
||||
/* 0x06AC */ s8 unk_6AC;
|
||||
/* 0x06AD */ u8 unk_6AD;
|
||||
/* 0x06AE */ u16 unk_6AE;
|
||||
/* 0x06B0 */ s16 unk_6B0;
|
||||
/* 0x06B2 */ char unk_6B4[0x004];
|
||||
/* 0x06B6 */ s16 unk_6B6;
|
||||
/* 0x06B8 */ s16 unk_6B8;
|
||||
/* 0x06BA */ s16 unk_6BA;
|
||||
/* 0x06BC */ s16 unk_6BC;
|
||||
/* 0x06BE */ s16 unk_6BE;
|
||||
/* 0x06C0 */ s16 unk_6C0;
|
||||
/* 0x06C2 */ s16 unk_6C2;
|
||||
/* 0x06C4 */ f32 unk_6C4;
|
||||
/* 0x06C8 */ SkelAnime upperSkelAnime;
|
||||
/* 0x070C */ Vec3s upperJointTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x079C */ Vec3s upperMorphTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x067C */ u32 stateFlags1;
|
||||
/* 0x0680 */ u32 stateFlags2;
|
||||
/* 0x0684 */ Actor* unk_684;
|
||||
/* 0x0688 */ Actor* boomerangActor;
|
||||
/* 0x068C */ Actor* naviActor;
|
||||
/* 0x0690 */ s16 naviTextId;
|
||||
/* 0x0692 */ u8 stateFlags3;
|
||||
/* 0x0693 */ s8 exchangeItemId;
|
||||
/* 0x0694 */ Actor* targetActor;
|
||||
/* 0x0698 */ f32 targetActorDistance;
|
||||
/* 0x069C */ char unk_69C[0x004];
|
||||
/* 0x06A0 */ f32 unk_6A0;
|
||||
/* 0x06A4 */ f32 closestSecretDistSq;
|
||||
/* 0x06A8 */ Actor* unk_6A8;
|
||||
/* 0x06AC */ s8 unk_6AC;
|
||||
/* 0x06AD */ u8 unk_6AD;
|
||||
/* 0x06AE */ u16 unk_6AE;
|
||||
/* 0x06B0 */ s16 unk_6B0;
|
||||
/* 0x06B2 */ char unk_6B4[0x004];
|
||||
/* 0x06B6 */ s16 unk_6B6;
|
||||
/* 0x06B8 */ s16 unk_6B8;
|
||||
/* 0x06BA */ s16 unk_6BA;
|
||||
/* 0x06BC */ s16 unk_6BC;
|
||||
/* 0x06BE */ s16 unk_6BE;
|
||||
/* 0x06C0 */ s16 unk_6C0;
|
||||
/* 0x06C2 */ s16 unk_6C2;
|
||||
/* 0x06C4 */ f32 unk_6C4;
|
||||
/* 0x06C8 */ SkelAnime upperSkelAnime;
|
||||
/* 0x070C */ Vec3s upperJointTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x079C */ Vec3s upperMorphTable[PLAYER_LIMB_BUF_COUNT];
|
||||
/* 0x082C */ UpperActionFunc upperActionFunc;
|
||||
/* 0x0830 */ f32 upperAnimBlendWeight;
|
||||
/* 0x0834 */ s16 unk_834;
|
||||
/* 0x0836 */ s8 unk_836;
|
||||
/* 0x0837 */ u8 unk_837;
|
||||
/* 0x0838 */ f32 linearVelocity;
|
||||
/* 0x083C */ s16 currentYaw;
|
||||
/* 0x083E */ s16 targetYaw;
|
||||
/* 0x0840 */ u16 underwaterTimer;
|
||||
/* 0x0842 */ s8 meleeWeaponAnimation;
|
||||
/* 0x0843 */ s8 meleeWeaponState;
|
||||
/* 0x0844 */ s8 unk_844;
|
||||
/* 0x0845 */ u8 unk_845;
|
||||
/* 0x0846 */ u8 unk_846;
|
||||
/* 0x0847 */ s8 unk_847[4];
|
||||
/* 0x084B */ s8 unk_84B[4];
|
||||
/* 0x084F */ s8 unk_84F;
|
||||
/* 0x0850 */ s16 unk_850; // multipurpose timer
|
||||
/* 0x0854 */ f32 unk_854;
|
||||
/* 0x0858 */ f32 unk_858;
|
||||
/* 0x085C */ f32 unk_85C; // stick length among other things
|
||||
/* 0x0860 */ s16 unk_860; // stick flame timer among other things
|
||||
/* 0x0862 */ s16 unk_862; // get item draw ID + 1
|
||||
/* 0x0864 */ f32 unk_864;
|
||||
/* 0x0868 */ f32 unk_868;
|
||||
/* 0x086C */ f32 unk_86C;
|
||||
/* 0x0870 */ f32 unk_870;
|
||||
/* 0x0874 */ f32 unk_874;
|
||||
/* 0x0878 */ f32 unk_878;
|
||||
/* 0x087C */ s16 unk_87C;
|
||||
/* 0x087E */ s16 unk_87E;
|
||||
/* 0x0880 */ f32 unk_880;
|
||||
/* 0x0884 */ f32 yDistToLedge; // y distance to ground above an interact wall. LEDGE_DIST_MAX if no ground is found
|
||||
/* 0x0888 */ f32 distToInteractWall; // distance to the colliding wall plane
|
||||
/* 0x088C */ u8 unk_88C;
|
||||
/* 0x088D */ u8 unk_88D;
|
||||
/* 0x088E */ u8 unk_88E;
|
||||
/* 0x088F */ u8 unk_88F;
|
||||
/* 0x0890 */ u8 unk_890;
|
||||
/* 0x0891 */ u8 shockTimer;
|
||||
/* 0x0892 */ u8 unk_892;
|
||||
/* 0x0893 */ u8 hoverBootsTimer;
|
||||
/* 0x0894 */ s16 fallStartHeight; // last truncated Y position before falling
|
||||
/* 0x0896 */ s16 fallDistance; // truncated Y distance the player has fallen so far (positive is down)
|
||||
/* 0x0898 */ s16 floorPitch; // angle of the floor slope in the direction of current world yaw (positive for ascending slope)
|
||||
/* 0x089A */ s16 floorPitchAlt; // the calculation for this value is bugged and doesn't represent anything meaningful
|
||||
/* 0x089C */ s16 unk_89C;
|
||||
/* 0x089E */ u16 floorSfxOffset;
|
||||
/* 0x08A0 */ u8 unk_8A0;
|
||||
/* 0x08A1 */ u8 unk_8A1;
|
||||
/* 0x08A2 */ s16 unk_8A2;
|
||||
/* 0x08A4 */ f32 unk_8A4;
|
||||
/* 0x08A8 */ f32 unk_8A8;
|
||||
/* 0x08AC */ f32 pushedSpeed; // Pushing player, examples include water currents, floor conveyors, climbing sloped surfaces
|
||||
/* 0x08B0 */ s16 pushedYaw; // Yaw direction of player being pushed
|
||||
/* 0x0830 */ f32 upperAnimBlendWeight;
|
||||
/* 0x0834 */ s16 unk_834;
|
||||
/* 0x0836 */ s8 unk_836;
|
||||
/* 0x0837 */ u8 unk_837;
|
||||
/* 0x0838 */ f32 linearVelocity;
|
||||
/* 0x083C */ s16 yaw; // General yaw value, used both for world and shape rotation. Current or target value depending on context.
|
||||
/* 0x083E */ s16 zTargetYaw; // yaw relating to Z targeting/"parallel" mode
|
||||
/* 0x0840 */ u16 underwaterTimer;
|
||||
/* 0x0842 */ s8 meleeWeaponAnimation;
|
||||
/* 0x0843 */ s8 meleeWeaponState;
|
||||
/* 0x0844 */ s8 unk_844;
|
||||
/* 0x0845 */ u8 unk_845;
|
||||
/* 0x0846 */ u8 unk_846;
|
||||
/* 0x0847 */ s8 unk_847[4];
|
||||
/* 0x084B */ s8 unk_84B[4];
|
||||
|
||||
/* 0x084F */ union {
|
||||
s8 actionVar1;
|
||||
} av1; // "Action Variable 1": context dependent variable that has different meanings depending on what action is currently running
|
||||
|
||||
/* 0x0850 */ union {
|
||||
s16 actionVar2;
|
||||
} av2; // "Action Variable 2": context dependent variable that has different meanings depending on what action is currently running
|
||||
|
||||
/* 0x0854 */ f32 unk_854;
|
||||
/* 0x0858 */ f32 unk_858;
|
||||
/* 0x085C */ f32 unk_85C; // stick length among other things
|
||||
/* 0x0860 */ s16 unk_860; // stick flame timer among other things
|
||||
/* 0x0862 */ s16 unk_862; // get item draw ID + 1
|
||||
/* 0x0864 */ f32 unk_864;
|
||||
/* 0x0868 */ f32 unk_868;
|
||||
/* 0x086C */ f32 unk_86C;
|
||||
/* 0x0870 */ f32 unk_870;
|
||||
/* 0x0874 */ f32 unk_874;
|
||||
/* 0x0878 */ f32 unk_878;
|
||||
/* 0x087C */ s16 unk_87C;
|
||||
/* 0x087E */ s16 unk_87E;
|
||||
/* 0x0880 */ f32 unk_880;
|
||||
/* 0x0884 */ f32 yDistToLedge; // y distance to ground above an interact wall. LEDGE_DIST_MAX if no ground is found
|
||||
/* 0x0888 */ f32 distToInteractWall; // xyz distance to the interact wall
|
||||
/* 0x088C */ u8 ledgeClimbType;
|
||||
/* 0x088D */ u8 ledgeClimbDelayTimer;
|
||||
/* 0x088E */ u8 unk_88E;
|
||||
/* 0x088F */ u8 unk_88F;
|
||||
/* 0x0890 */ u8 unk_890;
|
||||
/* 0x0891 */ u8 bodyShockTimer;
|
||||
/* 0x0892 */ u8 unk_892;
|
||||
/* 0x0893 */ u8 hoverBootsTimer;
|
||||
/* 0x0894 */ s16 fallStartHeight; // last truncated Y position before falling
|
||||
/* 0x0896 */ s16 fallDistance; // truncated Y distance the player has fallen so far (positive is down)
|
||||
/* 0x0898 */ s16 floorPitch; // angle of the floor slope in the direction of current world yaw (positive for ascending slope)
|
||||
/* 0x089A */ s16 floorPitchAlt; // the calculation for this value is bugged and doesn't represent anything meaningful
|
||||
/* 0x089C */ s16 unk_89C;
|
||||
/* 0x089E */ u16 floorSfxOffset;
|
||||
/* 0x08A0 */ u8 unk_8A0;
|
||||
/* 0x08A1 */ u8 unk_8A1;
|
||||
/* 0x08A2 */ s16 unk_8A2;
|
||||
/* 0x08A4 */ f32 unk_8A4;
|
||||
/* 0x08A8 */ f32 unk_8A8;
|
||||
/* 0x08AC */ f32 pushedSpeed; // Pushing player, examples include water currents, floor conveyors, climbing sloped surfaces
|
||||
/* 0x08B0 */ s16 pushedYaw; // Yaw direction of player being pushed
|
||||
/* 0x08B4 */ WeaponInfo meleeWeaponInfo[3];
|
||||
/* 0x0908 */ Vec3f bodyPartsPos[PLAYER_BODYPART_MAX];
|
||||
/* 0x09E0 */ MtxF mf_9E0;
|
||||
/* 0x0A20 */ MtxF shieldMf;
|
||||
/* 0x0A60 */ u8 isBurning;
|
||||
/* 0x0A61 */ u8 flameTimers[PLAYER_BODYPART_MAX]; // one flame per body part
|
||||
/* 0x0A73 */ u8 unk_A73;
|
||||
/* 0x0908 */ Vec3f bodyPartsPos[PLAYER_BODYPART_MAX];
|
||||
/* 0x09E0 */ MtxF mf_9E0;
|
||||
/* 0x0A20 */ MtxF shieldMf;
|
||||
/* 0x0A60 */ u8 bodyIsBurning;
|
||||
/* 0x0A61 */ u8 bodyFlameTimers[PLAYER_BODYPART_MAX]; // one flame per body part
|
||||
/* 0x0A73 */ u8 unk_A73;
|
||||
/* 0x0A74 */ PlayerFuncA74 func_A74;
|
||||
/* 0x0A78 */ s8 invincibilityTimer; // prevents damage when nonzero (positive = visible, counts towards zero each frame)
|
||||
/* 0x0A79 */ u8 unk_A79;
|
||||
/* 0x0A7A */ u8 unk_A7A;
|
||||
/* 0x0A7B */ u8 unk_A7B;
|
||||
/* 0x0A7C */ f32 unk_A7C;
|
||||
/* 0x0A80 */ s16 unk_A80;
|
||||
/* 0x0A82 */ u16 unk_A82;
|
||||
/* 0x0A84 */ s16 unk_A84;
|
||||
/* 0x0A86 */ s8 unk_A86;
|
||||
/* 0x0A87 */ u8 unk_A87;
|
||||
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
|
||||
/* 0x0A78 */ s8 invincibilityTimer; // prevents damage when nonzero (positive = visible, counts towards zero each frame)
|
||||
/* 0x0A79 */ u8 floorTypeTimer; // counts up every frame the current floor type is the same as the last frame
|
||||
/* 0x0A7A */ u8 floorProperty;
|
||||
/* 0x0A7B */ u8 prevFloorType;
|
||||
/* 0x0A7C */ f32 prevControlStickMagnitude;
|
||||
/* 0x0A80 */ s16 prevControlStickAngle;
|
||||
/* 0x0A82 */ u16 prevFloorSfxOffset;
|
||||
/* 0x0A84 */ s16 unk_A84;
|
||||
/* 0x0A86 */ s8 unk_A86;
|
||||
/* 0x0A87 */ u8 unk_A87;
|
||||
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
|
||||
// #region SOH [General]
|
||||
// Upstream TODO: Rename these to be more obviously SoH specific
|
||||
/* */ PendingFlag pendingFlag;
|
||||
|
@ -670,7 +677,7 @@ typedef struct Player {
|
|||
// #endregion
|
||||
// #region SOH [Enhancements]
|
||||
// Upstream TODO: Rename this to make it more obvious it is apart of an enhancement
|
||||
/* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
|
||||
/* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
|
||||
// #endregion
|
||||
u8 ivanFloating;
|
||||
u8 ivanDamageMultiplier;
|
||||
|
|
|
@ -7,68 +7,6 @@ export RESPATH="${SNAME%/MacOS*}/Resources"
|
|||
export LIBPATH="${SNAME%/MacOS*}/Frameworks"
|
||||
export DYLD_FALLBACK_LIBRARY_PATH="$LIBPATH"
|
||||
|
||||
remap_hashes ()
|
||||
{
|
||||
# Remap v64 and n64 hashes to their z64 hash equivalent
|
||||
# ZAPD will handle converting the data into z64 format
|
||||
case "$ROMHASH" in
|
||||
a9059b56e761c9034fbe02fe4c24985aaa835dac) # v64
|
||||
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
|
||||
;;
|
||||
24708102dc504d3f375a37f4ae4e149c167dc515) # n64
|
||||
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
|
||||
;;
|
||||
580dd0bd1b6d2c51cc20a764eece84dba558964c) # v64
|
||||
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
|
||||
;;
|
||||
d6342c59007e57c1194661ec6880b2f078403f4e) # n64
|
||||
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
|
||||
;;
|
||||
d0bdc2eb320668b4ba6893b9aefe4040a73123ff) # v64
|
||||
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
|
||||
;;
|
||||
4946ab250f6ac9b32d76b21f309ebb8ebc8103d2) # n64
|
||||
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
|
||||
;;
|
||||
663c34f1b2c05a09e5beffe4d0dcd440f7d49dc7) # v64
|
||||
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
|
||||
;;
|
||||
24c73d378b0620a380ce5ef9f2b186c6c157a68b) # n64
|
||||
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
|
||||
;;
|
||||
8ebf2e29313f44f2d49e5b4191971d09919e8e48) # v64
|
||||
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
|
||||
;;
|
||||
4264bf7b875737b8fae77d52322a5099d051fc11) # n64
|
||||
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
|
||||
;;
|
||||
973bc6fe56010a8d646166a1182a81b4f13b8cf9) # v64
|
||||
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
|
||||
;;
|
||||
d327752c46edc70ff3668b9514083dbbee08927c) # v64
|
||||
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
|
||||
;;
|
||||
ecdeb1747560834e079c22243febea7f6f26ba3b) # v64
|
||||
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
|
||||
;;
|
||||
f19f8662ec7abee29484a272a6fda53e39efe0f1) # n64
|
||||
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
|
||||
;;
|
||||
ab519ce04a33818ce2c39b3c514a751d807a494a) # v64
|
||||
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
|
||||
;;
|
||||
c19a34f7646305e1755249fca2071e178bd7cd00) # n64
|
||||
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
|
||||
;;
|
||||
25e8ae79ea0839ca5c984473f7460d8040c36f9c) # v64
|
||||
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
|
||||
;;
|
||||
166c02770d67fcc3954c443eb400a6a3573d3fc0) # n64
|
||||
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ ! -e "$SHIP_HOME" ]; then mkdir "$SHIP_HOME"; fi
|
||||
|
||||
if [ ! -e "$SHIP_HOME"/mods ]; then
|
||||
|
@ -76,178 +14,6 @@ if [ ! -e "$SHIP_HOME"/mods ]; then
|
|||
touch "$SHIP_HOME"/mods/custom_otr_files_go_here.txt
|
||||
fi
|
||||
|
||||
# If either OTR doesn't exist kick off the OTR gen process
|
||||
if [ ! -e "$SHIP_HOME"/oot.otr ] || [ ! -e "$SHIP_HOME"/oot-mq.otr ]; then
|
||||
|
||||
# If no ROMs exist kick off the file selection prompts
|
||||
while [ ! -e "$SHIP_HOME"/*.*64 ] && [ ! -e "$SHIP_HOME"/oot*.otr ]; do
|
||||
|
||||
SHOULD_PROMPT_FOR_ROM=1
|
||||
while [ $SHOULD_PROMPT_FOR_ROM -eq 1 ]; do
|
||||
SHOULD_PROMPT_FOR_ROM=0
|
||||
# Use osascript to prompt the user to chose a file
|
||||
DROPROM=`osascript <<-EOF
|
||||
set romFile to choose file of type {"b64","n64","v64","z64"} with prompt "Please select your ROM:"
|
||||
return POSIX path of romFile
|
||||
EOF`
|
||||
|
||||
# If no rom was selected, the user cancelled, so exit
|
||||
if [[ -z $DROPROM ]] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
|
||||
echo "No ROM selected. Exiting..."
|
||||
exit 1
|
||||
elif [[ -z $DROPROM ]]; then
|
||||
break;
|
||||
fi
|
||||
|
||||
# If an invalid rom was selected, let the user know and ask to try again
|
||||
ROMHASH="$(shasum "$DROPROM" | awk '{ print $1 }')"
|
||||
|
||||
remap_hashes
|
||||
|
||||
case "$ROMHASH" in
|
||||
cee6bc3c2a634b41728f2af8da54d9bf8cc14099)
|
||||
ROM_TYPE=0;;
|
||||
0227d7c0074f2d0ac935631990da8ec5914597b4)
|
||||
ROM_TYPE=0;;
|
||||
328a1f1beba30ce5e178f031662019eb32c5f3b5)
|
||||
ROM_TYPE=0;;
|
||||
cfbb98d392e4a9d39da8285d10cbef3974c2f012)
|
||||
ROM_TYPE=0;;
|
||||
f46239439f59a2a594ef83cf68ef65043b1bffe2)
|
||||
ROM_TYPE=1;;
|
||||
50bebedad9e0f10746a52b07239e47fa6c284d03)
|
||||
ROM_TYPE=1;;
|
||||
079b855b943d6ad8bd1eb026c0ed169ecbdac7da)
|
||||
ROM_TYPE=1;;
|
||||
cfecfdc58d650e71a200c81f033de4e6d617a9f6)
|
||||
ROM_TYPE=1;;
|
||||
517bd9714c73cb96c21e7c2ef640d7b55186102f)
|
||||
ROM_TYPE=1;;
|
||||
*)
|
||||
TRY_AGAIN_RESULT=`osascript <<-EOF
|
||||
set alertText to "Incompatible ROM hash"
|
||||
set alertMessage to "Incompatible ROM provided, would you like to try again?"
|
||||
return display alert alertText \
|
||||
message alertMessage \
|
||||
as critical \
|
||||
buttons {"Cancel", "Try Again"}
|
||||
EOF`
|
||||
if [[ "$TRY_AGAIN_RESULT" == "button returned:Try Again" ]]; then
|
||||
SHOULD_PROMPT_FOR_ROM=1
|
||||
continue;
|
||||
else
|
||||
echo "No ROM selected. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
esac
|
||||
|
||||
cp "$DROPROM" "$SHIP_HOME"
|
||||
|
||||
# Ask user if they would also like to select the other variant (MQ/Vanilla)
|
||||
if [ $ROM_TYPE -eq 0 ] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
|
||||
UPLOAD_ANOTHER_RESULT=`osascript <<-EOF
|
||||
set alertText to "Success"
|
||||
set alertMessage to "Would you also like to provide a Master Quest ROM?"
|
||||
return display alert alertText \
|
||||
message alertMessage \
|
||||
buttons {"No", "Yes"}
|
||||
EOF`
|
||||
elif [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
|
||||
UPLOAD_ANOTHER_RESULT=`osascript <<-EOF
|
||||
set alertText to "Success"
|
||||
set alertMessage to "Would you also like to provide a Vanilla (Non Master Quest) ROM?"
|
||||
return display alert alertText \
|
||||
message alertMessage \
|
||||
buttons {"No", "Yes"}
|
||||
EOF`
|
||||
fi
|
||||
|
||||
if [[ "$UPLOAD_ANOTHER_RESULT" == "button returned:Yes" ]]; then
|
||||
UPLOAD_ANOTHER_RESULT="button returned:No"
|
||||
SHOULD_PROMPT_FOR_ROM=1
|
||||
continue;
|
||||
fi
|
||||
break
|
||||
done
|
||||
done
|
||||
|
||||
# At this point we should now have 1 or more valid roms in $SHIP_HOME directory
|
||||
|
||||
# Prepare tmp dir
|
||||
for ROMPATH in "$SHIP_HOME"/*.*64
|
||||
do
|
||||
ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)"
|
||||
export ASSETDIR
|
||||
cp -r "$RESPATH/assets" "$ASSETDIR"
|
||||
mkdir -p "$ASSETDIR"/tmp
|
||||
cp "$ROMPATH" "$ASSETDIR"/tmp/rom.z64
|
||||
cd "$ASSETDIR" || return
|
||||
|
||||
# If an invalid rom was detected, let the user know
|
||||
ROMHASH="$(shasum "$ASSETDIR"/tmp/rom.z64 | awk '{ print $1 }')"
|
||||
|
||||
remap_hashes
|
||||
|
||||
case "$ROMHASH" in
|
||||
cee6bc3c2a634b41728f2af8da54d9bf8cc14099)
|
||||
ROM=GC_NMQ_D
|
||||
OTRNAME="oot.otr";;
|
||||
0227d7c0074f2d0ac935631990da8ec5914597b4)
|
||||
ROM=GC_NMQ_PAL_F
|
||||
OTRNAME="oot.otr";;
|
||||
328a1f1beba30ce5e178f031662019eb32c5f3b5)
|
||||
ROM=N64_PAL_10
|
||||
OTRNAME="oot.otr";;
|
||||
cfbb98d392e4a9d39da8285d10cbef3974c2f012)
|
||||
ROM=N64_PAL_11
|
||||
OTRNAME="oot.otr";;
|
||||
f46239439f59a2a594ef83cf68ef65043b1bffe2)
|
||||
ROM=GC_MQ_PAL_F
|
||||
OTRNAME="oot-mq.otr";;
|
||||
50bebedad9e0f10746a52b07239e47fa6c284d03)
|
||||
ROM=GC_MQ_D
|
||||
OTRNAME="oot-mq.otr";;
|
||||
079b855b943d6ad8bd1eb026c0ed169ecbdac7da)
|
||||
ROM=GC_MQ_D
|
||||
OTRNAME="oot-mq.otr";;
|
||||
cfecfdc58d650e71a200c81f033de4e6d617a9f6)
|
||||
ROM=GC_MQ_D
|
||||
OTRNAME="oot-mq.otr";;
|
||||
517bd9714c73cb96c21e7c2ef640d7b55186102f)
|
||||
ROM=GC_MQ_D
|
||||
OTRNAME="oot-mq.otr";;
|
||||
*)
|
||||
osascript -e 'display notification "One or more invalid ROM provided" with title "Ship Of Harkinian"'
|
||||
rm -r "$ASSETDIR"
|
||||
cd "$SNAME"
|
||||
continue;
|
||||
esac
|
||||
|
||||
# Only generate OTR if we don't have on of this type yet
|
||||
if [ -e "$SHIP_HOME"/"$OTRNAME" ]; then
|
||||
rm -r "$ASSETDIR"
|
||||
cd "$SNAME"
|
||||
continue;
|
||||
fi
|
||||
|
||||
osascript -e 'display notification "Generating OTR..." with title "Ship Of Harkinian"'
|
||||
assets/extractor/ZAPD.out ed -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR --portVer "@CMAKE_PROJECT_VERSION@"
|
||||
if [ -e "$ASSETDIR"/oot.otr ]; then
|
||||
osascript -e 'display notification "OTR successfully generated" with title "Ship Of Harkinian"'
|
||||
cp "$ASSETDIR"/oot.otr "$SHIP_HOME"/"$OTRNAME"
|
||||
rm -r "$ASSETDIR"
|
||||
cd "$SNAME"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -e "$SHIP_HOME"/oot*.otr ]; then
|
||||
osascript -e 'display notification "OTR failed to generate" with title "Ship Of Harkinian"'
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
cd "$SNAME"
|
||||
|
||||
"$RESPATH"/soh-macos
|
||||
|
||||
exit
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <Utils/StringHelper.h>
|
||||
#include <libultraship/bridge.h>
|
||||
#include <libultraship/classes.h>
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include <locale>
|
||||
#include <filesystem>
|
||||
|
||||
|
@ -330,11 +331,13 @@ AudioCollection::AudioCollection() {
|
|||
}
|
||||
|
||||
std::string AudioCollection::GetCvarKey(std::string sfxKey) {
|
||||
return "gAudioEditor.ReplacedSequences." + sfxKey + ".value";
|
||||
auto prefix = CVAR_AUDIO("ReplacedSequences.");
|
||||
return prefix + sfxKey + ".value";
|
||||
}
|
||||
|
||||
std::string AudioCollection::GetCvarLockKey(std::string sfxKey) {
|
||||
return "gAudioEditor.ReplacedSequences." + sfxKey + ".locked";
|
||||
auto prefix = std::string(CVAR_AUDIO("ReplacedSequences."));
|
||||
return prefix + sfxKey + ".locked";
|
||||
}
|
||||
|
||||
void AudioCollection::AddToCollection(char* otrPath, uint16_t seqNum) {
|
||||
|
@ -362,7 +365,7 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) {
|
|||
// for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will
|
||||
// play the normal track as usual.
|
||||
if (seqId == NA_BGM_FIELD_MORNING) {
|
||||
if (CVarGetInteger("gAudioEditor.ReplacedSequences.NA_BGM_FIELD_LOGIC.value", NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) {
|
||||
if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) {
|
||||
seqId = NA_BGM_FIELD_LOGIC;
|
||||
}
|
||||
}
|
||||
|
@ -381,19 +384,19 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) {
|
|||
}
|
||||
|
||||
void AudioCollection::RemoveFromShufflePool(SequenceInfo* seqInfo) {
|
||||
const std::string cvarKey = "gAudioEditor.Excluded." + seqInfo->sfxKey;
|
||||
const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo->sfxKey;
|
||||
excludedSequences.insert(seqInfo);
|
||||
includedSequences.erase(seqInfo);
|
||||
CVarSetInteger(cvarKey.c_str(), 1);
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
|
||||
void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) {
|
||||
const std::string cvarKey = "gAudioEditor.Excluded." + seqInfo->sfxKey;
|
||||
const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo->sfxKey;
|
||||
includedSequences.insert(seqInfo);
|
||||
excludedSequences.erase(seqInfo);
|
||||
CVarClear(cvarKey.c_str());
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
|
||||
void AudioCollection::InitializeShufflePool() {
|
||||
|
@ -401,7 +404,7 @@ void AudioCollection::InitializeShufflePool() {
|
|||
|
||||
for (auto& [seqId, seqInfo] : sequenceMap) {
|
||||
if (!seqInfo.canBeUsedAsReplacement) continue;
|
||||
const std::string cvarKey = "gAudioEditor.Excluded." + seqInfo.sfxKey;
|
||||
const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey;
|
||||
if (CVarGetInteger(cvarKey.c_str(), 0)) {
|
||||
excludedSequences.insert(&seqInfo);
|
||||
} else {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <Utils/StringHelper.h>
|
||||
#include "../../UIWidgets.hpp"
|
||||
#include "AudioCollection.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
|
||||
Vec3f pos = { 0.0f, 0.0f, 0.0f };
|
||||
f32 freqScale = 1.0f;
|
||||
|
@ -78,7 +79,12 @@ void UpdateCurrentBGM(u16 seqKey, SeqType seqType) {
|
|||
|
||||
void RandomizeGroup(SeqType type) {
|
||||
std::vector<u16> values;
|
||||
|
||||
|
||||
// An empty IncludedSequences set means that the AudioEditor window has never been drawn
|
||||
if (AudioCollection::Instance->GetIncludedSequences().empty()) {
|
||||
AudioCollection::Instance->InitializeShufflePool();
|
||||
}
|
||||
|
||||
// use a while loop to add duplicates if we don't have enough included sequences
|
||||
while (values.size() < AuthenticCountBySequenceType(type)) {
|
||||
for (const auto& seqData : AudioCollection::Instance->GetIncludedSequences()) {
|
||||
|
@ -123,23 +129,51 @@ void ResetGroup(const std::map<u16, SequenceInfo>& map, SeqType type) {
|
|||
}
|
||||
}
|
||||
|
||||
void LockGroup(const std::map<u16, SequenceInfo>& map, SeqType type) {
|
||||
for (const auto& [defaultValue, seqData] : map) {
|
||||
if (seqData.category == type) {
|
||||
// Only save authentic sequence CVars
|
||||
if (seqData.category == SEQ_FANFARE && defaultValue >= MAX_AUTHENTIC_SEQID) {
|
||||
continue;
|
||||
}
|
||||
const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey);
|
||||
const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey);
|
||||
CVarSetInteger(cvarLockKey.c_str(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnlockGroup(const std::map<u16, SequenceInfo>& map, SeqType type) {
|
||||
for (const auto& [defaultValue, seqData] : map) {
|
||||
if (seqData.category == type) {
|
||||
// Only save authentic sequence CVars
|
||||
if (seqData.category == SEQ_FANFARE && defaultValue >= MAX_AUTHENTIC_SEQID) {
|
||||
continue;
|
||||
}
|
||||
const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey);
|
||||
const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey);
|
||||
CVarSetInteger(cvarLockKey.c_str(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequenceType) {
|
||||
const std::string cvarKey = AudioCollection::Instance->GetCvarKey(sfxKey);
|
||||
const std::string hiddenKey = "##" + cvarKey;
|
||||
const std::string stopButton = ICON_FA_STOP + hiddenKey;
|
||||
const std::string previewButton = ICON_FA_PLAY + hiddenKey;
|
||||
|
||||
if (CVarGetInteger("gAudioEditor.Playing", 0) == sequenceId) {
|
||||
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) == sequenceId) {
|
||||
if (ImGui::Button(stopButton.c_str())) {
|
||||
func_800F5C2C();
|
||||
CVarSetInteger("gAudioEditor.Playing", 0);
|
||||
CVarSetInteger(CVAR_AUDIO("Playing"), 0);
|
||||
}
|
||||
UIWidgets::Tooltip("Stop Preview");
|
||||
} else {
|
||||
if (ImGui::Button(previewButton.c_str())) {
|
||||
if (CVarGetInteger("gAudioEditor.Playing", 0) != 0) {
|
||||
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) != 0) {
|
||||
func_800F5C2C();
|
||||
CVarSetInteger("gAudioEditor.Playing", 0);
|
||||
CVarSetInteger(CVAR_AUDIO("Playing"), 0);
|
||||
} else {
|
||||
if (sequenceType == SEQ_SFX || sequenceType == SEQ_VOICE) {
|
||||
Audio_PlaySoundGeneral(sequenceId, &pos, 4, &freqScale, &freqScale, &reverbAdd);
|
||||
|
@ -149,7 +183,7 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence
|
|||
} else {
|
||||
// TODO: Cant do both here, so have to click preview button twice
|
||||
PreviewSequence(sequenceId);
|
||||
CVarSetInteger("gAudioEditor.Playing", sequenceId);
|
||||
CVarSetInteger(CVAR_AUDIO("Playing"), sequenceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,11 +197,13 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
|
|||
const std::string hiddenTabId = "##" + tabId;
|
||||
const std::string resetAllButton = "Reset All" + hiddenTabId;
|
||||
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())) {
|
||||
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
|
||||
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
ResetGroup(map, type);
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) {
|
||||
ReplayCurrentBGM();
|
||||
|
@ -178,7 +214,29 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
|
|||
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
|
||||
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
RandomizeGroup(type);
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) {
|
||||
ReplayCurrentBGM();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(lockAllButton.c_str())) {
|
||||
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
|
||||
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
LockGroup(map, type);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) {
|
||||
ReplayCurrentBGM();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(unlockAllButton.c_str())) {
|
||||
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
|
||||
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
UnlockGroup(map, type);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
|
||||
if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) {
|
||||
ReplayCurrentBGM();
|
||||
|
@ -223,7 +281,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
|
|||
|
||||
if (ImGui::Selectable(seqData.label.c_str())) {
|
||||
CVarSetInteger(cvarKey.c_str(), value);
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
UpdateCurrentBGM(defaultValue, type);
|
||||
}
|
||||
|
||||
|
@ -243,7 +301,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
|
|||
if (ImGui::Button(resetButton.c_str())) {
|
||||
CVarClear(cvarKey.c_str());
|
||||
CVarClear(cvarLockKey.c_str());
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
UpdateCurrentBGM(defaultValue, seqData.category);
|
||||
}
|
||||
UIWidgets::Tooltip("Reset to default");
|
||||
|
@ -264,7 +322,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
|
|||
if (locked) {
|
||||
CVarClear(cvarLockKey.c_str());
|
||||
}
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
UpdateCurrentBGM(defaultValue, type);
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +335,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
|
|||
} else {
|
||||
CVarSetInteger(cvarLockKey.c_str(), 1);
|
||||
}
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
UIWidgets::Tooltip(locked ? "Sound locked" : "Sound unlocked");
|
||||
}
|
||||
|
@ -350,6 +408,19 @@ void DrawTypeChip(SeqType type) {
|
|||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
|
||||
void AudioEditorRegisterOnSceneInitHook() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
|
||||
if (CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) {
|
||||
AudioEditor_RandomizeAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AudioEditor::InitElement() {
|
||||
AudioEditorRegisterOnSceneInitHook();
|
||||
}
|
||||
|
||||
void AudioEditor::DrawElement() {
|
||||
AudioCollection::Instance->InitializeShufflePool();
|
||||
|
||||
|
@ -359,6 +430,28 @@ void AudioEditor::DrawElement() {
|
|||
return;
|
||||
}
|
||||
|
||||
float buttonSegments = ImGui::GetContentRegionAvail().x / 4;
|
||||
if (ImGui::Button("Randomize All Groups", ImVec2(buttonSegments, 30.0f))) {
|
||||
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))) {
|
||||
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))) {
|
||||
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))) {
|
||||
AudioEditor_UnlockAll();
|
||||
}
|
||||
UIWidgets::Tooltip("Unlocks all music and sound effects across tab groups");
|
||||
|
||||
|
||||
if (ImGui::BeginTabBar("SfxContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
|
||||
if (ImGui::BeginTabItem("Background Music")) {
|
||||
Draw_SfxTab("backgroundMusic", SEQ_BGM_WORLD);
|
||||
|
@ -399,18 +492,18 @@ void AudioEditor::DrawElement() {
|
|||
ImGui::TableNextColumn();
|
||||
if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) {
|
||||
ImGui::PushItemWidth(-FLT_MIN);
|
||||
UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", "gEnemyBGMDisable");
|
||||
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", "gLostWoodsConsistentVolume");
|
||||
UIWidgets::EnhancementCheckbox("Disable Leading Music in Lost Woods", CVAR_AUDIO("LostWoodsConsistentVolume"));
|
||||
UIWidgets::InsertHelpHoverText(
|
||||
"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", "gSeqNameOverlay");
|
||||
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)."
|
||||
|
@ -418,24 +511,28 @@ void AudioEditor::DrawElement() {
|
|||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
UIWidgets::EnhancementSliderInt("Overlay Duration: %d seconds", "##SeqNameOverlayDuration",
|
||||
"gSeqNameOverlayDuration", 1, 10, "", 5);
|
||||
CVAR_AUDIO("SeqNameOverlayDuration"), 1, 10, "", 5);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::NewLine();
|
||||
ImGui::PopItemWidth();
|
||||
UIWidgets::EnhancementSliderFloat("Link's voice pitch multiplier: %.1f %%", "##linkVoiceFreqMultiplier",
|
||||
"gLinkVoiceFreqMultiplier", 0.4, 2.5, "", 1.0, true, true);
|
||||
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())) {
|
||||
CVarSetFloat("gLinkVoiceFreqMultiplier", 1.0f);
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
CVarSetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0f);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
|
||||
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", "gExperimentalOctaveDrop");
|
||||
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 "
|
||||
"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 "
|
||||
|
@ -613,7 +710,14 @@ void AudioEditor_RandomizeAll() {
|
|||
RandomizeGroup(type);
|
||||
}
|
||||
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
ReplayCurrentBGM();
|
||||
}
|
||||
|
||||
void AudioEditor_RandomizeGroup(SeqType group) {
|
||||
RandomizeGroup(group);
|
||||
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
ReplayCurrentBGM();
|
||||
}
|
||||
|
||||
|
@ -622,6 +726,29 @@ void AudioEditor_ResetAll() {
|
|||
ResetGroup(AudioCollection::Instance->GetAllSequences(), type);
|
||||
}
|
||||
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
ReplayCurrentBGM();
|
||||
}
|
||||
|
||||
void AudioEditor_ResetGroup(SeqType group) {
|
||||
ResetGroup(AudioCollection::Instance->GetAllSequences(), group);
|
||||
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
ReplayCurrentBGM();
|
||||
}
|
||||
|
||||
void AudioEditor_LockAll() {
|
||||
for (auto type : allTypes) {
|
||||
LockGroup(AudioCollection::Instance->GetAllSequences(), type);
|
||||
}
|
||||
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
|
||||
void AudioEditor_UnlockAll() {
|
||||
for (auto type : allTypes) {
|
||||
UnlockGroup(AudioCollection::Instance->GetAllSequences(), type);
|
||||
}
|
||||
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
|
|
|
@ -8,19 +8,24 @@
|
|||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#endif
|
||||
#include <ImGui/imgui.h>
|
||||
#include "AudioCollection.h"
|
||||
|
||||
class AudioEditor : public LUS::GuiWindow {
|
||||
class AudioEditor : public Ship::GuiWindow {
|
||||
public:
|
||||
using LUS::GuiWindow::GuiWindow;
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
void DrawElement() override;
|
||||
void InitElement() override {};
|
||||
void InitElement() override;
|
||||
void UpdateElement() override {};
|
||||
~AudioEditor() {};
|
||||
};
|
||||
|
||||
void AudioEditor_RandomizeAll();
|
||||
void AudioEditor_RandomizeGroup(SeqType group);
|
||||
void AudioEditor_ResetAll();
|
||||
void AudioEditor_ResetGroup(SeqType group);
|
||||
void AudioEditor_LockAll();
|
||||
void AudioEditor_UnlockAll();
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -1,355 +0,0 @@
|
|||
#include "GameControlEditor.h"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
#include <variables.h>
|
||||
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#endif
|
||||
#include <ImGui/imgui.h>
|
||||
#include <ImGui/imgui_internal.h>
|
||||
#include <libultraship/bridge.h>
|
||||
#include <libultraship/libultra/controller.h>
|
||||
#include <Utils/StringHelper.h>
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
#include "../../UIWidgets.hpp"
|
||||
|
||||
namespace GameControlEditor {
|
||||
const ImGuiTableFlags PANEL_TABLE_FLAGS =
|
||||
ImGuiTableFlags_BordersH |
|
||||
ImGuiTableFlags_BordersV;
|
||||
const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS =
|
||||
ImGuiTableColumnFlags_IndentEnable |
|
||||
ImGuiTableColumnFlags_NoSort;
|
||||
|
||||
namespace TableHelper {
|
||||
void InitHeader(bool has_header = true) {
|
||||
if (has_header) {
|
||||
ImGui::TableHeadersRow();
|
||||
}
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding(); //This is to adjust Vertical pos of item in a cell to be normlized.
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
}
|
||||
|
||||
void NextCol() {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
}
|
||||
|
||||
void NextLine() {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawHelpIcon(const std::string& helptext) {
|
||||
// place the ? button to the most of the right side of the cell it is using.
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22);
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15);
|
||||
ImGui::SmallButton("?");
|
||||
UIWidgets::Tooltip(helptext.c_str());
|
||||
}
|
||||
|
||||
typedef uint32_t N64ButtonMask;
|
||||
|
||||
// Used together for an incomplete linked hash map implementation in order to
|
||||
// map button masks to their names and original mapping on N64
|
||||
static std::list<std::pair<N64ButtonMask, const char*>> buttons;
|
||||
static std::unordered_map<N64ButtonMask, decltype(buttons)::iterator> buttonNames;
|
||||
|
||||
void addButtonName(N64ButtonMask mask, const char* name) {
|
||||
buttons.push_back(std::make_pair(mask, name));
|
||||
buttonNames[mask] = std::prev(buttons.end());
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char* label;
|
||||
const char* cVarName;
|
||||
N64ButtonMask defaultBtn;
|
||||
} CustomButtonMap;
|
||||
|
||||
// Ocarina button maps
|
||||
static CustomButtonMap ocarinaD5 = {"D5", "gOcarinaD5BtnMap", BTN_CUP};
|
||||
static CustomButtonMap ocarinaB4 = {"B4", "gOcarinaB4BtnMap", BTN_CLEFT};
|
||||
static CustomButtonMap ocarinaA4 = {"A4", "gOcarinaA4BtnMap", BTN_CRIGHT};
|
||||
static CustomButtonMap ocarinaF4 = {"F4", "gOcarinaF4BtnMap", BTN_CDOWN};
|
||||
static CustomButtonMap ocarinaD4 = {"D4", "gOcarinaD4BtnMap", BTN_A};
|
||||
static CustomButtonMap ocarinaSongDisable = {"Disable songs", "gOcarinaDisableBtnMap", BTN_L};
|
||||
static CustomButtonMap ocarinaSharp = {"Pitch up", "gOcarinaSharpBtnMap", BTN_R};
|
||||
static CustomButtonMap ocarinaFlat = {"Pitch down", "gOcarinaFlatBtnMap", BTN_Z};
|
||||
|
||||
void GameControlEditorWindow::InitElement() {
|
||||
addButtonName(BTN_A, "A");
|
||||
addButtonName(BTN_B, "B");
|
||||
addButtonName(BTN_CUP, "C Up");
|
||||
addButtonName(BTN_CDOWN, "C Down");
|
||||
addButtonName(BTN_CLEFT, "C Left");
|
||||
addButtonName(BTN_CRIGHT, "C Right");
|
||||
addButtonName(BTN_L, "L");
|
||||
addButtonName(BTN_Z, "Z");
|
||||
addButtonName(BTN_R, "R");
|
||||
addButtonName(BTN_START, "Start");
|
||||
addButtonName(BTN_DUP, "D-pad up");
|
||||
addButtonName(BTN_DDOWN, "D-pad down");
|
||||
addButtonName(BTN_DLEFT, "D-pad left");
|
||||
addButtonName(BTN_DRIGHT, "D-pad right");
|
||||
addButtonName(0, "None");
|
||||
}
|
||||
|
||||
// Draw a button mapping setting consisting of a padded label and button dropdown.
|
||||
// excludedButtons indicates which buttons are unavailable to choose from.
|
||||
void DrawMapping(CustomButtonMap& mapping, float labelWidth, N64ButtonMask excludedButtons) {
|
||||
N64ButtonMask currentButton = CVarGetInteger(mapping.cVarName, mapping.defaultBtn);
|
||||
|
||||
const char* preview;
|
||||
if (buttonNames.contains(currentButton)) {
|
||||
preview = buttonNames[currentButton]->second;
|
||||
} else {
|
||||
preview = "Unknown";
|
||||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
ImVec2 cursorPos = ImGui::GetCursorPos();
|
||||
ImVec2 textSize = ImGui::CalcTextSize(mapping.label);
|
||||
ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4);
|
||||
ImGui::SetCursorPosX(cursorPos.x + abs(textSize.x - labelWidth));
|
||||
ImGui::Text("%s", mapping.label);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(cursorPos.y);
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
if (ImGui::BeginCombo(StringHelper::Sprintf("##%s", mapping.cVarName).c_str(), preview)) {
|
||||
for (auto i = buttons.begin(); i != buttons.end(); i++) {
|
||||
if ((i->first & excludedButtons) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (ImGui::Selectable(i->second, i->first == currentButton)) {
|
||||
CVarSetInteger(mapping.cVarName, i->first);
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
UIWidgets::Spacer(0);
|
||||
}
|
||||
|
||||
void DrawOcarinaControlPanel(GameControlEditorWindow* window) {
|
||||
if (!ImGui::CollapsingHeader("Ocarina Controls")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ImGui::BeginTable("tableCustomOcarinaControls", 1, PANEL_TABLE_FLAGS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::TableSetupColumn("Custom Ocarina Controls", PANEL_TABLE_COLUMN_FLAGS | ImGuiTableColumnFlags_WidthStretch);
|
||||
TableHelper::InitHeader(false);
|
||||
|
||||
ImVec2 cursor = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
|
||||
UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls");
|
||||
|
||||
if (CVarGetInteger("gCustomOcarinaControls", 0) == 1) {
|
||||
if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) {
|
||||
float labelWidth;
|
||||
N64ButtonMask disableMask = BTN_B;
|
||||
if (CVarGetInteger("gDpadOcarina", 0)) {
|
||||
disableMask |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
|
||||
}
|
||||
|
||||
ImGui::TableSetupColumn("Notes##CustomOcarinaNotes", PANEL_TABLE_COLUMN_FLAGS);
|
||||
ImGui::TableSetupColumn("Modifiers##CustomOcaranaModifiers", PANEL_TABLE_COLUMN_FLAGS);
|
||||
TableHelper::InitHeader(false);
|
||||
|
||||
window->BeginGroupPanelPublic("Notes", ImGui::GetContentRegionAvail());
|
||||
labelWidth = ImGui::CalcTextSize("D5").x + 10;
|
||||
DrawMapping(ocarinaD5, labelWidth, disableMask);
|
||||
DrawMapping(ocarinaB4, labelWidth, disableMask);
|
||||
DrawMapping(ocarinaA4, labelWidth, disableMask);
|
||||
DrawMapping(ocarinaF4, labelWidth, disableMask);
|
||||
DrawMapping(ocarinaD4, labelWidth, disableMask);
|
||||
ImGui::Dummy(ImVec2(0, 5));
|
||||
float cursorY = ImGui::GetCursorPosY();
|
||||
window->EndGroupPanelPublic(0);
|
||||
|
||||
TableHelper::NextCol();
|
||||
|
||||
window->BeginGroupPanelPublic("Modifiers", ImGui::GetContentRegionAvail());
|
||||
labelWidth = ImGui::CalcTextSize(ocarinaSongDisable.label).x + 10;
|
||||
DrawMapping(ocarinaSongDisable, labelWidth, disableMask);
|
||||
DrawMapping(ocarinaSharp, labelWidth, disableMask);
|
||||
DrawMapping(ocarinaFlat, labelWidth, disableMask);
|
||||
window->EndGroupPanelPublic(cursorY - ImGui::GetCursorPosY() + 2);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
} else {
|
||||
UIWidgets::Spacer(0);
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextWrapped("To modify the main ocarina controls, select the \"Customize Ocarina Controls\" checkbox.");
|
||||
UIWidgets::Spacer(0);
|
||||
}
|
||||
|
||||
window->BeginGroupPanelPublic("Alternate controls", ImGui::GetContentRegionAvail());
|
||||
if (ImGui::BeginTable("tableOcarinaAlternateControls", 2, ImGuiTableFlags_SizingFixedSame)) {
|
||||
ImGui::TableSetupColumn("D-pad", PANEL_TABLE_COLUMN_FLAGS);
|
||||
ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS);
|
||||
TableHelper::InitHeader(false);
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
UIWidgets::EnhancementCheckbox("Play with D-pad", "gDpadOcarina");
|
||||
TableHelper::NextCol();
|
||||
UIWidgets::EnhancementCheckbox("Play with camera stick", "gRStickOcarina");
|
||||
UIWidgets::Spacer(0);
|
||||
ImGui::EndTable();
|
||||
}
|
||||
window->EndGroupPanelPublic(0);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
void DrawCameraControlPanel(GameControlEditorWindow* window) {
|
||||
if (!ImGui::CollapsingHeader("Camera Controls")) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
window->BeginGroupPanelPublic("Aiming/First-Person Camera", ImGui::GetContentRegionAvail());
|
||||
UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming");
|
||||
DrawHelpIcon("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming");
|
||||
if (CVarGetInteger("gRightStickAiming", 0)) {
|
||||
UIWidgets::PaddedEnhancementCheckbox("Allow moving while in first person mode", "gMoveWhileFirstPerson");
|
||||
DrawHelpIcon("Changes the left stick to move the player while in first person mode");
|
||||
}
|
||||
UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", "gInvertAimingXAxis");
|
||||
DrawHelpIcon("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Invert Aiming Y Axis", "gInvertAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
||||
DrawHelpIcon("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming Y Axis", "gInvertShieldAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
||||
DrawHelpIcon("Inverts the Shield Aiming Y Axis");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", "gInvertShieldAimingXAxis");
|
||||
DrawHelpIcon("Inverts the Shield Aiming X Axis");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", "gInvertZAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
||||
DrawHelpIcon("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", "gDisableAutoCenterViewFirstPerson");
|
||||
DrawHelpIcon("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming");
|
||||
if (UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", "gEnableFirstPersonSensitivity", true, false)) {
|
||||
if (!CVarGetInteger("gEnableFirstPersonSensitivity", 0)) {
|
||||
CVarClear("gFirstPersonCameraSensitivityX");
|
||||
CVarClear("gFirstPersonCameraSensitivityY");
|
||||
}
|
||||
}
|
||||
if (CVarGetInteger("gEnableFirstPersonSensitivity", 0)) {
|
||||
UIWidgets::EnhancementSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", "##FirstPersonSensitivity Horizontal",
|
||||
"gFirstPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true);
|
||||
UIWidgets::EnhancementSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", "##FirstPersonSensitivity Vertical",
|
||||
"gFirstPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true);
|
||||
}
|
||||
UIWidgets::Spacer(0);
|
||||
window->EndGroupPanelPublic(0);
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
window->BeginGroupPanelPublic("Third-Person Camera", ImGui::GetContentRegionAvail());
|
||||
|
||||
UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera");
|
||||
DrawHelpIcon("Enables free 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", "gInvertXAxis");
|
||||
DrawHelpIcon("Inverts the Camera X Axis in:\n-Free camera");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
||||
DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free camera");
|
||||
UIWidgets::Spacer(0);
|
||||
UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", "##ThirdPersonSensitivity Horizontal",
|
||||
"gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true);
|
||||
UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", "##ThirdPersonSensitivity Vertical",
|
||||
"gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true);
|
||||
UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist",
|
||||
"gFreeCameraDistMax", 100, 900, "", 185, true, false, true);
|
||||
UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed",
|
||||
"gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true);
|
||||
window->EndGroupPanelPublic(0);
|
||||
}
|
||||
|
||||
void DrawDpadControlPanel(GameControlEditorWindow* window) {
|
||||
if (!ImGui::CollapsingHeader("D-Pad Controls")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImVec2 cursor = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
|
||||
window->BeginGroupPanelPublic("D-Pad Options", ImGui::GetContentRegionAvail());
|
||||
UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause");
|
||||
DrawHelpIcon("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\n"
|
||||
"To make the cursor only move a single space no matter how long a direction is held, manually set gDpadHoldChange to 0");
|
||||
UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", "gDpadText");
|
||||
DrawHelpIcon("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad\n"
|
||||
"To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gDpadHoldChange to 0");
|
||||
UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips");
|
||||
DrawHelpIcon("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate");
|
||||
window->EndGroupPanelPublic(0);
|
||||
}
|
||||
|
||||
void DrawMiscControlPanel(GameControlEditorWindow* window) {
|
||||
if (!ImGui::CollapsingHeader("Miscellaneous Controls")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImVec2 cursor = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
|
||||
window->BeginGroupPanelPublic("Misc Controls", ImGui::GetContentRegionAvail());
|
||||
UIWidgets::PaddedText("Allow the cursor to be on any slot");
|
||||
static const char* cursorOnAnySlot[3] = { "Only in Rando", "Always", "Never" };
|
||||
UIWidgets::EnhancementCombobox("gPauseAnyCursor", cursorOnAnySlot, PAUSE_ANY_CURSOR_RANDO_ONLY);
|
||||
DrawHelpIcon("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select "
|
||||
"certain items.");
|
||||
UIWidgets::Spacer(0);
|
||||
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||
UIWidgets::PaddedEnhancementCheckbox("Enable walk speed modifiers", "gEnableWalkModify", true, false);
|
||||
DrawHelpIcon("Hold the assigned button to change the maximum walking speed\nTo change the assigned button, go into the Ports tabs above");
|
||||
if (CVarGetInteger("gEnableWalkModify", 0)) {
|
||||
UIWidgets::Spacer(5);
|
||||
window->BeginGroupPanelPublic("Walk Modifier", ImGui::GetContentRegionAvail());
|
||||
UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false);
|
||||
UIWidgets::PaddedEnhancementSliderFloat("Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
|
||||
UIWidgets::PaddedEnhancementSliderFloat("Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
|
||||
window->EndGroupPanelPublic(0);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
UIWidgets::Spacer(0);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL");
|
||||
DrawHelpIcon("Speak to Navi with L but enter first-person camera with C-Up");
|
||||
window->EndGroupPanelPublic(0);
|
||||
}
|
||||
|
||||
|
||||
void GameControlEditorWindow::DrawElement() {
|
||||
ImGui::SetNextWindowSize(ImVec2(465, 430), ImGuiCond_FirstUseEver);
|
||||
if (ImGui::Begin("Game Controls Configuration", &mIsVisible)) {
|
||||
DrawOcarinaControlPanel(this);
|
||||
DrawCameraControlPanel(this);
|
||||
DrawDpadControlPanel(this);
|
||||
DrawMiscControlPanel(this);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void GameControlEditorWindow::BeginGroupPanelPublic(const char* name, const ImVec2& size) {
|
||||
BeginGroupPanel(name, size);
|
||||
}
|
||||
|
||||
void GameControlEditorWindow::EndGroupPanelPublic(float minHeight) {
|
||||
EndGroupPanel(minHeight);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
namespace GameControlEditor {
|
||||
class GameControlEditorWindow : public LUS::GuiWindow {
|
||||
public:
|
||||
using LUS::GuiWindow::GuiWindow;
|
||||
|
||||
void BeginGroupPanelPublic(const char* name, const ImVec2& size);
|
||||
void EndGroupPanelPublic(float minHeight);
|
||||
|
||||
void InitElement() override;
|
||||
void DrawElement() override;
|
||||
void UpdateElement() override {};
|
||||
};
|
||||
|
||||
static int CurrentPort = 0;
|
||||
static int BtnReading = -1;
|
||||
|
||||
} // namespace GameControlEditor
|
|
@ -0,0 +1,520 @@
|
|||
#include "InputViewer.h"
|
||||
|
||||
#include "public/bridge/consolevariablebridge.h"
|
||||
#include "libultraship/libultra/controller.h"
|
||||
#include "Context.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#endif
|
||||
#include <ImGui/imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "../../UIWidgets.hpp"
|
||||
|
||||
// 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 const char* buttonOutlineOptions[4] = { "Always Shown", "Shown Only While Not Pressed",
|
||||
"Shown Only While Pressed", "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);
|
||||
}
|
||||
|
||||
InputViewer::~InputViewer() {
|
||||
SPDLOG_TRACE("destruct input viewer");
|
||||
}
|
||||
|
||||
void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTexture, int state, ImVec2 size,
|
||||
int outlineMode) {
|
||||
const ImVec2 pos = ImGui::GetCursorPos();
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
// Render Outline based on settings
|
||||
if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) ||
|
||||
(outlineMode == BUTTON_OUTLINE_PRESSED && state)) {
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size,
|
||||
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
||||
}
|
||||
// Render button if pressed
|
||||
if (state) {
|
||||
ImGui::SetCursorPos(pos);
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size,
|
||||
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
void InputViewer::DrawElement() {
|
||||
if (CVarGetInteger(CVAR_WINDOW("InputViewer"), 0)) {
|
||||
static bool sButtonTexturesLoaded = false;
|
||||
if (!sButtonTexturesLoaded) {
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
|
||||
"Input-Viewer-Background", "textures/buttons/InputViewerBackground.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn",
|
||||
"textures/buttons/StartBtn.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick",
|
||||
"textures/buttons/AnalogStick.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left",
|
||||
"textures/buttons/DPadLeft.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right",
|
||||
"textures/buttons/DPadRight.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down",
|
||||
"textures/buttons/DPadDown.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick",
|
||||
"textures/buttons/RightStick.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline",
|
||||
"textures/buttons/ABtnOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline",
|
||||
"textures/buttons/BBtnOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline",
|
||||
"textures/buttons/LBtnOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline",
|
||||
"textures/buttons/RBtnOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline",
|
||||
"textures/buttons/ZBtnOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline",
|
||||
"textures/buttons/StartBtnOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline",
|
||||
"textures/buttons/CLeftOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline",
|
||||
"textures/buttons/CRightOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline",
|
||||
"textures/buttons/CUpOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline",
|
||||
"textures/buttons/CDownOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline",
|
||||
"textures/buttons/AnalogStickOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline",
|
||||
"textures/buttons/DPadLeftOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline",
|
||||
"textures/buttons/DPadRightOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline",
|
||||
"textures/buttons/DPadUpOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline",
|
||||
"textures/buttons/DPadDownOutline.png");
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline",
|
||||
"textures/buttons/RightStickOutline.png");
|
||||
sButtonTexturesLoaded = true;
|
||||
}
|
||||
|
||||
ImVec2 mainPos = ImGui::GetWindowPos();
|
||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||
|
||||
#ifdef __WIIU__
|
||||
const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f) * 2.0f;
|
||||
#else
|
||||
const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f);
|
||||
#endif
|
||||
const int showAnalogAngles = CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0);
|
||||
const int buttonOutlineMode = CVarGetInteger("gInputViewer.ButtonOutlineMode", BUTTON_OUTLINE_NOT_PRESSED);
|
||||
|
||||
ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background");
|
||||
ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale);
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(
|
||||
scaledBGSize.x + 20,
|
||||
scaledBGSize.y +
|
||||
(showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f) + 20));
|
||||
ImGui::SetNextWindowContentSize(
|
||||
ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale *
|
||||
CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f)));
|
||||
ImGui::SetNextWindowPos(
|
||||
ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30),
|
||||
ImGuiCond_FirstUseEver);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
|
||||
OSContPad* pads = Ship::Context::GetInstance()->GetControlDeck()->GetPads();
|
||||
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar |
|
||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground |
|
||||
ImGuiWindowFlags_NoFocusOnAppearing;
|
||||
|
||||
if (!CVarGetInteger("gInputViewer.EnableDragging", 1)) {
|
||||
windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove;
|
||||
}
|
||||
|
||||
if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) {
|
||||
ImGui::SetCursorPos(ImVec2(10, 10));
|
||||
const ImVec2 aPos = ImGui::GetCursorPos();
|
||||
|
||||
if (CVarGetInteger("gInputViewer.ShowBackground", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
// Background
|
||||
ImGui::Image(
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"),
|
||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
||||
}
|
||||
|
||||
// A/B
|
||||
if (CVarGetInteger("gInputViewer.BBtn", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
if (CVarGetInteger("gInputViewer.ABtn", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
|
||||
// C buttons
|
||||
if (CVarGetInteger("gInputViewer.CUp", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
if (CVarGetInteger("gInputViewer.CLeft", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
if (CVarGetInteger("gInputViewer.CRight", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize,
|
||||
buttonOutlineMode);
|
||||
}
|
||||
if (CVarGetInteger("gInputViewer.CDown", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
|
||||
// L/R/Z
|
||||
if (CVarGetInteger("gInputViewer.LBtn", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
if (CVarGetInteger("gInputViewer.RBtn", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
if (CVarGetInteger("gInputViewer.ZBtn", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, buttonOutlineMode);
|
||||
}
|
||||
|
||||
// Start
|
||||
if (CVarGetInteger("gInputViewer.StartBtn", 1)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize,
|
||||
buttonOutlineMode);
|
||||
}
|
||||
|
||||
// Dpad
|
||||
if (CVarGetInteger("gInputViewer.Dpad", 0)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize,
|
||||
buttonOutlineMode);
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize,
|
||||
buttonOutlineMode);
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, buttonOutlineMode);
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize,
|
||||
buttonOutlineMode);
|
||||
}
|
||||
|
||||
const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y;
|
||||
const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y;
|
||||
|
||||
// Analog Stick
|
||||
const int analogOutlineMode =
|
||||
CVarGetInteger("gInputViewer.AnalogStick.OutlineMode", STICK_MODE_ALWAYS_SHOWN);
|
||||
const float maxStickDistance = CVarGetInteger("gInputViewer.AnalogStick.Movement", 12);
|
||||
if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
|
||||
(analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
ImGui::Image(
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"),
|
||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
||||
}
|
||||
const int analogStickMode =
|
||||
CVarGetInteger("gInputViewer.AnalogStick.VisibilityMode", STICK_MODE_ALWAYS_SHOWN);
|
||||
if (analogStickMode == STICK_MODE_ALWAYS_SHOWN ||
|
||||
(analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(
|
||||
ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale,
|
||||
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"),
|
||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
||||
}
|
||||
|
||||
// Right Stick
|
||||
const float maxRightStickDistance = CVarGetInteger("gInputViewer.RightStick.Movement", 7);
|
||||
const int rightOutlineMode =
|
||||
CVarGetInteger("gInputViewer.RightStick.OutlineMode", STICK_MODE_ALWAYS_HIDDEN);
|
||||
if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
|
||||
(rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(aPos);
|
||||
ImGui::Image(
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"),
|
||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
||||
}
|
||||
const int rightStickMode =
|
||||
CVarGetInteger("gInputViewer.RightStick.VisibilityMode", STICK_MODE_ALWAYS_HIDDEN);
|
||||
if (rightStickMode == STICK_MODE_ALWAYS_SHOWN ||
|
||||
(rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) {
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
ImGui::SetCursorPos(
|
||||
ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale,
|
||||
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"),
|
||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
||||
}
|
||||
|
||||
// Analog stick angle text
|
||||
if (showAnalogAngles) {
|
||||
ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger("gInputViewer.AnalogAngles.Offset", 0) * scale,
|
||||
scaledBGSize.y + aPos.y + 10));
|
||||
// Scale font with input viewer scale
|
||||
float oldFontScale = ImGui::GetFont()->Scale;
|
||||
ImGui::GetFont()->Scale *= scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f);
|
||||
ImGui::PushFont(ImGui::GetFont());
|
||||
|
||||
// Calculate polar R coordinate from X and Y angles, squared to avoid sqrt
|
||||
const float rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y;
|
||||
|
||||
// ESS range
|
||||
const int range1Min = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Min", 8);
|
||||
const int range1Max = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Max", 27);
|
||||
// Walking speed range
|
||||
const int range2Min = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Min", 27);
|
||||
const int range2Max = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Max", 62);
|
||||
|
||||
// Push color based on angle ranges
|
||||
if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0) &&
|
||||
(rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) {
|
||||
ImGui::PushStyleColor(
|
||||
ImGuiCol_Text,
|
||||
color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color))));
|
||||
} else if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0) &&
|
||||
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
|
||||
ImGui::PushStyleColor(
|
||||
ImGuiCol_Text,
|
||||
color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color))));
|
||||
} else {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color2Vec(CVarGetColor("gInputViewer.AnalogAngles.TextColor",
|
||||
vec2Color(textColor))));
|
||||
}
|
||||
|
||||
// Render text
|
||||
ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y);
|
||||
// Restore original color
|
||||
ImGui::PopStyleColor();
|
||||
// Restore original font scale
|
||||
ImGui::GetFont()->Scale = oldFontScale;
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
InputViewerSettingsWindow::~InputViewerSettingsWindow() {
|
||||
SPDLOG_TRACE("destruct input viewer settings window");
|
||||
}
|
||||
|
||||
void InputViewerSettingsWindow::DrawElement() {
|
||||
ImGui::SetNextWindowSize(ImVec2(450, 525), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (ImGui::Begin("Input Viewer Settings", &mIsVisible)) {
|
||||
|
||||
// gInputViewer.Scale
|
||||
UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", "gInputViewer.Scale", 0.1f, 5.0f, "",
|
||||
1.0f, false, true);
|
||||
UIWidgets::Tooltip("Sets the on screen size of the input viewer");
|
||||
|
||||
// gInputViewer.EnableDragging
|
||||
UIWidgets::EnhancementCheckbox("Enable Dragging", "gInputViewer.EnableDragging", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
|
||||
UIWidgets::PaddedSeparator(true, true);
|
||||
|
||||
// gInputViewer.ShowBackground
|
||||
UIWidgets::EnhancementCheckbox("Show Background Layer", "gInputViewer.ShowBackground", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
|
||||
UIWidgets::PaddedSeparator(true, true);
|
||||
|
||||
if (ImGui::CollapsingHeader("Buttons")) {
|
||||
// gInputViewer.ABtn
|
||||
UIWidgets::EnhancementCheckbox("Show A-Button Layers", "gInputViewer.ABtn", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.BBtn
|
||||
UIWidgets::EnhancementCheckbox("Show B-Button Layers", "gInputViewer.BBtn", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.CUp
|
||||
UIWidgets::EnhancementCheckbox("Show C-Up Layers", "gInputViewer.CUp", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.CRight
|
||||
UIWidgets::EnhancementCheckbox("Show C-Right Layers", "gInputViewer.CRight", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.CDown
|
||||
UIWidgets::EnhancementCheckbox("Show C-Down Layers", "gInputViewer.CDown", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.CLeft
|
||||
UIWidgets::EnhancementCheckbox("Show C-Left Layers", "gInputViewer.CLeft", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.LBtn
|
||||
UIWidgets::EnhancementCheckbox("Show L-Button Layers", "gInputViewer.LBtn", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.RBtn
|
||||
UIWidgets::EnhancementCheckbox("Show R-Button Layers", "gInputViewer.RBtn", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.ZBtn
|
||||
UIWidgets::EnhancementCheckbox("Show Z-Button Layers", "gInputViewer.ZBtn", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.StartBtn
|
||||
UIWidgets::EnhancementCheckbox("Show Start Button Layers", "gInputViewer.StartBtn", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, true);
|
||||
// gInputViewer.Dpad
|
||||
UIWidgets::EnhancementCheckbox("Show D-Pad Layers", "gInputViewer.Dpad", false, "",
|
||||
UIWidgets::CheckboxGraphics::Checkmark, false);
|
||||
|
||||
// gInputViewer.ButtonOutlineMode
|
||||
UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false);
|
||||
UIWidgets::EnhancementCombobox("gInputViewer.ButtonOutlineMode", buttonOutlineOptions,
|
||||
BUTTON_OUTLINE_NOT_PRESSED);
|
||||
UIWidgets::Tooltip(
|
||||
"Sets the desired visibility behavior for the button outline/background layers. Useful for "
|
||||
"custom input viewers.");
|
||||
|
||||
UIWidgets::PaddedSeparator(true, true);
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Analog Stick")) {
|
||||
// gInputViewer.AnalogStick.VisibilityMode
|
||||
UIWidgets::PaddedText("Analog Stick Visibility", true, false);
|
||||
UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.VisibilityMode", stickModeOptions,
|
||||
STICK_MODE_ALWAYS_SHOWN);
|
||||
UIWidgets::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("gInputViewer.AnalogStick.OutlineMode", stickModeOptions,
|
||||
STICK_MODE_ALWAYS_SHOWN);
|
||||
UIWidgets::Tooltip(
|
||||
"Determines the conditions under which the analog stick outline/background texture is visible.");
|
||||
|
||||
// gInputViewer.AnalogStick.Movement
|
||||
UIWidgets::EnhancementSliderInt("Analog Stick Movement: %dpx", "##AnalogMovement",
|
||||
"gInputViewer.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.");
|
||||
UIWidgets::PaddedSeparator(true, true);
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
|
||||
// gInputViewer.RightStick.VisibilityMode
|
||||
UIWidgets::PaddedText("Right Stick Visibility", true, false);
|
||||
UIWidgets::EnhancementCombobox("gInputViewer.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.");
|
||||
|
||||
// gInputViewer.RightStick.OutlineMode
|
||||
UIWidgets::PaddedText("Right Stick Outline/Background Visibility", true, false);
|
||||
UIWidgets::EnhancementCombobox("gInputViewer.RightStick.OutlineMode", stickModeOptions,
|
||||
STICK_MODE_HIDDEN_IN_DEADZONE);
|
||||
UIWidgets::Tooltip(
|
||||
"Determines the conditions under which the right stick outline/background texture is visible.");
|
||||
|
||||
// gInputViewer.RightStick.Movement
|
||||
UIWidgets::EnhancementSliderInt("Right Stick Movement: %dpx", "##RightMovement",
|
||||
"gInputViewer.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.");
|
||||
UIWidgets::PaddedSeparator(true, true);
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Analog Angle Values")) {
|
||||
// gAnalogAngles
|
||||
UIWidgets::EnhancementCheckbox("Show Analog Stick Angle Values", "gInputViewer.AnalogAngles.Enabled");
|
||||
UIWidgets::Tooltip("Displays analog stick angle values in the input viewer");
|
||||
if (CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0)) {
|
||||
// gInputViewer.AnalogAngles.TextColor
|
||||
if (ImGui::ColorEdit4("Text Color", (float*)&textColor)) {
|
||||
CVarSetColor("gInputViewer.AnalogAngles.TextColor", vec2Color(textColor));
|
||||
}
|
||||
// gAnalogAngleScale
|
||||
UIWidgets::EnhancementSliderFloat("Angle Text Scale: %.2f%%", "##AnalogAngleScale",
|
||||
"gInputViewer.AnalogAngles.Scale", 0.1f, 5.0f, "", 1.0f, true, true);
|
||||
// gInputViewer.AnalogAngles.Offset
|
||||
UIWidgets::EnhancementSliderInt("Angle Text Offset: %dpx", "##AnalogAngleOffset",
|
||||
"gInputViewer.AnalogAngles.Offset", 0, 400, "", 0, true);
|
||||
UIWidgets::PaddedSeparator(true, true);
|
||||
// gInputViewer.AnalogAngles.Range1.Enabled
|
||||
UIWidgets::EnhancementCheckbox("Highlight ESS Position", "gInputViewer.AnalogAngles.Range1.Enabled");
|
||||
UIWidgets::Tooltip(
|
||||
"Highlights the angle value text when the analog stick is in ESS position (on flat ground)");
|
||||
if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0)) {
|
||||
// gInputViewer.AnalogAngles.Range1.Color
|
||||
if (ImGui::ColorEdit4("ESS Color", (float*)&range1Color)) {
|
||||
CVarSetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color));
|
||||
}
|
||||
}
|
||||
|
||||
UIWidgets::PaddedSeparator(true, true);
|
||||
// gInputViewer.AnalogAngles.Range2.Enabled
|
||||
UIWidgets::EnhancementCheckbox("Highlight Walking Speed Angles",
|
||||
"gInputViewer.AnalogAngles.Range2.Enabled");
|
||||
UIWidgets::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");
|
||||
if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0)) {
|
||||
// gInputViewer.AnalogAngles.Range2.Color
|
||||
if (ImGui::ColorEdit4("Walking Speed Color", (float*)&range2Color)) {
|
||||
CVarSetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
typedef enum {
|
||||
BUTTON_OUTLINE_ALWAYS_SHOWN,
|
||||
BUTTON_OUTLINE_NOT_PRESSED,
|
||||
BUTTON_OUTLINE_PRESSED,
|
||||
BUTTON_OUTLINE_ALWAYS_HIDDEN
|
||||
} ButtonOutlineMode;
|
||||
|
||||
typedef enum {
|
||||
STICK_MODE_ALWAYS_SHOWN,
|
||||
STICK_MODE_HIDDEN_IN_DEADZONE,
|
||||
STICK_MODE_ALWAYS_HIDDEN,
|
||||
} StickMode;
|
||||
|
||||
class InputViewer : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
void InitElement() override {};
|
||||
void DrawElement() override;
|
||||
void UpdateElement() override {};
|
||||
|
||||
InputViewer();
|
||||
~InputViewer();
|
||||
|
||||
void Draw();
|
||||
|
||||
private:
|
||||
void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode);
|
||||
};
|
||||
|
||||
class InputViewerSettingsWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
void InitElement() override {};
|
||||
void DrawElement() override;
|
||||
void UpdateElement() override {};
|
||||
|
||||
InputViewerSettingsWindow();
|
||||
~InputViewerSettingsWindow();
|
||||
|
||||
void Draw();
|
||||
};
|
|
@ -10,8 +10,17 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
class SohInputEditorWindow : public LUS::GuiWindow {
|
||||
typedef uint32_t N64ButtonMask;
|
||||
|
||||
typedef struct {
|
||||
const char* label;
|
||||
const char* cVarName;
|
||||
N64ButtonMask defaultBtn;
|
||||
} CustomButtonMap;
|
||||
|
||||
class SohInputEditorWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
~SohInputEditorWindow();
|
||||
|
@ -29,14 +38,14 @@ class SohInputEditorWindow : public LUS::GuiWindow {
|
|||
void UpdateElement() override;
|
||||
|
||||
private:
|
||||
void DrawStickDirectionLine(const char* axisDirectionName, uint8_t port, uint8_t stick, LUS::Direction direction,
|
||||
void DrawStickDirectionLine(const char* axisDirectionName, uint8_t port, uint8_t stick, Ship::Direction direction,
|
||||
ImVec4 color);
|
||||
void DrawButtonLine(const char* buttonName, uint8_t port, uint16_t bitmask, ImVec4 color);
|
||||
void DrawButtonLineEditMappingButton(uint8_t port, uint16_t bitmask, std::string id);
|
||||
void DrawButtonLineAddMappingButton(uint8_t port, uint16_t bitmask);
|
||||
|
||||
void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, LUS::Direction direction, std::string id);
|
||||
void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, LUS::Direction direction);
|
||||
void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction, std::string id);
|
||||
void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction);
|
||||
void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color);
|
||||
|
||||
void DrawRumbleSection(uint8_t port);
|
||||
|
@ -51,23 +60,34 @@ class SohInputEditorWindow : public LUS::GuiWindow {
|
|||
void DrawRemoveGyroMappingButton(uint8_t port, std::string id);
|
||||
void DrawAddGyroMappingButton(uint8_t port);
|
||||
|
||||
// Used together for an incomplete linked hash map implementation in order to
|
||||
// map button masks to their names and original mapping on N64
|
||||
std::list<std::pair<N64ButtonMask, const char*>> buttons;
|
||||
std::unordered_map<N64ButtonMask, decltype(buttons)::iterator> buttonNames;
|
||||
void addButtonName(N64ButtonMask mask, const char* name);
|
||||
void DrawMapping(CustomButtonMap& mapping, float labelWidth, N64ButtonMask excludedButtons);
|
||||
void DrawOcarinaControlPanel();
|
||||
void DrawCameraControlPanel();
|
||||
void DrawDpadControlPanel();
|
||||
void DrawMiscControlPanel();
|
||||
|
||||
int32_t mGameInputBlockTimer;
|
||||
int32_t mMappingInputBlockTimer;
|
||||
int32_t mRumbleTimer;
|
||||
std::shared_ptr<LUS::ControllerRumbleMapping> mRumbleMappingToTest;
|
||||
std::shared_ptr<Ship::ControllerRumbleMapping> mRumbleMappingToTest;
|
||||
|
||||
// mBitmaskToMappingIds[port][bitmask] = { id0, id1, ... }
|
||||
std::unordered_map<uint8_t, std::unordered_map<uint16_t, std::vector<std::string>>> mBitmaskToMappingIds;
|
||||
|
||||
// mStickDirectionToMappingIds[port][stick][direction] = { id0, id1, ... }
|
||||
std::unordered_map<uint8_t,
|
||||
std::unordered_map<uint8_t, std::unordered_map<LUS::Direction, std::vector<std::string>>>>
|
||||
std::unordered_map<uint8_t, std::unordered_map<Ship::Direction, std::vector<std::string>>>>
|
||||
mStickDirectionToMappingIds;
|
||||
|
||||
void UpdateBitmaskToMappingIds(uint8_t port);
|
||||
void UpdateStickDirectionToMappingIds(uint8_t port);
|
||||
|
||||
void GetButtonColorsForLUSDeviceIndex(LUS::LUSDeviceIndex lusIndex, ImVec4& buttonColor,
|
||||
void GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex lusIndex, ImVec4& buttonColor,
|
||||
ImVec4& buttonHoveredColor);
|
||||
void DrawLinkTab();
|
||||
void DrawIvanTab();
|
||||
|
@ -77,13 +97,11 @@ class SohInputEditorWindow : public LUS::GuiWindow {
|
|||
std::set<uint16_t> mDpadBitmasks;
|
||||
std::set<uint16_t> mModifierButtonsBitmasks;
|
||||
void DrawButtonDeviceIcons(uint8_t portIndex, std::set<uint16_t> bitmasks);
|
||||
void DrawAnalogStickDeviceIcons(uint8_t portIndex, LUS::Stick stick);
|
||||
void DrawAnalogStickDeviceIcons(uint8_t portIndex, Ship::Stick stick);
|
||||
void DrawRumbleDeviceIcons(uint8_t portIndex);
|
||||
void DrawGyroDeviceIcons(uint8_t portIndex);
|
||||
void DrawLEDDeviceIcons(uint8_t portIndex);
|
||||
bool mInputEditorPopupOpen;
|
||||
void DrawSetDefaultsButton(uint8_t portIndex);
|
||||
void DrawClearAllButton(uint8_t portIndex);
|
||||
|
||||
void DrawHelpIcon(const std::string& helptext);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,29 @@
|
|||
ResourceMgr_UnpatchGfxByName(path, name); \
|
||||
}
|
||||
|
||||
// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize
|
||||
// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor`
|
||||
typedef enum {
|
||||
COSMETICS_GROUP_LINK,
|
||||
COSMETICS_GROUP_MIRRORSHIELD,
|
||||
COSMETICS_GROUP_SWORDS,
|
||||
COSMETICS_GROUP_GLOVES,
|
||||
COSMETICS_GROUP_EQUIPMENT,
|
||||
COSMETICS_GROUP_CONSUMABLE,
|
||||
COSMETICS_GROUP_HUD,
|
||||
COSMETICS_GROUP_KALEIDO,
|
||||
COSMETICS_GROUP_TITLE,
|
||||
COSMETICS_GROUP_NPC,
|
||||
COSMETICS_GROUP_WORLD,
|
||||
COSMETICS_GROUP_MAGIC,
|
||||
COSMETICS_GROUP_ARROWS,
|
||||
COSMETICS_GROUP_SPIN_ATTACK,
|
||||
COSMETICS_GROUP_TRAILS,
|
||||
COSMETICS_GROUP_NAVI,
|
||||
COSMETICS_GROUP_IVAN,
|
||||
COSMETICS_GROUP_MAX
|
||||
} CosmeticGroup;
|
||||
|
||||
typedef struct {
|
||||
const std::string Name;
|
||||
const std::string ToolTip;
|
||||
|
@ -26,10 +49,12 @@ static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | Im
|
|||
void InitCosmeticsEditor();//Init the menu itself
|
||||
ImVec4 GetRandomValue(int MaximumPossible);
|
||||
void CosmeticsEditor_RandomizeAll();
|
||||
void CosmeticsEditor_RandomizeGroup(CosmeticGroup group);
|
||||
void CosmeticsEditor_ResetAll();
|
||||
void CosmeticsEditor_ResetGroup(CosmeticGroup group);
|
||||
void ApplyOrResetCustomGfxPatches(bool manualChange = true);
|
||||
|
||||
class CosmeticsEditorWindow : public LUS::GuiWindow {
|
||||
class CosmeticsEditorWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <libultraship/bridge.h>
|
||||
#include <string>
|
||||
#include "soh/OTRGlobals.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libultraship/libultra.h>
|
||||
|
@ -8,6 +9,7 @@ extern "C" {
|
|||
#include "objects/object_gi_soldout/object_gi_soldout.h"
|
||||
#include "objects/object_ik/object_ik.h"
|
||||
#include "objects/object_link_child/object_link_child.h"
|
||||
#include "objects/object_ru2/object_ru2.h"
|
||||
|
||||
uint32_t ResourceMgr_GameHasMasterQuest();
|
||||
uint32_t ResourceMgr_GameHasOriginal();
|
||||
|
@ -80,7 +82,7 @@ void PatchDekuStickTextureOverflow() {
|
|||
const char* dlist = gLinkChildLinkDekuStickDL;
|
||||
int start = 5;
|
||||
|
||||
if (!CVarGetInteger("gFixTexturesOOB", 0)) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) {
|
||||
// Unpatch the other texture fix
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
int instruction = start + (i == 0 ? 0 : i + 1);
|
||||
|
@ -120,7 +122,7 @@ void PatchFreezardTextureOverflow() {
|
|||
char patchNameBuf[24];
|
||||
|
||||
// Patch using custom overflowed texture
|
||||
if (!CVarGetInteger("gFixTexturesOOB", 0)) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) {
|
||||
// Unpatch the other texture fix
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
int instruction = start + (i == 0 ? 0 : i + 1);
|
||||
|
@ -162,7 +164,7 @@ void PatchIronKnuckleTextureOverflow() {
|
|||
// Until this is solved, Iron Knuckle will be hardcoded to always display with the "authentic" texture fix
|
||||
|
||||
// Patch using custom overflowed texture
|
||||
// if (!CVarGetInteger("gFixTexturesOOB", 0)) {
|
||||
// if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) {
|
||||
// Unpatch the other texture fix
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
int instruction = start + (i == 0 ? 0 : i + 1);
|
||||
|
@ -187,10 +189,25 @@ void PatchIronKnuckleTextureOverflow() {
|
|||
}
|
||||
}
|
||||
|
||||
void PatchPrincessRutoEaring() {
|
||||
// FAST3D: This is a hack for the issue of both TEXEL0 and TEXEL1 using the same texture with different settings.
|
||||
// Ruto's earring uses both TEXEL0 and TEXEL1 to render. The issue is that it never loads anything into TEXEL1, so
|
||||
// it reuses whatever happens to be there, which is the water temple brick texture. It just so happens that the
|
||||
// earring texture loads into the same place in TMEM as the brick texture, so when it comes to rendering, TEXEL1
|
||||
// uses the earring texture with different clamp settings, and it displays without noticeable error. However, both
|
||||
// texel samplers are not intended to be used for the same texture with different settings, so this misuse confuses
|
||||
// our texture cache, and we load the wrong settings for the earrings texture. This patch is a hack that replaces
|
||||
// TEXEL1 with TEXEL0, which is most likely the original intention, and all is well.
|
||||
ResourceMgr_PatchGfxByName(gAdultRutoHeadDL, "RutoEaringTileFix", 162,
|
||||
gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, COMBINED,
|
||||
TEXEL0, 0, PRIM_LOD_FRAC, COMBINED));
|
||||
}
|
||||
|
||||
void ApplyAuthenticGfxPatches() {
|
||||
PatchDekuStickTextureOverflow();
|
||||
PatchFreezardTextureOverflow();
|
||||
PatchIronKnuckleTextureOverflow();
|
||||
PatchPrincessRutoEaring();
|
||||
}
|
||||
|
||||
// Patches the Sold Out GI DL to render the texture in the mirror boundary
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef enum {
|
|||
TEXT_CARPET_SALESMAN_1 = 0x6077,
|
||||
TEXT_CARPET_SALESMAN_2 = 0x6078,
|
||||
TEXT_MARKET_GUARD_NIGHT = 0x7003,
|
||||
TEXT_FISHERMAN_LEAVE = 0x409E,
|
||||
TEXT_SHEIK_NEED_HOOK = 0x700F,
|
||||
TEXT_SHEIK_HAVE_HOOK = 0x7010,
|
||||
TEXT_SCRUB_RANDOM = 0x9000,
|
||||
|
@ -54,6 +55,22 @@ typedef enum {
|
|||
TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW = 0x9210,
|
||||
TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x346, // 0x3yy for cuttable sign range
|
||||
TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x1B3, // 0x1yy for Navi msg range
|
||||
TEXT_SARIAS_SONG_CHANNELING_POWER = 0x016D,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_10 = 0x405E,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_20 = 0x405F,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_30 = 0x4060,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_40 = 0x4061,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_50 = 0x4062,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_60 = 0x4063,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_70 = 0x4064,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_80 = 0x4065,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_90 = 0x4066,
|
||||
TEXT_BEAN_SALESMAN_BUY_FOR_100 = 0x4067,
|
||||
TEXT_BEAN_SALESMAN_OH_WELL = 0x4068,
|
||||
TEXT_BEAN_SALESMAN_NOT_ENOUGH_MONEY = 0x4069,
|
||||
TEXT_BEAN_SALESMAN_SET_A_BEAN_TO_C = 0x406A,
|
||||
TEXT_BEAN_SALESMAN_SOLD_OUT = 0x406B,
|
||||
TEXT_BEAN_SALESMAN_WANT_TO_PLANT = 0x406C,
|
||||
} TextIDs;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -36,12 +36,12 @@ extern PlayState* gPlayState;
|
|||
#include <libultraship/bridge.h>
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
#define CMD_REGISTER LUS::Context::GetInstance()->GetConsole()->AddCommand
|
||||
#define CMD_REGISTER Ship::Context::GetInstance()->GetConsole()->AddCommand
|
||||
// TODO: Commands should be using the output passed in.
|
||||
#define ERROR_MESSAGE std::reinterpret_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendErrorMessage
|
||||
#define INFO_MESSAGE std::reinterpret_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendInfoMessage
|
||||
#define ERROR_MESSAGE std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendErrorMessage
|
||||
#define INFO_MESSAGE std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendInfoMessage
|
||||
|
||||
static bool ActorSpawnHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) {
|
||||
ERROR_MESSAGE("Not enough arguments passed to actorspawn");
|
||||
return 1;
|
||||
|
@ -101,7 +101,7 @@ static bool ActorSpawnHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool KillPlayerHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>&, std::string* output) {
|
||||
static bool KillPlayerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&, std::string* output) {
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::SetPlayerHealth();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = 0;
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
@ -114,7 +114,7 @@ static bool KillPlayerHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
}
|
||||
}
|
||||
|
||||
static bool SetPlayerHealthHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -145,7 +145,7 @@ static bool SetPlayerHealthHandler(std::shared_ptr<LUS::Console> Console, const
|
|||
}
|
||||
}
|
||||
|
||||
static bool LoadSceneHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>&, std::string* output) {
|
||||
static bool LoadSceneHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&, std::string* output) {
|
||||
gSaveContext.respawnFlag = 0;
|
||||
gSaveContext.seqId = 0xFF;
|
||||
gSaveContext.gameMode = 0;
|
||||
|
@ -153,7 +153,7 @@ static bool LoadSceneHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool RupeeHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool RupeeHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ static bool RupeeHandler(std::shared_ptr<LUS::Console> Console, const std::vecto
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool SetPosHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string> args, std::string* output) {
|
||||
static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args, std::string* output) {
|
||||
if (gPlayState == nullptr) {
|
||||
ERROR_MESSAGE("PlayState == nullptr");
|
||||
return 1;
|
||||
|
@ -205,7 +205,7 @@ static bool SetPosHandler(std::shared_ptr<LUS::Console> Console, const std::vect
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool ResetHandler(std::shared_ptr<LUS::Console> Console, std::vector<std::string> args, std::string* output) {
|
||||
static bool ResetHandler(std::shared_ptr<Ship::Console> Console, std::vector<std::string> args, std::string* output) {
|
||||
if (gPlayState == nullptr) {
|
||||
ERROR_MESSAGE("PlayState == nullptr");
|
||||
return 1;
|
||||
|
@ -225,7 +225,7 @@ const static std::map<std::string, uint16_t> ammoItems{
|
|||
{ "beans", ITEM_BEAN }
|
||||
};
|
||||
|
||||
static bool AddAmmoHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool AddAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 3) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -264,7 +264,7 @@ static bool AddAmmoHandler(std::shared_ptr<LUS::Console> Console, const std::vec
|
|||
}
|
||||
}
|
||||
|
||||
static bool TakeAmmoHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool TakeAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 3) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -311,7 +311,7 @@ const static std::map<std::string, uint16_t> bottleItems{
|
|||
{ "big_poe", ITEM_BIG_POE }, { "blue_fire", ITEM_BLUE_FIRE }, { "rutos_letter", ITEM_LETTER_RUTO },
|
||||
};
|
||||
|
||||
static bool BottleHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 3) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -343,7 +343,7 @@ static bool BottleHandler(std::shared_ptr<LUS::Console> Console, const std::vect
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool BHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool BHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -353,7 +353,7 @@ static bool BHandler(std::shared_ptr<LUS::Console> Console, const std::vector<st
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool ItemHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool ItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 3) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -364,7 +364,7 @@ static bool ItemHandler(std::shared_ptr<LUS::Console> Console, const std::vector
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool GiveItemHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string> args, std::string* output) {
|
||||
static bool GiveItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args, std::string* output) {
|
||||
if (args.size() < 3) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -385,7 +385,7 @@ static bool GiveItemHandler(std::shared_ptr<LUS::Console> Console, const std::ve
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool EntranceHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -406,7 +406,7 @@ static bool EntranceHandler(std::shared_ptr<LUS::Console> Console, const std::ve
|
|||
gSaveContext.nextTransitionType = TRANS_TYPE_INSTANT;
|
||||
}
|
||||
|
||||
static bool VoidHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (gPlayState != nullptr) {
|
||||
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwchFlags = gPlayState->actorCtx.flags.tempSwch;
|
||||
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags = gPlayState->actorCtx.flags.tempCollect;
|
||||
|
@ -422,7 +422,7 @@ static bool VoidHandler(std::shared_ptr<LUS::Console> Console, const std::vector
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool ReloadHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool ReloadHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (gPlayState != nullptr) {
|
||||
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
|
||||
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||
|
@ -439,7 +439,7 @@ const static std::map<std::string, uint16_t> fw_options {
|
|||
{ "clear", 0}, {"warp", 1}, {"backup", 2}
|
||||
};
|
||||
|
||||
static bool FWHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool FWHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -471,7 +471,7 @@ static bool FWHandler(std::shared_ptr<LUS::Console> Console, const std::vector<s
|
|||
return 0;
|
||||
break;
|
||||
case 2: //backup
|
||||
if (CVarGetInteger("gBetterFW", 0)) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("BetterFarore"), 0)) {
|
||||
gSaveContext.fw = gSaveContext.backupFW;
|
||||
gSaveContext.fw.set = 1;
|
||||
INFO_MESSAGE("[SOH] Backup FW data copied! Reload scene to take effect.");
|
||||
|
@ -491,7 +491,7 @@ static bool FWHandler(std::shared_ptr<LUS::Console> Console, const std::vector<s
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool FileSelectHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool FileSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (gPlayState != nullptr) {
|
||||
SET_NEXT_GAMESTATE(&gPlayState->state, FileChoose_Init, FileChooseContext);
|
||||
gPlayState->state.running = 0;
|
||||
|
@ -502,12 +502,12 @@ static bool FileSelectHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool QuitHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
LUS::Context::GetInstance()->GetWindow()->Close();
|
||||
static bool QuitHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
Ship::Context::GetInstance()->GetWindow()->Close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool SaveStateHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool SaveStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
|
||||
const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE });
|
||||
|
||||
|
@ -521,7 +521,7 @@ static bool SaveStateHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
static bool LoadStateHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool LoadStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
|
||||
const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD });
|
||||
|
||||
|
@ -542,7 +542,7 @@ static bool LoadStateHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
|
||||
}
|
||||
|
||||
static bool StateSlotSelectHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -567,7 +567,7 @@ static bool StateSlotSelectHandler(std::shared_ptr<LUS::Console> Console, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool InvisibleHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool InvisibleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -594,7 +594,7 @@ static bool InvisibleHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
static bool GiantLinkHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool GiantLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -622,7 +622,7 @@ static bool GiantLinkHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
static bool MinishLinkHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool MinishLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -650,7 +650,7 @@ static bool MinishLinkHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
}
|
||||
}
|
||||
|
||||
static bool AddHeartContainerHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool AddHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -681,7 +681,7 @@ static bool AddHeartContainerHandler(std::shared_ptr<LUS::Console> Console, cons
|
|||
}
|
||||
}
|
||||
|
||||
static bool RemoveHeartContainerHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool RemoveHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -712,7 +712,7 @@ static bool RemoveHeartContainerHandler(std::shared_ptr<LUS::Console> Console, c
|
|||
}
|
||||
}
|
||||
|
||||
static bool GravityHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool GravityHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -721,7 +721,7 @@ static bool GravityHandler(std::shared_ptr<LUS::Console> Console, const std::vec
|
|||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyGravity();
|
||||
|
||||
try {
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = LUS::Math::clamp(std::stoi(args[1], nullptr, 10), GI_GRAVITY_LEVEL_LIGHT, GI_GRAVITY_LEVEL_HEAVY);
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = Ship::Math::clamp(std::stoi(args[1], nullptr, 10), GI_GRAVITY_LEVEL_LIGHT, GI_GRAVITY_LEVEL_HEAVY);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
ERROR_MESSAGE("[SOH] Gravity value must be a number.");
|
||||
return 1;
|
||||
|
@ -737,7 +737,7 @@ static bool GravityHandler(std::shared_ptr<LUS::Console> Console, const std::vec
|
|||
}
|
||||
}
|
||||
|
||||
static bool NoUIHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool NoUIHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -765,7 +765,7 @@ static bool NoUIHandler(std::shared_ptr<LUS::Console> Console, const std::vector
|
|||
}
|
||||
}
|
||||
|
||||
static bool FreezeHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool FreezeHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::FreezePlayer();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
|
@ -778,7 +778,7 @@ static bool FreezeHandler(std::shared_ptr<LUS::Console> Console, const std::vect
|
|||
}
|
||||
}
|
||||
|
||||
static bool DefenseModifierHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool DefenseModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -802,7 +802,7 @@ static bool DefenseModifierHandler(std::shared_ptr<LUS::Console> Console, const
|
|||
}
|
||||
}
|
||||
|
||||
static bool DamageHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool DamageHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -832,7 +832,7 @@ static bool DamageHandler(std::shared_ptr<LUS::Console> Console, const std::vect
|
|||
}
|
||||
}
|
||||
|
||||
static bool HealHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool HealHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -862,7 +862,7 @@ static bool HealHandler(std::shared_ptr<LUS::Console> Console, const std::vector
|
|||
}
|
||||
}
|
||||
|
||||
static bool FillMagicHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool FillMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::FillMagic();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
|
@ -875,7 +875,7 @@ static bool FillMagicHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
static bool EmptyMagicHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool EmptyMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::EmptyMagic();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
|
@ -888,7 +888,7 @@ static bool EmptyMagicHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
}
|
||||
}
|
||||
|
||||
static bool NoZHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool NoZHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -916,7 +916,7 @@ static bool NoZHandler(std::shared_ptr<LUS::Console> Console, const std::vector<
|
|||
}
|
||||
}
|
||||
|
||||
static bool OneHitKOHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool OneHitKOHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -944,7 +944,7 @@ static bool OneHitKOHandler(std::shared_ptr<LUS::Console> Console, const std::ve
|
|||
}
|
||||
}
|
||||
|
||||
static bool PacifistHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool PacifistHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -972,7 +972,7 @@ static bool PacifistHandler(std::shared_ptr<LUS::Console> Console, const std::ve
|
|||
}
|
||||
}
|
||||
|
||||
static bool PaperLinkHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool PaperLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1001,7 +1001,7 @@ static bool PaperLinkHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
static bool RainstormHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool RainstormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1029,7 +1029,7 @@ static bool RainstormHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
static bool ReverseControlsHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool ReverseControlsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1058,7 +1058,7 @@ static bool ReverseControlsHandler(std::shared_ptr<LUS::Console> Console, const
|
|||
}
|
||||
}
|
||||
|
||||
static bool UpdateRupeesHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool UpdateRupeesHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1082,7 +1082,7 @@ static bool UpdateRupeesHandler(std::shared_ptr<LUS::Console> Console, const std
|
|||
}
|
||||
}
|
||||
|
||||
static bool SpeedModifierHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool SpeedModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1112,7 +1112,7 @@ const static std::map<std::string, uint16_t> boots {
|
|||
{ "hover", EQUIP_VALUE_BOOTS_HOVER },
|
||||
};
|
||||
|
||||
static bool BootsHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool BootsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1143,7 +1143,7 @@ const static std::map<std::string, uint16_t> shields {
|
|||
{ "mirror", ITEM_SHIELD_MIRROR },
|
||||
};
|
||||
|
||||
static bool GiveShieldHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool GiveShieldHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1168,7 +1168,7 @@ static bool GiveShieldHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
}
|
||||
}
|
||||
|
||||
static bool TakeShieldHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool TakeShieldHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1193,7 +1193,7 @@ static bool TakeShieldHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
}
|
||||
}
|
||||
|
||||
static bool KnockbackHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool KnockbackHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
|
@ -1223,7 +1223,7 @@ static bool KnockbackHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
static bool ElectrocuteHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool ElectrocuteHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ElectrocutePlayer();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
|
@ -1236,7 +1236,7 @@ static bool ElectrocuteHandler(std::shared_ptr<LUS::Console> Console, const std:
|
|||
}
|
||||
}
|
||||
|
||||
static bool BurnHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool BurnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::BurnPlayer();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
|
@ -1249,7 +1249,7 @@ static bool BurnHandler(std::shared_ptr<LUS::Console> Console, const std::vector
|
|||
}
|
||||
}
|
||||
|
||||
static bool CuccoStormHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
GameInteractionEffectQueryResult result = GameInteractor::RawAction::SpawnActor(ACTOR_EN_NIW, 0);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
|
@ -1261,7 +1261,7 @@ static bool CuccoStormHandler(std::shared_ptr<LUS::Console> Console, const std::
|
|||
}
|
||||
}
|
||||
|
||||
static bool GenerateRandoHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static bool GenerateRandoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() == 1) {
|
||||
if (GenerateRandomizer()) {
|
||||
return 0;
|
||||
|
@ -1289,16 +1289,58 @@ static bool GenerateRandoHandler(std::shared_ptr<LUS::Console> Console, const st
|
|||
return 1;
|
||||
}
|
||||
|
||||
static bool CosmeticsHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static constexpr std::array<std::pair<const char*, CosmeticGroup>, COSMETICS_GROUP_MAX> cosmetic_groups = {{
|
||||
{"link", COSMETICS_GROUP_LINK},
|
||||
{"mirror_shield", COSMETICS_GROUP_MIRRORSHIELD},
|
||||
{"swords", COSMETICS_GROUP_SWORDS},
|
||||
{"gloves", COSMETICS_GROUP_GLOVES},
|
||||
{"equipment", COSMETICS_GROUP_EQUIPMENT},
|
||||
{"consumable", COSMETICS_GROUP_CONSUMABLE},
|
||||
{"hud", COSMETICS_GROUP_HUD},
|
||||
{"kaleido", COSMETICS_GROUP_KALEIDO},
|
||||
{"title", COSMETICS_GROUP_TITLE},
|
||||
{"npc", COSMETICS_GROUP_NPC},
|
||||
{"world", COSMETICS_GROUP_WORLD},
|
||||
{"magic", COSMETICS_GROUP_MAGIC},
|
||||
{"arrows", COSMETICS_GROUP_ARROWS},
|
||||
{"spin_attack", COSMETICS_GROUP_SPIN_ATTACK},
|
||||
{"trials", COSMETICS_GROUP_TRAILS},
|
||||
{"navi", COSMETICS_GROUP_NAVI},
|
||||
{"ivan", COSMETICS_GROUP_IVAN},
|
||||
}};
|
||||
|
||||
static bool CosmeticsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (args[1].compare("reset") == 0) {
|
||||
CosmeticsEditor_ResetAll();
|
||||
if (args.size() == 2) {
|
||||
CosmeticsEditor_ResetAll();
|
||||
} else {
|
||||
for (const auto& [key, value] : cosmetic_groups) {
|
||||
if (args[2].compare(key) == 0) {
|
||||
CosmeticsEditor_ResetGroup(value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
|
||||
return 1;
|
||||
}
|
||||
} else if (args[1].compare("randomize") == 0) {
|
||||
CosmeticsEditor_RandomizeAll();
|
||||
if (args.size() == 2) {
|
||||
CosmeticsEditor_RandomizeAll();
|
||||
} else {
|
||||
for (const auto& [key, value] : cosmetic_groups) {
|
||||
if (args[2].compare(key) == 0) {
|
||||
CosmeticsEditor_RandomizeGroup(value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
ERROR_MESSAGE("[SOH] Invalid argument passed, must be 'reset' or 'randomize'");
|
||||
return 1;
|
||||
|
@ -1307,16 +1349,50 @@ static bool CosmeticsHandler(std::shared_ptr<LUS::Console> Console, const std::v
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool SfxHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
static std::map<std::string, SeqType> sfx_groups = {
|
||||
{"bgm", SEQ_BGM_WORLD},
|
||||
{"fanfares", SEQ_FANFARE},
|
||||
{"events", SEQ_BGM_EVENT},
|
||||
{"battle", SEQ_BGM_BATTLE},
|
||||
{"ocarina", SEQ_OCARINA},
|
||||
{"instruments", SEQ_INSTRUMENT},
|
||||
{"sfx", SEQ_SFX},
|
||||
{"voices", SEQ_VOICE},
|
||||
{"custom", SEQ_BGM_CUSTOM},
|
||||
};
|
||||
|
||||
static bool SfxHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) {
|
||||
if (args.size() < 2) {
|
||||
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (args[1].compare("reset") == 0) {
|
||||
AudioEditor_ResetAll();
|
||||
if (args.size() == 2) {
|
||||
AudioEditor_ResetAll();
|
||||
} else {
|
||||
for (const auto& [key, value] : sfx_groups) {
|
||||
if (args[2].compare(key) == 0) {
|
||||
AudioEditor_ResetGroup(value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
|
||||
return 1;
|
||||
}
|
||||
} else if (args[1].compare("randomize") == 0) {
|
||||
AudioEditor_RandomizeAll();
|
||||
if (args.size() == 2) {
|
||||
AudioEditor_RandomizeAll();
|
||||
} else {
|
||||
for (const auto& [key, value] : sfx_groups) {
|
||||
if (args[2].compare(key) == 0) {
|
||||
AudioEditor_RandomizeGroup(value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
ERROR_MESSAGE("[SOH] Invalid argument passed, must be 'reset' or 'randomize'");
|
||||
return 1;
|
||||
|
@ -1335,17 +1411,17 @@ void DebugConsole_Init(void) {
|
|||
CMD_REGISTER("save_state", {SaveStateHandler, "Save a state."});
|
||||
CMD_REGISTER("load_state", {LoadStateHandler, "Load a state."});
|
||||
CMD_REGISTER("set_slot", {StateSlotSelectHandler, "Selects a SaveState slot", {
|
||||
{"Slot number", LUS::ArgumentType::NUMBER,}
|
||||
{"Slot number", Ship::ArgumentType::NUMBER,}
|
||||
}});
|
||||
|
||||
// Map & Location
|
||||
CMD_REGISTER("void", {VoidHandler, "Voids out of the current map."});
|
||||
CMD_REGISTER("reload", {ReloadHandler, "Reloads the current map."});
|
||||
CMD_REGISTER("fw", {FWHandler, "Spawns the player where Farore's Wind is set.", {
|
||||
{"clear|warp|backup", LUS::ArgumentType::TEXT}
|
||||
{"clear|warp|backup", Ship::ArgumentType::TEXT}
|
||||
}});
|
||||
CMD_REGISTER("entrance", {EntranceHandler, "Sends player to the entered entrance (hex)", {
|
||||
{"entrance", LUS::ArgumentType::NUMBER}
|
||||
{"entrance", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
// Gameplay
|
||||
|
@ -1354,64 +1430,64 @@ void DebugConsole_Init(void) {
|
|||
CMD_REGISTER("map", {LoadSceneHandler, "Load up kak?"});
|
||||
|
||||
CMD_REGISTER("rupee", {RupeeHandler, "Set your rupee counter.", {
|
||||
{"amount", LUS::ArgumentType::NUMBER}
|
||||
{"amount", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("bItem", {BHandler, "Set an item to the B button.", {
|
||||
{"Item ID", LUS::ArgumentType::NUMBER}
|
||||
{"Item ID", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor name/id", LUS::ArgumentType::NUMBER }, // TODO there should be an actor_id arg type
|
||||
{"data", LUS::ArgumentType::NUMBER},
|
||||
{"x", LUS::ArgumentType::NUMBER, true},
|
||||
{"y", LUS::ArgumentType::NUMBER, true},
|
||||
{"z", LUS::ArgumentType::NUMBER, true},
|
||||
{"rx", LUS::ArgumentType::NUMBER, true},
|
||||
{"ry", LUS::ArgumentType::NUMBER, true},
|
||||
{"rz", LUS::ArgumentType::NUMBER, true}
|
||||
CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor name/id", Ship::ArgumentType::NUMBER }, // TODO there should be an actor_id arg type
|
||||
{"data", Ship::ArgumentType::NUMBER},
|
||||
{"x", Ship::ArgumentType::NUMBER, true},
|
||||
{"y", Ship::ArgumentType::NUMBER, true},
|
||||
{"z", Ship::ArgumentType::NUMBER, true},
|
||||
{"rx", Ship::ArgumentType::NUMBER, true},
|
||||
{"ry", Ship::ArgumentType::NUMBER, true},
|
||||
{"rz", Ship::ArgumentType::NUMBER, true}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("pos", {SetPosHandler, "Sets the position of the player.", {
|
||||
{"x", LUS::ArgumentType::NUMBER, true},
|
||||
{"y", LUS::ArgumentType::NUMBER, true},
|
||||
{"z", LUS::ArgumentType::NUMBER, true}
|
||||
{"x", Ship::ArgumentType::NUMBER, true},
|
||||
{"y", Ship::ArgumentType::NUMBER, true},
|
||||
{"z", Ship::ArgumentType::NUMBER, true}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("addammo", {AddAmmoHandler, "Adds ammo of an item.", {
|
||||
{"sticks|nuts|bombs|seeds|arrows|bombchus|beans", LUS::ArgumentType::TEXT},
|
||||
{"count", LUS::ArgumentType::NUMBER}
|
||||
{"sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT},
|
||||
{"count", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("takeammo", {TakeAmmoHandler, "Removes ammo of an item.", {
|
||||
{"sticks|nuts|bombs|seeds|arrows|bombchus|beans", LUS::ArgumentType::TEXT},
|
||||
{"count", LUS::ArgumentType::NUMBER}
|
||||
{"sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT},
|
||||
{"count", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("bottle", {BottleHandler, "Changes item in a bottle slot.", {
|
||||
{"item", LUS::ArgumentType::TEXT},
|
||||
{"slot", LUS::ArgumentType::NUMBER}
|
||||
{"item", Ship::ArgumentType::TEXT},
|
||||
{"slot", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("give_item", {GiveItemHandler, "Gives an item to the player as if it was given from an actor", {
|
||||
{"vanilla|randomizer", LUS::ArgumentType::TEXT},
|
||||
{"giveItemID", LUS::ArgumentType::NUMBER}
|
||||
{"vanilla|randomizer", Ship::ArgumentType::TEXT},
|
||||
{"giveItemID", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("item", {ItemHandler, "Sets item ID in arg 1 into slot arg 2. No boundary checks. Use with caution.", {
|
||||
{"slot", LUS::ArgumentType::NUMBER},
|
||||
{"item id", LUS::ArgumentType::NUMBER}
|
||||
{"slot", Ship::ArgumentType::NUMBER},
|
||||
{"item id", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("invisible", {InvisibleHandler, "Activate Link's Elvish cloak, making him appear invisible.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("giant_link", {GiantLinkHandler, "Turn Link into a giant Lonky boi.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("minish_link", {MinishLinkHandler, "Turn Link into a minish boi.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("add_heart_container",
|
||||
|
@ -1421,25 +1497,25 @@ void DebugConsole_Init(void) {
|
|||
{RemoveHeartContainerHandler, "Remove a heart from Link. The minimal amount of hearts is 3."});
|
||||
|
||||
CMD_REGISTER("gravity", {GravityHandler, "Set gravity level.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("no_ui", {NoUIHandler, "Disables the UI.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("freeze", {FreezeHandler, "Freezes Link in place"});
|
||||
|
||||
CMD_REGISTER("defense_modifier", {DefenseModifierHandler, "Sets the defense modifier.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("damage", {DamageHandler, "Deal damage to Link.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("heal", {HealHandler, "Heals Link.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("fill_magic", {FillMagicHandler, "Fills magic."});
|
||||
|
@ -1447,50 +1523,50 @@ void DebugConsole_Init(void) {
|
|||
CMD_REGISTER("empty_magic", {EmptyMagicHandler, "Empties magic."});
|
||||
|
||||
CMD_REGISTER("no_z", {NoZHandler, "Disables Z-button presses.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("ohko", {OneHitKOHandler,
|
||||
"Activates one hit KO. Any damage kills Link and he cannot gain health in this mode.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("pacifist", {PacifistHandler, "Activates pacifist mode. Prevents Link from using his weapon.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("paper_link", {PaperLinkHandler, "Link but made out of paper.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("rainstorm", {RainstormHandler, "Activates rainstorm."});
|
||||
|
||||
CMD_REGISTER("reverse_controls", {ReverseControlsHandler, "Reverses the controls.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("update_rupees", {UpdateRupeesHandler, "Adds rupees.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("speed_modifier", {SpeedModifierHandler, "Sets the speed modifier.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("boots", {BootsHandler, "Activates boots.", {
|
||||
{"kokiri|iron|hover", LUS::ArgumentType::TEXT},
|
||||
{"kokiri|iron|hover", Ship::ArgumentType::TEXT},
|
||||
}});
|
||||
|
||||
CMD_REGISTER("giveshield", {GiveShieldHandler, "Gives a shield and equips it when Link is the right age for it.", {
|
||||
{"deku|hylian|mirror", LUS::ArgumentType::TEXT},
|
||||
{"deku|hylian|mirror", Ship::ArgumentType::TEXT},
|
||||
}});
|
||||
|
||||
CMD_REGISTER("takeshield", {TakeShieldHandler, "Takes a shield and unequips it if Link is wearing it.", {
|
||||
{"deku|hylian|mirror", LUS::ArgumentType::TEXT},
|
||||
{"deku|hylian|mirror", Ship::ArgumentType::TEXT},
|
||||
}});
|
||||
|
||||
CMD_REGISTER("knockback", {KnockbackHandler, "Knocks Link back.", {
|
||||
{"value", LUS::ArgumentType::NUMBER}
|
||||
{"value", Ship::ArgumentType::NUMBER}
|
||||
}});
|
||||
|
||||
CMD_REGISTER("electrocute", {ElectrocuteHandler, "Electrocutes Link."});
|
||||
|
@ -1500,16 +1576,18 @@ void DebugConsole_Init(void) {
|
|||
CMD_REGISTER("cucco_storm", {CuccoStormHandler, "Cucco Storm"});
|
||||
|
||||
CMD_REGISTER("gen_rando", {GenerateRandoHandler, "Generate a randomizer seed", {
|
||||
{"seed|count", LUS::ArgumentType::NUMBER, true},
|
||||
{"testing", LUS::ArgumentType::NUMBER, true},
|
||||
{"seed|count", Ship::ArgumentType::NUMBER, true},
|
||||
{"testing", Ship::ArgumentType::NUMBER, true},
|
||||
}});
|
||||
|
||||
CMD_REGISTER("cosmetics", {CosmeticsHandler, "Change cosmetics.", {
|
||||
{"reset|randomize", LUS::ArgumentType::TEXT},
|
||||
{"reset|randomize", Ship::ArgumentType::TEXT},
|
||||
{"group name", Ship::ArgumentType::TEXT, true},
|
||||
}});
|
||||
|
||||
CMD_REGISTER("sfx", {SfxHandler, "Change SFX.", {
|
||||
{"reset|randomize", LUS::ArgumentType::TEXT},
|
||||
{"reset|randomize", Ship::ArgumentType::TEXT},
|
||||
{"group_name", Ship::ArgumentType::TEXT, true},
|
||||
}});
|
||||
|
||||
CVarSave();
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
#include "MessageViewer.h"
|
||||
|
||||
#include <soh/UIWidgets.hpp>
|
||||
#include <textures/message_static/message_static.h>
|
||||
|
||||
#include "../custom-message/CustomMessageManager.h"
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
#include "message_data_static.h"
|
||||
#include "variables.h"
|
||||
#include "soh/util.h"
|
||||
|
||||
extern "C" u8 sMessageHasSetSfx;
|
||||
|
||||
void MessageViewer::InitElement() {
|
||||
CustomMessageManager::Instance->AddCustomMessageTable(TABLE_ID);
|
||||
mTableIdBuf = static_cast<char*>(calloc(MAX_STRING_SIZE, sizeof(char)));
|
||||
mTextIdBuf = static_cast<char*>(calloc(MAX_STRING_SIZE, sizeof(char)));
|
||||
mCustomMessageBuf = static_cast<char*>(calloc(MAX_STRING_SIZE, sizeof(char)));
|
||||
}
|
||||
|
||||
void MessageViewer::DrawElement() {
|
||||
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
|
||||
if (!ImGui::Begin("Custom Message Debugger", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
ImGui::Text("Table ID");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum);
|
||||
UIWidgets::InsertHelpHoverText("Leave blank for vanilla table");
|
||||
ImGui::Text("Text ID");
|
||||
ImGui::SameLine();
|
||||
switch (mTextIdBase) {
|
||||
case DECIMAL:
|
||||
ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsDecimal);
|
||||
UIWidgets::InsertHelpHoverText("Decimal Text ID of the message to load. Decimal digits only (0-9).");
|
||||
break;
|
||||
case HEXADECIMAL:
|
||||
default:
|
||||
ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
UIWidgets::InsertHelpHoverText("Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F).");
|
||||
break;
|
||||
}
|
||||
if (ImGui::RadioButton("Hexadecimal", &mTextIdBase, HEXADECIMAL)) {
|
||||
memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Decimal", &mTextIdBase, DECIMAL)) {
|
||||
memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE);
|
||||
}
|
||||
ImGui::Text("Language");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##Language", mLanguages[mLanguage])) {
|
||||
// ReSharper disable CppDFAUnreachableCode
|
||||
for (size_t i = 0; i < mLanguages.size(); i++) {
|
||||
if (strlen(mLanguages[i]) > 0) {
|
||||
if (ImGui::Selectable(mLanguages[i], i == mLanguage)) {
|
||||
mLanguage = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
UIWidgets::InsertHelpHoverText("Which language to load from the selected text ID");
|
||||
if (ImGui::Button("Display Message##ExistingMessage")) {
|
||||
mDisplayExistingMessageClicked = true;
|
||||
}
|
||||
ImGui::Text("Custom Message");
|
||||
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.");
|
||||
ImGui::InputTextMultiline("##CustomMessage", mCustomMessageBuf, MAX_STRING_SIZE);
|
||||
if (ImGui::Button("Display Message##CustomMessage")) {
|
||||
mDisplayCustomMessageClicked = true;
|
||||
}
|
||||
ImGui::End();
|
||||
// ReSharper restore CppDFAUnreachableCode
|
||||
}
|
||||
|
||||
void MessageViewer::UpdateElement() {
|
||||
if (mDisplayExistingMessageClicked) {
|
||||
mTableId = std::string(mTableIdBuf);
|
||||
switch (mTextIdBase) {
|
||||
case DECIMAL:
|
||||
mTextId = std::stoi(std::string(mTextIdBuf), nullptr, 10);
|
||||
break;
|
||||
case HEXADECIMAL:
|
||||
default:
|
||||
mTextId = std::stoi(std::string(mTextIdBuf), nullptr, 16);
|
||||
break;
|
||||
}
|
||||
DisplayExistingMessage();
|
||||
mDisplayExistingMessageClicked = false;
|
||||
}
|
||||
if (mDisplayCustomMessageClicked) {
|
||||
mCustomMessageString = std::string(mCustomMessageBuf);
|
||||
std::erase(mCustomMessageString, '\n');
|
||||
DisplayCustomMessage();
|
||||
mDisplayCustomMessageClicked = false;
|
||||
}
|
||||
}
|
||||
|
||||
void MessageViewer::DisplayExistingMessage() const {
|
||||
MessageDebug_StartTextBox(mTableId.c_str(), mTextId, mLanguage);
|
||||
}
|
||||
|
||||
void MessageViewer::DisplayCustomMessage() const {
|
||||
MessageDebug_DisplayCustomMessage(mCustomMessageString.c_str());
|
||||
}
|
||||
|
||||
extern "C" MessageTableEntry* sNesMessageEntryTablePtr;
|
||||
extern "C" MessageTableEntry* sGerMessageEntryTablePtr;
|
||||
extern "C" MessageTableEntry* sFraMessageEntryTablePtr;
|
||||
extern "C" MessageTableEntry* sStaffMessageEntryTablePtr;
|
||||
|
||||
void FindMessage(PlayState* play, const uint16_t textId, const uint8_t language) {
|
||||
const char* foundSeg;
|
||||
const char* nextSeg;
|
||||
MessageTableEntry* messageTableEntry = sNesMessageEntryTablePtr;
|
||||
Font* font;
|
||||
u16 bufferId = textId;
|
||||
// Use the better owl message if better owl is enabled
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) != 0 && (bufferId == 0x2066 || bufferId == 0x607B ||
|
||||
bufferId == 0x10C2 || bufferId == 0x10C6 || bufferId == 0x206A))
|
||||
{
|
||||
bufferId = 0x71B3;
|
||||
}
|
||||
|
||||
if (language == LANGUAGE_GER)
|
||||
messageTableEntry = sGerMessageEntryTablePtr;
|
||||
else if (language == LANGUAGE_FRA)
|
||||
messageTableEntry = sFraMessageEntryTablePtr;
|
||||
|
||||
// If PAL languages are not present in the OTR file, default to English
|
||||
if (messageTableEntry == nullptr)
|
||||
messageTableEntry = sNesMessageEntryTablePtr;
|
||||
|
||||
const char* seg = messageTableEntry->segment;
|
||||
|
||||
while (messageTableEntry->textId != 0xFFFF) {
|
||||
font = &play->msgCtx.font;
|
||||
|
||||
if (messageTableEntry->textId == bufferId) {
|
||||
foundSeg = messageTableEntry->segment;
|
||||
font->charTexBuf[0] = messageTableEntry->typePos;
|
||||
|
||||
nextSeg = messageTableEntry->segment;
|
||||
font->msgOffset = reinterpret_cast<uintptr_t>(messageTableEntry->segment);
|
||||
font->msgLength = messageTableEntry->msgSize;
|
||||
return;
|
||||
}
|
||||
messageTableEntry++;
|
||||
}
|
||||
|
||||
font = &play->msgCtx.font;
|
||||
messageTableEntry = sNesMessageEntryTablePtr;
|
||||
|
||||
foundSeg = messageTableEntry->segment;
|
||||
font->charTexBuf[0] = messageTableEntry->typePos;
|
||||
messageTableEntry++;
|
||||
nextSeg = messageTableEntry->segment;
|
||||
font->msgOffset = foundSeg - seg;
|
||||
font->msgLength = nextSeg - foundSeg;
|
||||
}
|
||||
|
||||
static const char* msgStaticTbl[] =
|
||||
{
|
||||
gDefaultMessageBackgroundTex,
|
||||
gSignMessageBackgroundTex,
|
||||
gNoteStaffMessageBackgroundTex,
|
||||
gFadingMessageBackgroundTex,
|
||||
gMessageContinueTriangleTex,
|
||||
gMessageEndSquareTex,
|
||||
gMessageArrowTex
|
||||
};
|
||||
|
||||
void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t language) {
|
||||
PlayState* play = gPlayState;
|
||||
static int16_t messageStaticIndices[] = { 0, 1, 3, 2 };
|
||||
const auto player = GET_PLAYER(gPlayState);
|
||||
player->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
|
||||
MessageContext* msgCtx = &play->msgCtx;
|
||||
msgCtx->ocarinaAction = 0xFFFF;
|
||||
Font* font = &msgCtx->font;
|
||||
sMessageHasSetSfx = 0;
|
||||
for (u32 i = 0; i < FONT_CHAR_TEX_SIZE * 120; i += FONT_CHAR_TEX_SIZE) {
|
||||
if (&font->charTexBuf[i] != nullptr) {
|
||||
gSPInvalidateTexCache(play->state.gfxCtx->polyOpa.p++, reinterpret_cast<uintptr_t>(&font->charTexBuf[i]));
|
||||
}
|
||||
}
|
||||
R_TEXT_CHAR_SCALE = 75;
|
||||
R_TEXT_LINE_SPACING = 12;
|
||||
R_TEXT_INIT_XPOS = 65;
|
||||
char* buffer = font->msgBuf;
|
||||
msgCtx->textId = textId;
|
||||
if (strlen(tableId) == 0) {
|
||||
FindMessage(play, textId, language);
|
||||
msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
|
||||
const uintptr_t src = font->msgOffset;
|
||||
memcpy(font->msgBuf, reinterpret_cast<void const *>(src), font->msgLength);
|
||||
} else {
|
||||
constexpr int maxBufferSize = sizeof(font->msgBuf);
|
||||
const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId);
|
||||
font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition();
|
||||
switch (language) {
|
||||
case LANGUAGE_FRA:
|
||||
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetFrench(), maxBufferSize);
|
||||
break;
|
||||
case LANGUAGE_GER:
|
||||
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetGerman(), maxBufferSize);
|
||||
break;
|
||||
case LANGUAGE_ENG:
|
||||
default:
|
||||
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetEnglish(), maxBufferSize);
|
||||
break;
|
||||
}
|
||||
msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
|
||||
}
|
||||
msgCtx->textBoxProperties = font->charTexBuf[0];
|
||||
msgCtx->textBoxType = msgCtx->textBoxProperties >> 4;
|
||||
msgCtx->textBoxPos = msgCtx->textBoxProperties & 0xF;
|
||||
const int16_t textBoxType = msgCtx->textBoxType;
|
||||
// "Text Box Type"
|
||||
osSyncPrintf("吹き出し種類=%d\n", msgCtx->textBoxType);
|
||||
if (textBoxType < TEXTBOX_TYPE_NONE_BOTTOM) {
|
||||
const char* textureName = msgStaticTbl[messageStaticIndices[textBoxType]];
|
||||
memcpy(msgCtx->textboxSegment, textureName, strlen(textureName) + 1);
|
||||
if (textBoxType == TEXTBOX_TYPE_BLACK) {
|
||||
msgCtx->textboxColorRed = 0;
|
||||
msgCtx->textboxColorGreen = 0;
|
||||
msgCtx->textboxColorBlue = 0;
|
||||
} else if (textBoxType == TEXTBOX_TYPE_WOODEN) {
|
||||
msgCtx->textboxColorRed = 70;
|
||||
msgCtx->textboxColorGreen = 50;
|
||||
msgCtx->textboxColorBlue = 30;
|
||||
} else if (textBoxType == TEXTBOX_TYPE_BLUE) {
|
||||
msgCtx->textboxColorRed = 0;
|
||||
msgCtx->textboxColorGreen = 10;
|
||||
msgCtx->textboxColorBlue = 50;
|
||||
} else {
|
||||
msgCtx->textboxColorRed = 255;
|
||||
msgCtx->textboxColorGreen = 0;
|
||||
msgCtx->textboxColorBlue = 0;
|
||||
}
|
||||
if (textBoxType == TEXTBOX_TYPE_WOODEN) {
|
||||
msgCtx->textboxColorAlphaTarget = 230;
|
||||
} else if (textBoxType == TEXTBOX_TYPE_OCARINA) {
|
||||
msgCtx->textboxColorAlphaTarget = 180;
|
||||
} else {
|
||||
msgCtx->textboxColorAlphaTarget = 170;
|
||||
}
|
||||
msgCtx->textboxColorAlphaCurrent = 0;
|
||||
}
|
||||
msgCtx->choiceNum = msgCtx->textUnskippable = msgCtx->textboxEndType = 0;
|
||||
msgCtx->msgBufPos = msgCtx->unk_E3D0 = msgCtx->textDrawPos = 0;
|
||||
msgCtx->talkActor = &player->actor;
|
||||
msgCtx->msgMode = MSGMODE_TEXT_START;
|
||||
msgCtx->stateTimer = 0;
|
||||
msgCtx->textDelayTimer = 0;
|
||||
msgCtx->ocarinaMode = OCARINA_MODE_00;
|
||||
}
|
||||
|
||||
void MessageDebug_DisplayCustomMessage(const char* customMessage) {
|
||||
CustomMessageManager::Instance->ClearMessageTable(MessageViewer::TABLE_ID);
|
||||
CustomMessageManager::Instance->CreateMessage(MessageViewer::TABLE_ID, 0,
|
||||
CustomMessage(customMessage, customMessage, customMessage));
|
||||
MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef CUSTOMMESSAGEDEBUGGER_H
|
||||
#define CUSTOMMESSAGEDEBUGGER_H
|
||||
#include "z64.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "GuiWindow.h"
|
||||
#include <array>
|
||||
extern "C" {
|
||||
#endif
|
||||
/**
|
||||
* \brief Pulls a message from the specified message table and kicks off the process of displaying that message
|
||||
* in a text box on screen.
|
||||
* \param tableId the tableId string for the table we want to pull from. Empty string for authentic/vanilla messages
|
||||
* \param textId The textId corresponding to the message to display. Putting in a textId that doesn't exist will
|
||||
* probably result in a crash.
|
||||
* \param language The Language to display on the screen.
|
||||
*/
|
||||
void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t language);
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* \param customMessage A string using Custom Message Syntax.
|
||||
*/
|
||||
void MessageDebug_DisplayCustomMessage(const char* customMessage);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
|
||||
class MessageViewer : public Ship::GuiWindow {
|
||||
public:
|
||||
static inline const char* TABLE_ID = "MessageViewer";
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
void InitElement() override;
|
||||
void DrawElement() override;
|
||||
void UpdateElement() override;
|
||||
|
||||
virtual ~MessageViewer() = default;
|
||||
|
||||
private:
|
||||
void DisplayExistingMessage() const;
|
||||
void DisplayCustomMessage() const;
|
||||
|
||||
static constexpr uint16_t MAX_STRING_SIZE = 1024;
|
||||
static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = {"English", "German", "French"};
|
||||
static constexpr int HEXADECIMAL = 0;
|
||||
static constexpr int DECIMAL = 1;
|
||||
char* mTableIdBuf;
|
||||
std::string mTableId;
|
||||
char* mTextIdBuf;
|
||||
uint16_t mTextId;
|
||||
int mTextIdBase = HEXADECIMAL;
|
||||
size_t mLanguage = LANGUAGE_ENG;
|
||||
char* mCustomMessageBuf;
|
||||
std::string mCustomMessageString;
|
||||
bool mDisplayExistingMessageClicked = false;
|
||||
bool mDisplayCustomMessageClicked = false;
|
||||
};
|
||||
|
||||
|
||||
#endif //__cplusplus
|
||||
#endif //CUSTOMMESSAGEDEBUGGER_H
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
class ActorViewerWindow : public LUS::GuiWindow {
|
||||
class ActorViewerWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ typedef enum {
|
|||
} ColViewerRenderSetting;
|
||||
|
||||
#ifdef __cplusplus
|
||||
class ColViewerWindow : public LUS::GuiWindow {
|
||||
class ColViewerWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
|
|
|
@ -614,7 +614,7 @@ void DrawInfoTab() {
|
|||
|
||||
void DrawBGSItemFlag(uint8_t itemID) {
|
||||
const ItemMapEntry& slotEntry = itemMapping[itemID];
|
||||
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1));
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1));
|
||||
ImGui::SameLine();
|
||||
int tradeIndex = itemID - ITEM_POCKET_EGG;
|
||||
bool hasItem = (gSaveContext.adultTradeItems & (1 << tradeIndex)) != 0;
|
||||
|
@ -656,7 +656,7 @@ void DrawInventoryTab() {
|
|||
uint8_t item = gSaveContext.inventory.items[index];
|
||||
if (item != ITEM_NONE) {
|
||||
const ItemMapEntry& slotEntry = itemMapping.find(item)->second;
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0),
|
||||
ImVec2(1, 1), 0)) {
|
||||
selectedIndex = index;
|
||||
ImGui::OpenPopup(itemPopupPicker);
|
||||
|
@ -704,7 +704,7 @@ void DrawInventoryTab() {
|
|||
ImGui::SameLine();
|
||||
}
|
||||
const ItemMapEntry& slotEntry = possibleItems[pickerIndex];
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f),
|
||||
ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||
gSaveContext.inventory.items[selectedIndex] = slotEntry.id;
|
||||
// Set adult trade item flag if you're playing adult trade shuffle in rando
|
||||
|
@ -742,7 +742,7 @@ void DrawInventoryTab() {
|
|||
ImGui::PushItemWidth(32.0f);
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[item].name), ImVec2(32.0f, 32.0f));
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[item].name), ImVec2(32.0f, 32.0f));
|
||||
ImGui::InputScalar("##ammoInput", ImGuiDataType_S8, &AMMO(item));
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
@ -1157,7 +1157,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
|
|||
uint8_t item = items[CUR_UPG_VALUE(categoryId)];
|
||||
if (item != ITEM_NONE) {
|
||||
const ItemMapEntry& slotEntry = itemMapping[item];
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0),
|
||||
ImVec2(1, 1), 0)) {
|
||||
ImGui::OpenPopup(upgradePopupPicker);
|
||||
}
|
||||
|
@ -1185,7 +1185,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
|
|||
UIWidgets::SetLastItemHoverText("None");
|
||||
} else {
|
||||
const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]];
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0),
|
||||
ImVec2(1, 1), 0)) {
|
||||
Inventory_ChangeUpgrade(categoryId, pickerIndex);
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
@ -1222,7 +1222,7 @@ void DrawEquipmentTab() {
|
|||
bool hasEquip = (bitMask & gSaveContext.inventory.equipment) != 0;
|
||||
const ItemMapEntry& entry = itemMapping[equipmentValues[i]];
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip ? entry.name : entry.nameFaded),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip ? entry.name : entry.nameFaded),
|
||||
ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||
if (hasEquip) {
|
||||
gSaveContext.inventory.equipment &= ~bitMask;
|
||||
|
@ -1321,7 +1321,7 @@ void DrawQuestItemButton(uint32_t item) {
|
|||
uint32_t bitMask = 1 << entry.id;
|
||||
bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded),
|
||||
ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||
if (hasQuestItem) {
|
||||
gSaveContext.inventory.questItems &= ~bitMask;
|
||||
|
@ -1339,7 +1339,7 @@ void DrawDungeonItemButton(uint32_t item, uint32_t scene) {
|
|||
uint32_t bitMask = 1 << (entry.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential
|
||||
bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[scene]) != 0;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem ? entry.name : entry.nameFaded),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem ? entry.name : entry.nameFaded),
|
||||
ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||
if (hasItem) {
|
||||
gSaveContext.inventory.dungeonItems[scene] &= ~bitMask;
|
||||
|
@ -1386,7 +1386,7 @@ void DrawQuestStatusTab() {
|
|||
uint32_t bitMask = 1 << entry.id;
|
||||
bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded),
|
||||
if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded),
|
||||
ImVec2(16.0f, 24.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||
if (hasQuestItem) {
|
||||
gSaveContext.inventory.questItems &= ~bitMask;
|
||||
|
@ -1449,7 +1449,7 @@ void DrawQuestStatusTab() {
|
|||
|
||||
if (dungeonItemsScene != SCENE_JABU_JABU_BOSS) {
|
||||
float lineHeight = ImGui::GetTextLineHeightWithSpacing();
|
||||
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[ITEM_KEY_SMALL].name), ImVec2(lineHeight, lineHeight));
|
||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[ITEM_KEY_SMALL].name), ImVec2(lineHeight, lineHeight));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::InputScalar("##Keys", ImGuiDataType_S8, gSaveContext.inventory.dungeonKeys + dungeonItemsScene)) {
|
||||
gSaveContext.sohStats.dungeonKeys[dungeonItemsScene] = gSaveContext.inventory.dungeonKeys[dungeonItemsScene];
|
||||
|
@ -1793,34 +1793,34 @@ void SaveEditorWindow::DrawElement() {
|
|||
void SaveEditorWindow::InitElement() {
|
||||
// Load item icons into ImGui
|
||||
for (const auto& entry : itemMapping) {
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1));
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
|
||||
}
|
||||
for (const auto& entry : gregMapping) {
|
||||
ImVec4 gregGreen = ImVec4(42.0f / 255.0f, 169.0f / 255.0f, 40.0f / 255.0f, 1.0f);
|
||||
ImVec4 gregFadedGreen = gregGreen;
|
||||
gregFadedGreen.w = 0.3f;
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, gregGreen);
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, gregFadedGreen);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, gregGreen);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, gregFadedGreen);
|
||||
}
|
||||
for (const auto& entry : triforcePieceMapping) {
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1));
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
|
||||
}
|
||||
for (const auto& entry : questMapping) {
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1));
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
|
||||
}
|
||||
for (const auto& entry : songMapping) {
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color);
|
||||
ImVec4 fadedCol = entry.color;
|
||||
fadedCol.w = 0.3f;
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol);
|
||||
}
|
||||
for (const auto& entry : vanillaSongMapping) {
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color);
|
||||
ImVec4 fadedCol = entry.color;
|
||||
fadedCol.w = 0.3f;
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -590,7 +590,7 @@ const std::vector<std::string> state3 = {
|
|||
"Travelling to Hook Target"
|
||||
};
|
||||
|
||||
class SaveEditorWindow : public LUS::GuiWindow {
|
||||
class SaveEditorWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <bit>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <libultraship/libultraship.h>
|
||||
#include "dlViewer.h"
|
||||
|
||||
|
@ -66,16 +65,14 @@ std::map<int, std::string> cmdMap = {
|
|||
};
|
||||
|
||||
void PerformDisplayListSearch() {
|
||||
auto result = LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->ListFiles("*" + std::string(searchString) + "*DL*");
|
||||
|
||||
std::regex dlSearch(".*((DL)|(DL_.*))$");
|
||||
auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*");
|
||||
|
||||
displayListSearchResults.clear();
|
||||
|
||||
// Filter the file results even further as StormLib can only use wildcard searching
|
||||
for (size_t i = 0; i < result->size(); i++) {
|
||||
std::string val = result->at(i);
|
||||
if (std::regex_search(val.c_str(), dlSearch)) {
|
||||
if (val.ends_with("DL") || val.find("DL_") != std::string::npos) {
|
||||
displayListSearchResults.push_back(val);
|
||||
}
|
||||
}
|
||||
|
@ -99,8 +96,6 @@ void DLViewerWindow::DrawElement() {
|
|||
return;
|
||||
}
|
||||
|
||||
ImGui::Text("%d", searchDebounceFrames);
|
||||
|
||||
// Debounce the search field as listing otr files is expensive
|
||||
if (ImGui::InputText("Search Display Lists", searchString, ARRAY_COUNT(searchString))) {
|
||||
doSearch = true;
|
||||
|
@ -132,9 +127,9 @@ void DLViewerWindow::DrawElement() {
|
|||
}
|
||||
|
||||
try {
|
||||
auto res = std::static_pointer_cast<LUS::DisplayList>(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList));
|
||||
auto res = std::static_pointer_cast<LUS::DisplayList>(Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList));
|
||||
|
||||
if (res->GetInitData()->Type != LUS::ResourceType::DisplayList) {
|
||||
if (res->GetInitData()->Type != static_cast<uint32_t>(LUS::ResourceType::DisplayList)) {
|
||||
ImGui::Text("Resource type is not a Display List. Please choose another.");
|
||||
ImGui::End();
|
||||
return;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
class DLViewerWindow : public LUS::GuiWindow {
|
||||
class DLViewerWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef struct {
|
|||
uint32_t y;
|
||||
} ValueTableElement;
|
||||
|
||||
class ValueViewerWindow : public LUS::GuiWindow {
|
||||
class ValueViewerWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "soh/Enhancements/randomizer/3drando/random.hpp"
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include "variables.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
|
@ -233,7 +234,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
|
|||
}
|
||||
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
|
||||
if (CVarGetInteger("gRandomizedEnemies", ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
|
||||
uint32_t finalSeed = seed + (IS_RANDO ? gSaveContext.finalSeed : gSaveContext.sohStats.fileCreatedAt);
|
||||
Random_Init(finalSeed);
|
||||
}
|
||||
|
|
|
@ -78,4 +78,10 @@ typedef enum {
|
|||
DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE,
|
||||
} DekuStickType;
|
||||
|
||||
typedef enum {
|
||||
SWORD_TOGGLE_NONE,
|
||||
SWORD_TOGGLE_CHILD,
|
||||
SWORD_TOGGLE_BOTH_AGES,
|
||||
} SwordToggleMode;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,12 +37,19 @@ GameInteractionEffectQueryResult GameInteractor::RemoveEffect(RemovableGameInter
|
|||
|
||||
// MARK: - Helpers
|
||||
|
||||
bool GameInteractor::IsSaveLoaded() {
|
||||
bool GameInteractor::IsSaveLoaded(bool allowDbgSave) {
|
||||
Player* player;
|
||||
if (gPlayState != NULL) {
|
||||
player = GET_PLAYER(gPlayState);
|
||||
}
|
||||
return (gPlayState == NULL || player == NULL || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) ? false : true;
|
||||
|
||||
// Checking for normal game mode prevents debug saves from reporting true on title screen
|
||||
if (gPlayState == NULL || player == NULL || gSaveContext.gameMode != GAMEMODE_NORMAL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Valid save file or debug save
|
||||
return (gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) || (allowDbgSave && gSaveContext.fileNum == 0xFF);
|
||||
}
|
||||
|
||||
bool GameInteractor::IsGameplayPaused() {
|
||||
|
|
|
@ -163,11 +163,30 @@ public:
|
|||
static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect);
|
||||
|
||||
// Game Hooks
|
||||
template <typename H> struct RegisteredGameHooks { inline static std::vector<typename H::fn> functions; };
|
||||
template <typename H> void RegisterGameHook(typename H::fn h) { RegisteredGameHooks<H>::functions.push_back(h); }
|
||||
uint32_t nextHookId = 1;
|
||||
template <typename H> struct RegisteredGameHooks { inline static std::unordered_map<uint32_t, typename H::fn> functions; };
|
||||
template <typename H> struct HooksToUnregister { inline static std::vector<uint32_t> hooks; };
|
||||
template <typename H> uint32_t RegisterGameHook(typename H::fn h) {
|
||||
// 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;
|
||||
while (RegisteredGameHooks<H>::functions.find(this->nextHookId) != RegisteredGameHooks<H>::functions.end()) {
|
||||
this->nextHookId++;
|
||||
}
|
||||
|
||||
RegisteredGameHooks<H>::functions[this->nextHookId] = h;
|
||||
return this->nextHookId++;
|
||||
}
|
||||
template <typename H> void UnregisterGameHook(uint32_t id) {
|
||||
HooksToUnregister<H>::hooks.push_back(id);
|
||||
}
|
||||
|
||||
template <typename H, typename... Args> void ExecuteHooks(Args&&... args) {
|
||||
for (auto& fn : RegisteredGameHooks<H>::functions) {
|
||||
fn(std::forward<Args>(args)...);
|
||||
for (auto& hookId : HooksToUnregister<H>::hooks) {
|
||||
RegisteredGameHooks<H>::functions.erase(hookId);
|
||||
}
|
||||
HooksToUnregister<H>::hooks.clear();
|
||||
for (auto& hook : RegisteredGameHooks<H>::functions) {
|
||||
hook.second(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,9 +240,10 @@ public:
|
|||
|
||||
DEFINE_HOOK(OnFileDropped, void(std::string filePath));
|
||||
DEFINE_HOOK(OnAssetAltChange, void());
|
||||
DEFINE_HOOK(OnKaleidoUpdate, void());
|
||||
|
||||
// Helpers
|
||||
static bool IsSaveLoaded();
|
||||
static bool IsSaveLoaded(bool allowDbgSave = false);
|
||||
static bool IsGameplayPaused();
|
||||
static bool CanSpawnActor();
|
||||
static bool CanAddOrTakeAmmo(int16_t amount, int16_t item);
|
||||
|
|
|
@ -187,3 +187,9 @@ void GameInteractor_ExecuteOnSetGameLanguage() {
|
|||
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn);
|
||||
}
|
||||
|
||||
//MARK: Pause Menu
|
||||
|
||||
void GameInteractor_ExecuteOnKaleidoUpdate() {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnKaleidoUpdate>();
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ void GameInteractor_ExecuteOnSetGameLanguage();
|
|||
// MARK: - System
|
||||
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void));
|
||||
|
||||
//Mark: - Pause Menu
|
||||
void GameInteractor_ExecuteOnKaleidoUpdate();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -111,9 +111,9 @@ void GameInteractor::RawAction::FreezePlayer() {
|
|||
void GameInteractor::RawAction::BurnPlayer() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
for (int i = 0; i < 18; i++) {
|
||||
player->flameTimers[i] = Rand_S16Offset(0, 200);
|
||||
player->bodyFlameTimers[i] = Rand_S16Offset(0, 200);
|
||||
}
|
||||
player->isBurning = true;
|
||||
player->bodyIsBurning = true;
|
||||
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -428,55 +428,55 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint
|
|||
|
||||
switch (cosmeticCategory) {
|
||||
case GI_COSMETICS_TUNICS:
|
||||
CVarSetColor("gCosmetics.Link_KokiriTunic.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Link_KokiriTunic.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Link_GoronTunic.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Link_GoronTunic.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Link_ZoraTunic.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Link_ZoraTunic.Changed", 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Link.KokiriTunic.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Link.KokiriTunic.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Link.GoronTunic.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Link.GoronTunic.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Link.ZoraTunic.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Link.ZoraTunic.Changed"), 1);
|
||||
break;
|
||||
case GI_COSMETICS_NAVI:
|
||||
CVarSetColor("gCosmetics.Navi_EnemyPrimary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_EnemyPrimary.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Navi_EnemySecondary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_EnemySecondary.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Navi_IdlePrimary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_IdlePrimary.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Navi_IdleSecondary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_IdleSecondary.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Navi_NPCPrimary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_NPCPrimary.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Navi_NPCSecondary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_NPCSecondary.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Navi_PropsPrimary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_PropsPrimary.Changed", 1);
|
||||
CVarSetColor("gCosmetics.Navi_PropsSecondary.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Navi_PropsSecondary.Changed", 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.EnemySecondary.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.IdlePrimary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.IdleSecondary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.IdleSecondary.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.NPCPrimary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.NPCSecondary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.NPCSecondary.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.PropsPrimary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Navi.PropsSecondary.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Navi.PropsSecondary.Changed"), 1);
|
||||
break;
|
||||
case GI_COSMETICS_HAIR:
|
||||
CVarSetColor("gCosmetics.Link_Hair.Value", newColor);
|
||||
CVarSetInteger("gCosmetics.Link_Hair.Changed", 1);
|
||||
CVarSetColor(CVAR_COSMETIC("Link.Hair.Value"), newColor);
|
||||
CVarSetInteger(CVAR_COSMETIC("Link.Hair.Changed"), 1);
|
||||
break;
|
||||
}
|
||||
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
ApplyOrResetCustomGfxPatches();
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) {
|
||||
const char* cvarsToLock[12] = {
|
||||
"gCosmetics.Link_KokiriTunic.Locked",
|
||||
"gCosmetics.Link_GoronTunic.Locked",
|
||||
"gCosmetics.Link_ZoraTunic.Locked",
|
||||
"gCosmetics.Navi_EnemyPrimary.Locked",
|
||||
"gCosmetics.Navi_EnemySecondary.Locked",
|
||||
"gCosmetics.Navi_IdlePrimary.Locked",
|
||||
"gCosmetics.Navi_IdleSecondary.Locked",
|
||||
"gCosmetics.Navi_NPCPrimary.Locked",
|
||||
"gCosmetics.Navi_NPCSecondary.Locked",
|
||||
"gCosmetics.Navi_PropsPrimary.Locked",
|
||||
"gCosmetics.Navi_PropsSecondary.Locked",
|
||||
"gCosmetics.Link_Hair.Locked"
|
||||
CVAR_COSMETIC("Link.KokiriTunic.Locked"),
|
||||
CVAR_COSMETIC("Link.GoronTunic.Locked"),
|
||||
CVAR_COSMETIC("Link.ZoraTunic.Locked"),
|
||||
CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
|
||||
CVAR_COSMETIC("Navi.EnemySecondary.Locked"),
|
||||
CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
|
||||
CVAR_COSMETIC("Navi.IdleSecondary.Locked"),
|
||||
CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
|
||||
CVAR_COSMETIC("Navi.NPCSecondary.Locked"),
|
||||
CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
|
||||
CVAR_COSMETIC("Navi.PropsSecondary.Locked"),
|
||||
CVAR_COSMETIC("Link.Hair.Locked")
|
||||
};
|
||||
|
||||
if (excludeBiddingWarColors) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <libultraship/libultraship.h>
|
||||
#include "soh/OTRGlobals.h"
|
||||
|
||||
// MARK: - Remote
|
||||
|
||||
|
@ -16,7 +17,7 @@ void GameInteractor::EnableRemoteInteractor() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (SDLNet_ResolveHost(&remoteIP, CVarGetString("gRemote.IP", "127.0.0.1"), CVarGetInteger("gRemote.Port", 43384)) == -1) {
|
||||
if (SDLNet_ResolveHost(&remoteIP, CVarGetString(CVAR_REMOTE("IP"), "127.0.0.1"), CVarGetInteger(CVAR_REMOTE("Port"), 43384)) == -1) {
|
||||
SPDLOG_ERROR("[GameInteractor] SDLNet_ResolveHost: {}", SDLNet_GetError());
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ void GameInteractorSail::HandleRemoteJson(nlohmann::json payload) {
|
|||
}
|
||||
|
||||
std::string command = payload["command"].get<std::string>();
|
||||
std::reinterpret_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command);
|
||||
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command);
|
||||
responsePayload["status"] = "success";
|
||||
GameInteractor::Instance->TransmitJsonToRemote(responsePayload);
|
||||
return;
|
||||
|
@ -88,7 +88,7 @@ void GameInteractorSail::HandleRemoteJson(nlohmann::json payload) {
|
|||
}
|
||||
|
||||
std::string command = payload["effect"]["command"].get<std::string>();
|
||||
std::reinterpret_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command);
|
||||
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command);
|
||||
responsePayload["status"] = "success";
|
||||
GameInteractor::Instance->TransmitJsonToRemote(responsePayload);
|
||||
return;
|
||||
|
|
|
@ -14,6 +14,7 @@ extern "C" {
|
|||
#include <libultraship/bridge.h>
|
||||
#include <libultraship/libultraship.h>
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
|
@ -538,7 +539,7 @@ void DrawGameplayStatsCountsTab() {
|
|||
GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_SWORD_SWINGS]));
|
||||
GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_STEPS]));
|
||||
// If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time)
|
||||
if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
|
||||
GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] / 2));
|
||||
}
|
||||
GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_ROLLS]));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <libultraship/libultraship.h>
|
||||
#include "gameplaystats.h"
|
||||
|
||||
class GameplayStatsWindow : public LUS::GuiWindow {
|
||||
class GameplayStatsWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include "src/overlays/actors/ovl_En_Tp/z_en_tp.h"
|
||||
#include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h"
|
||||
#include "src/overlays/actors/ovl_En_Xc/z_en_xc.h"
|
||||
#include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h"
|
||||
#include "objects/object_link_boy/object_link_boy.h"
|
||||
#include "objects/object_link_child/object_link_child.h"
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
|
@ -31,6 +34,7 @@ extern "C" {
|
|||
#include "functions.h"
|
||||
#include "variables.h"
|
||||
#include "functions.h"
|
||||
#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
|
||||
void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction);
|
||||
void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
|
||||
|
||||
|
@ -61,8 +65,8 @@ void ReloadSceneTogglingLinkAge() {
|
|||
|
||||
void RegisterInfiniteMoney() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (CVarGetInteger("gInfiniteMoney", 0) != 0) {
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
if (CVarGetInteger(CVAR_CHEAT("InfiniteMoney"), 0) != 0) {
|
||||
if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) {
|
||||
gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET);
|
||||
}
|
||||
|
@ -72,8 +76,8 @@ void RegisterInfiniteMoney() {
|
|||
|
||||
void RegisterInfiniteHealth() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (CVarGetInteger("gInfiniteHealth", 0) != 0) {
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
if (CVarGetInteger(CVAR_CHEAT("InfiniteHealth"), 0) != 0) {
|
||||
if (gSaveContext.health < gSaveContext.healthCapacity) {
|
||||
gSaveContext.health = gSaveContext.healthCapacity;
|
||||
}
|
||||
|
@ -83,8 +87,8 @@ void RegisterInfiniteHealth() {
|
|||
|
||||
void RegisterInfiniteAmmo() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (CVarGetInteger("gInfiniteAmmo", 0) != 0) {
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
if (CVarGetInteger(CVAR_CHEAT("InfiniteAmmo"), 0) != 0) {
|
||||
// Deku Sticks
|
||||
if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) {
|
||||
AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS);
|
||||
|
@ -120,8 +124,8 @@ void RegisterInfiniteAmmo() {
|
|||
|
||||
void RegisterInfiniteMagic() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (CVarGetInteger("gInfiniteMagic", 0) != 0) {
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
if (CVarGetInteger(CVAR_CHEAT("InfiniteMagic"), 0) != 0) {
|
||||
if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) {
|
||||
gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30;
|
||||
}
|
||||
|
@ -131,8 +135,8 @@ void RegisterInfiniteMagic() {
|
|||
|
||||
void RegisterInfiniteNayrusLove() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (CVarGetInteger("gInfiniteNayru", 0) != 0) {
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
if (CVarGetInteger(CVAR_CHEAT("InfiniteNayru"), 0) != 0) {
|
||||
gSaveContext.nayrusLoveTimer = 0x44B;
|
||||
}
|
||||
});
|
||||
|
@ -140,9 +144,9 @@ void RegisterInfiniteNayrusLove() {
|
|||
|
||||
void RegisterMoonJumpOnL() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
|
||||
if (CVarGetInteger("gMoonJumpOnL", 0) != 0) {
|
||||
if (CVarGetInteger(CVAR_CHEAT("MoonJumpOnL"), 0) != 0) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
|
||||
if (CHECK_BTN_ANY(gPlayState->state.input[0].cur.button, BTN_L)) {
|
||||
|
@ -155,9 +159,9 @@ void RegisterMoonJumpOnL() {
|
|||
|
||||
void RegisterInfiniteISG() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
|
||||
if (CVarGetInteger("gEzISG", 0) != 0) {
|
||||
if (CVarGetInteger(CVAR_CHEAT("EasyISG"), 0) != 0) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
player->meleeWeaponState = 1;
|
||||
}
|
||||
|
@ -167,9 +171,9 @@ void RegisterInfiniteISG() {
|
|||
//Permanent quick put away (QPA) glitched damage value
|
||||
void RegisterEzQPA() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
|
||||
if (CVarGetInteger("gEzQPA", 0) != 0) {
|
||||
if (CVarGetInteger(CVAR_CHEAT("EasyQPA"), 0) != 0) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
player->meleeWeaponQuads[0].info.toucher.dmgFlags = 0x16171617;
|
||||
player->meleeWeaponQuads[1].info.toucher.dmgFlags = 0x16171617;
|
||||
|
@ -179,9 +183,9 @@ void RegisterEzQPA() {
|
|||
|
||||
void RegisterUnrestrictedItems() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||
|
||||
if (CVarGetInteger("gNoRestrictItems", 0) != 0) {
|
||||
if (CVarGetInteger(CVAR_CHEAT("NoRestrictItems"), 0) != 0) {
|
||||
u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
|
||||
memset(&gPlayState->interfaceCtx.restrictions, 0, sizeof(gPlayState->interfaceCtx.restrictions));
|
||||
gPlayState->interfaceCtx.restrictions.sunsSong = sunsBackup;
|
||||
|
@ -191,7 +195,7 @@ void RegisterUnrestrictedItems() {
|
|||
|
||||
void RegisterFreezeTime() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (CVarGetInteger("gFreezeTime", 0) != 0) {
|
||||
if (CVarGetInteger(CVAR_CHEAT("FreezeTime"), 0) != 0) {
|
||||
if (CVarGetInteger("gPrevTime", -1) == -1) {
|
||||
CVarSetInteger("gPrevTime", gSaveContext.dayTime);
|
||||
}
|
||||
|
@ -207,17 +211,20 @@ void RegisterFreezeTime() {
|
|||
/// Switches Link's age and respawns him at the last entrance he entered.
|
||||
void RegisterSwitchAge() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
CVarClear("gSwitchAge");
|
||||
static bool warped = false;
|
||||
|
||||
if (!GameInteractor::IsSaveLoaded(true)) {
|
||||
CVarClear(CVAR_GENERAL("SwitchAge"));
|
||||
warped = false;
|
||||
return;
|
||||
}
|
||||
static bool warped = false;
|
||||
|
||||
static Vec3f playerPos;
|
||||
static int16_t playerYaw;
|
||||
static RoomContext* roomCtx;
|
||||
static s32 roomNum;
|
||||
|
||||
if (CVarGetInteger("gSwitchAge", 0) && !warped) {
|
||||
if (CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) && !warped) {
|
||||
playerPos = GET_PLAYER(gPlayState)->actor.world.pos;
|
||||
playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y;
|
||||
roomCtx = &gPlayState->roomCtx;
|
||||
|
@ -236,7 +243,7 @@ void RegisterSwitchAge() {
|
|||
func_80097534(gPlayState, roomCtx); // load map for new room (unloading the previous room)
|
||||
}
|
||||
warped = false;
|
||||
CVarClear("gSwitchAge");
|
||||
CVarClear(CVAR_GENERAL("SwitchAge"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -245,8 +252,8 @@ void RegisterSwitchAge() {
|
|||
void RegisterOcarinaTimeTravel() {
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnOcarinaSongAction>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
CVarClear("gTimeTravel");
|
||||
if (!GameInteractor::IsSaveLoaded(true)) {
|
||||
CVarClear(CVAR_ENHANCEMENT("TimeTravel"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -260,7 +267,7 @@ void RegisterOcarinaTimeTravel() {
|
|||
uint8_t hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME);
|
||||
// If TimeTravel + Player have the Ocarina of Time + Have Master Sword + is in proper range
|
||||
// TODO: Once Swordless Adult is fixed: Remove the Master Sword check
|
||||
if (((CVarGetInteger("gTimeTravel", 0) == 1 && hasOcarinaOfTime) || CVarGetInteger("gTimeTravel", 0) == 2) && hasMasterSword &&
|
||||
if (((CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 1 && hasOcarinaOfTime) || CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2) && hasMasterSword &&
|
||||
gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME && !nearbyTimeBlockEmpty && !nearbyTimeBlock &&
|
||||
!nearbyOcarinaSpot && !nearbyFrogs) {
|
||||
|
||||
|
@ -282,13 +289,13 @@ void AutoSave(GetItemEntry itemEntry) {
|
|||
// Don't autosave immediately after buying items from shops to prevent getting them for free!
|
||||
// Don't autosave in the Chamber of Sages since resuming from that map breaks the game
|
||||
// Don't autosave during the Ganon fight when picking up the Master Sword
|
||||
if ((CVarGetInteger("gAutosave", AUTOSAVE_OFF) != AUTOSAVE_OFF) && (gPlayState != NULL) && (gSaveContext.pendingSale == ITEM_NONE) &&
|
||||
if ((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) != AUTOSAVE_OFF) && (gPlayState != NULL) && (gSaveContext.pendingSale == ITEM_NONE) &&
|
||||
(gPlayState->gameplayFrames > 60 && gSaveContext.cutsceneIndex < 0xFFF0) && (gPlayState->sceneNum != SCENE_GANON_BOSS) && (gPlayState->sceneNum != SCENE_CHAMBER_OF_THE_SAGES)) {
|
||||
if (((CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS) || (CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_ALL_ITEMS)) && (item != ITEM_NONE)) {
|
||||
if (((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS) || (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_ALL_ITEMS)) && (item != ITEM_NONE)) {
|
||||
// Autosave for all items
|
||||
performSave = true;
|
||||
|
||||
} else if (((CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS) || (CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_MAJOR_ITEMS)) && (item != ITEM_NONE)) {
|
||||
} else if (((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS) || (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_MAJOR_ITEMS)) && (item != ITEM_NONE)) {
|
||||
// Autosave for major items
|
||||
if (itemEntry.modIndex == 0) {
|
||||
switch (item) {
|
||||
|
@ -328,7 +335,7 @@ void AutoSave(GetItemEntry itemEntry) {
|
|||
case ITEM_BOMBCHU:
|
||||
case ITEM_BOMBCHUS_5:
|
||||
case ITEM_BOMBCHUS_20:
|
||||
if (!CVarGetInteger("gBombchuDrops", 0)) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("BombchuDrops"), 0)) {
|
||||
performSave = true;
|
||||
}
|
||||
break;
|
||||
|
@ -339,9 +346,9 @@ void AutoSave(GetItemEntry itemEntry) {
|
|||
} else if (itemEntry.modIndex == 1 && item != RG_ICE_TRAP) {
|
||||
performSave = true;
|
||||
}
|
||||
} else if (CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS ||
|
||||
CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS ||
|
||||
CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION) {
|
||||
} else if (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS ||
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS ||
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION) {
|
||||
performSave = true;
|
||||
}
|
||||
if (performSave) {
|
||||
|
@ -359,13 +366,13 @@ void RegisterAutoSave() {
|
|||
|
||||
void RegisterRupeeDash() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||
if (!CVarGetInteger("gRupeeDash", 0)) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize Timer
|
||||
static uint16_t rupeeDashTimer = 0;
|
||||
uint16_t rdmTime = CVarGetInteger("gDashInterval", 5) * 20;
|
||||
uint16_t rdmTime = CVarGetInteger(CVAR_ENHANCEMENT("RupeeDashInterval"), 5) * 20;
|
||||
|
||||
// Did time change by DashInterval?
|
||||
if (rupeeDashTimer >= rdmTime) {
|
||||
|
@ -387,7 +394,7 @@ void RegisterShadowTag() {
|
|||
static uint16_t delayTimer = 60;
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||
if (!CVarGetInteger("gShadowTag", 0)) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) {
|
||||
return;
|
||||
}
|
||||
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene
|
||||
|
@ -418,7 +425,7 @@ static bool hasAffectedHealth = false;
|
|||
void UpdatePermanentHeartLossState() {
|
||||
if (!GameInteractor::IsSaveLoaded()) return;
|
||||
|
||||
if (!CVarGetInteger("gPermanentHeartLoss", 0) && hasAffectedHealth) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) {
|
||||
uint8_t heartContainers = gSaveContext.sohStats.heartContainers; // each worth 16 health
|
||||
uint8_t heartPieces = gSaveContext.sohStats.heartPieces; // each worth 4 health, but only in groups of 4
|
||||
uint8_t startingHealth = 16 * 3;
|
||||
|
@ -438,7 +445,7 @@ void RegisterPermanentHeartLoss() {
|
|||
});
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||
if (!CVarGetInteger("gPermanentHeartLoss", 0) || !GameInteractor::IsSaveLoaded()) return;
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded()) return;
|
||||
|
||||
if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) {
|
||||
gSaveContext.healthCapacity -= 16;
|
||||
|
@ -450,12 +457,12 @@ void RegisterPermanentHeartLoss() {
|
|||
|
||||
void RegisterDeleteFileOnDeath() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
if (!CVarGetInteger("gDeleteFileOnDeath", 0) || !GameInteractor::IsSaveLoaded() || &gPlayState->gameOverCtx == NULL || &gPlayState->pauseCtx == NULL) return;
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() || &gPlayState->gameOverCtx == NULL || &gPlayState->pauseCtx == NULL) return;
|
||||
|
||||
if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) {
|
||||
SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum);
|
||||
hasAffectedHealth = false;
|
||||
std::reinterpret_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset");
|
||||
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -471,7 +478,7 @@ using DayTimeGoldSkulltulasList = std::vector<DayTimeGoldSkulltulas>;
|
|||
|
||||
void RegisterDaytimeGoldSkultullas() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
|
||||
if (!CVarGetInteger("gNightGSAlwaysSpawn", 0)) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -516,75 +523,98 @@ void RegisterDaytimeGoldSkultullas() {
|
|||
});
|
||||
}
|
||||
|
||||
void RegisterHyperBosses() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
|
||||
// Run the update function a second time to make bosses move and act twice as fast.
|
||||
bool IsHyperBossesActive() {
|
||||
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
|
||||
(IS_BOSS_RUSH && gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
void UpdateHyperBossesState() {
|
||||
static uint32_t actorUpdateHookId = 0;
|
||||
if (actorUpdateHookId != 0) {
|
||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(actorUpdateHookId);
|
||||
actorUpdateHookId = 0;
|
||||
}
|
||||
|
||||
uint8_t isBossActor =
|
||||
actor->id == ACTOR_BOSS_GOMA || // Gohma
|
||||
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
|
||||
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
|
||||
actor->id == ACTOR_BOSS_VA || // Barinade
|
||||
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
|
||||
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
|
||||
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
|
||||
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
|
||||
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
|
||||
actor->id == ACTOR_BOSS_MO || // Morpha
|
||||
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
|
||||
actor->id == ACTOR_BOSS_TW || // Twinrova
|
||||
actor->id == ACTOR_BOSS_GANON || // Ganondorf
|
||||
actor->id == ACTOR_BOSS_GANON2; // Ganon
|
||||
if (IsHyperBossesActive()) {
|
||||
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
|
||||
// Run the update function a second time to make bosses move and act twice as fast.
|
||||
|
||||
uint8_t hyperBossesActive =
|
||||
CVarGetInteger("gHyperBosses", 0) ||
|
||||
(IS_BOSS_RUSH &&
|
||||
gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
|
||||
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
|
||||
if (hyperBossesActive && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
|
||||
// Barinade needs to be updated in sequence to avoid unintended behaviour.
|
||||
if (actor->id == ACTOR_BOSS_VA) {
|
||||
// params -1 is BOSSVA_BODY
|
||||
if (actor->params == -1) {
|
||||
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
|
||||
while (actorList != NULL) {
|
||||
GameInteractor::RawAction::UpdateActor(actorList);
|
||||
actorList = actorList->next;
|
||||
uint8_t isBossActor =
|
||||
actor->id == ACTOR_BOSS_GOMA || // Gohma
|
||||
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
|
||||
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
|
||||
actor->id == ACTOR_BOSS_VA || // Barinade
|
||||
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
|
||||
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
|
||||
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
|
||||
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
|
||||
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
|
||||
actor->id == ACTOR_BOSS_MO || // Morpha
|
||||
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
|
||||
actor->id == ACTOR_BOSS_TW || // Twinrova
|
||||
actor->id == ACTOR_BOSS_GANON || // Ganondorf
|
||||
actor->id == ACTOR_BOSS_GANON2; // Ganon
|
||||
|
||||
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
|
||||
if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
|
||||
// Barinade needs to be updated in sequence to avoid unintended behaviour.
|
||||
if (actor->id == ACTOR_BOSS_VA) {
|
||||
// params -1 is BOSSVA_BODY
|
||||
if (actor->params == -1) {
|
||||
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
|
||||
while (actorList != NULL) {
|
||||
GameInteractor::RawAction::UpdateActor(actorList);
|
||||
actorList = actorList->next;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GameInteractor::RawAction::UpdateActor(actor);
|
||||
}
|
||||
} else {
|
||||
GameInteractor::RawAction::UpdateActor(actor);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHyperBosses() {
|
||||
UpdateHyperBossesState();
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int16_t fileNum) {
|
||||
UpdateHyperBossesState();
|
||||
});
|
||||
}
|
||||
|
||||
void RegisterHyperEnemies() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
|
||||
// Run the update function a second time to make enemies and minibosses move and act twice as fast.
|
||||
void UpdateHyperEnemiesState() {
|
||||
static uint32_t actorUpdateHookId = 0;
|
||||
if (actorUpdateHookId != 0) {
|
||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(actorUpdateHookId);
|
||||
actorUpdateHookId = 0;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) {
|
||||
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
|
||||
// Run the update function a second time to make enemies and minibosses move and act twice as fast.
|
||||
|
||||
// Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies.
|
||||
bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2;
|
||||
bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2;
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
|
||||
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes.
|
||||
if (CVarGetInteger("gHyperEnemies", 0) && isEnemy && !isExcludedEnemy &&
|
||||
!Player_InBlockingCsMode(gPlayState, player)) {
|
||||
GameInteractor::RawAction::UpdateActor(actor);
|
||||
}
|
||||
});
|
||||
// Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies.
|
||||
bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2;
|
||||
bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2;
|
||||
|
||||
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes.
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0) && isEnemy && !isExcludedEnemy &&
|
||||
!Player_InBlockingCsMode(gPlayState, player)) {
|
||||
GameInteractor::RawAction::UpdateActor(actor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterBonkDamage() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerBonk>([]() {
|
||||
uint8_t bonkOption = CVarGetInteger("gBonkDamageMul", BONK_DAMAGE_NONE);
|
||||
uint8_t bonkOption = CVarGetInteger(CVAR_ENHANCEMENT("BonkDamageMult"), BONK_DAMAGE_NONE);
|
||||
if (bonkOption == BONK_DAMAGE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
@ -630,7 +660,7 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
|
|||
case SCENE_HYRULE_FIELD:
|
||||
case SCENE_KOKIRI_FOREST:
|
||||
case SCENE_HYRULE_CASTLE:
|
||||
CVarSetInteger("gZFightingMode", CVarGetInteger("gSceneSpecificDirtPathFix", ZFIGHT_FIX_DISABLED));
|
||||
CVarSetInteger("gZFightingMode", CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED));
|
||||
return;
|
||||
default:
|
||||
CVarClear("gZFightingMode");
|
||||
|
@ -647,7 +677,7 @@ void UpdateMirrorModeState(int32_t sceneNum) {
|
|||
static bool prevMirroredWorld = false;
|
||||
bool nextMirroredWorld = false;
|
||||
|
||||
int16_t mirroredMode = CVarGetInteger("gMirroredWorldMode", MIRRORED_WORLD_OFF);
|
||||
int16_t mirroredMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorldMode"), MIRRORED_WORLD_OFF);
|
||||
int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE && sceneNum != SCENE_THIEVES_HIDEOUT) ||
|
||||
(sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) ||
|
||||
(sceneNum == SCENE_GANON_BOSS);
|
||||
|
@ -687,6 +717,62 @@ void RegisterMirrorModeHandler() {
|
|||
});
|
||||
}
|
||||
|
||||
void UpdatePatchHand() {
|
||||
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && LINK_IS_CHILD) {
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList());
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85, gsSPEndDisplayList());
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList());
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105, gsSPEndDisplayList());
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList());
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77, gsSPEndDisplayList());
|
||||
|
||||
} else {
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2");
|
||||
}
|
||||
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && LINK_IS_ADULT) {
|
||||
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
|
||||
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
|
||||
} else {
|
||||
ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang");
|
||||
ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield");
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterPatchHandHandler() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
|
||||
UpdatePatchHand();
|
||||
});
|
||||
}
|
||||
|
||||
void RegisterResetNaviTimer() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("ResetNaviTimer"), 0)) {
|
||||
gSaveContext.naviTimer = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
f32 triforcePieceScale;
|
||||
|
||||
void RegisterTriforceHunt() {
|
||||
|
@ -935,16 +1021,16 @@ typedef enum {
|
|||
} AltTrapType;
|
||||
|
||||
const char* altTrapTypeCvars[] = {
|
||||
"gAddTraps.Ice",
|
||||
"gAddTraps.Burn",
|
||||
"gAddTraps.Shock",
|
||||
"gAddTraps.Knock",
|
||||
"gAddTraps.Speed",
|
||||
"gAddTraps.Bomb",
|
||||
"gAddTraps.Void",
|
||||
"gAddTraps.Ammo",
|
||||
"gAddTraps.Kill",
|
||||
"gAddTraps.Tele"
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Ice"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Burn"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Shock"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Speed"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Void"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Kill"),
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Teleport")
|
||||
};
|
||||
|
||||
std::vector<AltTrapType> getEnabledAddTraps () {
|
||||
|
@ -966,7 +1052,7 @@ void RegisterAltTrapTypes() {
|
|||
static int eventTimer = -1;
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry itemEntry) {
|
||||
if (!CVarGetInteger("gAddTraps.enabled", 0) || itemEntry.modIndex != MOD_RANDOMIZER || itemEntry.getItemId != RG_ICE_TRAP) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) || itemEntry.modIndex != MOD_RANDOMIZER || itemEntry.getItemId != RG_ICE_TRAP) {
|
||||
return;
|
||||
}
|
||||
roll = RandomElement(getEnabledAddTraps());
|
||||
|
@ -1090,6 +1176,29 @@ void RegisterRandomizerSheikSpawn() {
|
|||
});
|
||||
}
|
||||
|
||||
void UpdateHurtContainerModeState(bool newState) {
|
||||
static bool hurtEnabled = false;
|
||||
if (hurtEnabled == newState) {
|
||||
return;
|
||||
}
|
||||
|
||||
hurtEnabled = newState;
|
||||
uint16_t getHeartPieces = gSaveContext.sohStats.heartPieces / 4;
|
||||
uint16_t getHeartContainers = gSaveContext.sohStats.heartContainers;
|
||||
|
||||
if (hurtEnabled) {
|
||||
gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16);
|
||||
} else {
|
||||
gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHurtContainerModeHandler() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
|
||||
UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0));
|
||||
});
|
||||
}
|
||||
|
||||
void RegisterRandomizedEnemySizes() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
|
||||
// Randomized Enemy Sizes
|
||||
|
@ -1105,7 +1214,7 @@ void RegisterRandomizedEnemySizes() {
|
|||
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
|
||||
|
||||
// Only apply to enemies and bosses.
|
||||
if (!CVarGetInteger("gRandomizedEnemySizes", 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1128,7 +1237,7 @@ void RegisterRandomizedEnemySizes() {
|
|||
|
||||
Actor_SetScale(actor, actor->scale.z * randomScale);
|
||||
|
||||
if (CVarGetInteger("gEnemySizeScalesHealth", 0) && (actor->category == ACTORCAT_ENEMY)) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("EnemySizeScalesHealth"), 0) && (actor->category == ACTORCAT_ENEMY)) {
|
||||
// Scale the health based on a smaller factor than randomScale
|
||||
float healthScalingFactor = 0.8f; // Adjust this factor as needed
|
||||
float scaledHealth = actor->colChkInfo.health * (randomScale * healthScalingFactor);
|
||||
|
@ -1141,10 +1250,38 @@ void RegisterRandomizedEnemySizes() {
|
|||
});
|
||||
}
|
||||
|
||||
void RegisterOpenAllHours() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR)) {
|
||||
switch (actor->params) {
|
||||
case 4753: // Night Market Bazaar
|
||||
case 1678: // Night Potion Shop
|
||||
case 2689: // Day Bombchu Shop
|
||||
case 2703: // Night Slingshot Game
|
||||
case 653: // Day Chest Game
|
||||
case 6801: // Night Kak Bazaar
|
||||
case 7822: // Night Kak Potion Shop
|
||||
case 4751: // Night Kak Archery Game
|
||||
case 3728: // Night Mask Shop
|
||||
{
|
||||
actor->params = (actor->params & 0xFC00) | (DOOR_SCENEEXIT << 7) | 0x3F;
|
||||
EnDoor* enDoor = static_cast<EnDoor*>(refActor);
|
||||
EnDoor_SetupType(enDoor, gPlayState);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PatchToTMedallions() {
|
||||
// TODO: Refactor the DemoEffect_UpdateJewelAdult and DemoEffect_UpdateJewelChild from z_demo_effect
|
||||
// effects to take effect in there
|
||||
if (CVarGetInteger("gToTMedallionsColors", 0)) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0)) {
|
||||
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale", 7, gsSPGrayscale(true));
|
||||
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true));
|
||||
|
||||
|
@ -1210,19 +1347,53 @@ void PatchToTMedallions() {
|
|||
|
||||
void RegisterToTMedallions() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry _unused) {
|
||||
if (!CVarGetInteger("gToTMedallionsColors", 0) || !gPlayState || gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState || gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) {
|
||||
return;
|
||||
}
|
||||
PatchToTMedallions();
|
||||
});
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
|
||||
if (!CVarGetInteger("gToTMedallionsColors", 0) || sceneNum != SCENE_TEMPLE_OF_TIME) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || sceneNum != SCENE_TEMPLE_OF_TIME) {
|
||||
return;
|
||||
}
|
||||
PatchToTMedallions();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void RegisterFloorSwitchesHook() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
if (actor->id != ACTOR_OBJ_SWITCH || !CVarGetInteger(CVAR_ENHANCEMENT("FixFloorSwitches"), 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ObjSwitch* switchActor = reinterpret_cast<ObjSwitch*>(actor);
|
||||
s32 type = (switchActor->dyna.actor.params & 7);
|
||||
|
||||
if (switchActor->dyna.actor.params == 0x1200 || switchActor->dyna.actor.params == 0x3A00) {
|
||||
switchActor->dyna.actor.world.pos.y -= 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void RegisterPauseMenuHooks() {
|
||||
static bool pauseWarpHooksRegistered = false;
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([&]() {
|
||||
if (!GameInteractor::IsSaveLoaded() || !CVarGetInteger(CVAR_ENHANCEMENT("PauseWarp"), 0)) {
|
||||
pauseWarpHooksRegistered = false;
|
||||
return;
|
||||
}
|
||||
if (!pauseWarpHooksRegistered) {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>([]() {PauseWarp_HandleSelection();});
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
PauseWarp_Execute();
|
||||
});
|
||||
pauseWarpHooksRegistered = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void InitMods() {
|
||||
RegisterTTS();
|
||||
RegisterInfiniteMoney();
|
||||
|
@ -1244,16 +1415,22 @@ void InitMods() {
|
|||
RegisterPermanentHeartLoss();
|
||||
RegisterDeleteFileOnDeath();
|
||||
RegisterHyperBosses();
|
||||
RegisterHyperEnemies();
|
||||
UpdateHyperEnemiesState();
|
||||
RegisterBonkDamage();
|
||||
RegisterMenuPathFix();
|
||||
RegisterMirrorModeHandler();
|
||||
RegisterResetNaviTimer();
|
||||
RegisterTriforceHunt();
|
||||
RegisterGrantGanonsBossKey();
|
||||
RegisterEnemyDefeatCounts();
|
||||
RegisterAltTrapTypes();
|
||||
RegisterRandomizerSheikSpawn();
|
||||
RegisterRandomizedEnemySizes();
|
||||
RegisterOpenAllHours();
|
||||
RegisterToTMedallions();
|
||||
NameTag_RegisterHooks();
|
||||
RegisterFloorSwitchesHook();
|
||||
RegisterPatchHandHandler();
|
||||
RegisterHurtContainerModeHandler();
|
||||
RegisterPauseMenuHooks();
|
||||
}
|
||||
|
|
|
@ -9,9 +9,13 @@ extern "C" {
|
|||
|
||||
void UpdateDirtPathFixState(int32_t sceneNum);
|
||||
void UpdateMirrorModeState(int32_t sceneNum);
|
||||
void UpdateHurtContainerModeState(bool newState);
|
||||
void PatchToTMedallions();
|
||||
void UpdatePermanentHeartLossState();
|
||||
void UpdateHyperEnemiesState();
|
||||
void UpdateHyperBossesState();
|
||||
void InitMods();
|
||||
void UpdatePatchHand();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "soh/frame_interpolation.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
|
||||
extern "C" {
|
||||
#include "z64.h"
|
||||
|
@ -70,11 +71,11 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
|
|||
Color_RGBA8 textboxColor = { 0, 0, 0, 80};
|
||||
Color_RGBA8 textColor = { 255, 255, 255, 255 };
|
||||
|
||||
if (CVarGetInteger("gCosmetics.Hud_NameTagActorBackground.Changed", 0)) {
|
||||
textboxColor = CVarGetColor("gCosmetics.Hud_NameTagActorBackground.Value", textboxColor);
|
||||
if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorBackground.Changed"), 0)) {
|
||||
textboxColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorBackground.Value"), textboxColor);
|
||||
}
|
||||
if (CVarGetInteger("gCosmetics.Hud_NameTagActorText.Changed", 0)) {
|
||||
textColor = CVarGetColor("gCosmetics.Hud_NameTagActorText.Value", textColor);
|
||||
if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorText.Changed"), 0)) {
|
||||
textColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorText.Value"), textColor);
|
||||
}
|
||||
|
||||
FrameInterpolation_RecordOpenChild(nameTag->actor, 10);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
#include "custom-message/CustomMessageTypes.h"
|
||||
#include "global.h"
|
||||
#include "z64.h"
|
||||
#include "game-interactor/GameInteractor.h"
|
||||
|
||||
static const int songMessageMap[] = {
|
||||
TEXT_WARP_MINUET_OF_FOREST,
|
||||
TEXT_WARP_BOLERO_OF_FIRE,
|
||||
TEXT_WARP_SERENADE_OF_WATER,
|
||||
TEXT_WARP_REQUIEM_OF_SPIRIT,
|
||||
TEXT_WARP_NOCTURNE_OF_SHADOW,
|
||||
TEXT_WARP_PRELUDE_OF_LIGHT
|
||||
};
|
||||
|
||||
static const int ocarinaSongMap[] = {
|
||||
OCARINA_SONG_MINUET,
|
||||
OCARINA_SONG_BOLERO,
|
||||
OCARINA_SONG_SERENADE,
|
||||
OCARINA_SONG_REQUIEM,
|
||||
OCARINA_SONG_NOCTURNE,
|
||||
OCARINA_SONG_PRELUDE
|
||||
};
|
||||
|
||||
static const int entranceIndexMap[] = {
|
||||
ENTR_SACRED_FOREST_MEADOW_2, // Minuet
|
||||
ENTR_DEATH_MOUNTAIN_CRATER_4, // Bolero
|
||||
ENTR_LAKE_HYLIA_8, // Serenade
|
||||
ENTR_DESERT_COLOSSUS_5, // Requiem
|
||||
ENTR_GRAVEYARD_7, // Nocturne
|
||||
ENTR_TEMPLE_OF_TIME_7 // Prelude
|
||||
};
|
||||
|
||||
static const int songAudioMap[] = {
|
||||
NA_BGM_OCA_MINUET,
|
||||
NA_BGM_OCA_BOLERO,
|
||||
NA_BGM_OCA_SERENADE,
|
||||
NA_BGM_OCA_REQUIEM,
|
||||
NA_BGM_OCA_NOCTURNE,
|
||||
NA_BGM_OCA_LIGHT
|
||||
};
|
||||
|
||||
static bool isWarpActive = false;
|
||||
|
||||
void PauseWarp_Execute() {
|
||||
if (!isWarpActive || gPlayState->msgCtx.msgMode != MSGMODE_NONE) {
|
||||
return;
|
||||
}
|
||||
isWarpActive = false;
|
||||
GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
|
||||
if (gPlayState->msgCtx.choiceIndex != 0) {
|
||||
return;
|
||||
}
|
||||
if (IS_RANDO) {
|
||||
Entrance_SetWarpSongEntrance();
|
||||
return;
|
||||
}
|
||||
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||
gPlayState->transitionType = TRANS_TYPE_FADE_WHITE_FAST;
|
||||
for (int i = 0; i < ARRAY_COUNT(ocarinaSongMap); i++) {
|
||||
if (gPlayState->msgCtx.lastPlayedSong == ocarinaSongMap[i]) {
|
||||
gPlayState->nextEntranceIndex = entranceIndexMap[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
gPlayState->transitionTrigger = TRANS_TRIGGER_OFF;
|
||||
}
|
||||
|
||||
void ActivateWarp(PauseContext* pauseCtx, int song) {
|
||||
Audio_OcaSetInstrument(0);
|
||||
Interface_SetDoAction(gPlayState, DO_ACTION_NONE);
|
||||
pauseCtx->state = 0x12;
|
||||
WREG(2) = -6240;
|
||||
func_800F64E0(0);
|
||||
pauseCtx->unk_1E4 = 0;
|
||||
int idx = song - QUEST_SONG_MINUET;
|
||||
gPlayState->msgCtx.lastPlayedSong = ocarinaSongMap[idx];
|
||||
Audio_SetSoundBanksMute(0x20);
|
||||
Audio_PlayFanfare(songAudioMap[idx]);
|
||||
Message_StartTextbox(gPlayState, songMessageMap[idx], NULL);
|
||||
GET_PLAYER(gPlayState)->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
|
||||
isWarpActive = true;
|
||||
}
|
||||
|
||||
void PauseWarp_HandleSelection() {
|
||||
if (gSaveContext.inventory.items[SLOT_OCARINA] != ITEM_NONE) {
|
||||
int aButtonPressed = CHECK_BTN_ALL(gPlayState->state.input->press.button, BTN_A);
|
||||
int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST];
|
||||
if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE &&
|
||||
gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) {
|
||||
ActivateWarp(&gPlayState->pauseCtx, song);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,14 @@ void clearCvars(std::vector<const char*> cvarsToClear) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string FormatLocations(std::vector<RandomizerCheck> locs) {
|
||||
std::string locString = "";
|
||||
for (auto loc: locs) {
|
||||
locString += std::to_string(loc) + ",";
|
||||
}
|
||||
return locString;
|
||||
}
|
||||
|
||||
void applyPreset(std::vector<PresetEntry> entries) {
|
||||
for(auto& [cvar, type, value] : entries) {
|
||||
switch (type) {
|
||||
|
@ -24,6 +32,9 @@ void applyPreset(std::vector<PresetEntry> entries) {
|
|||
case PRESET_ENTRY_TYPE_STRING:
|
||||
CVarSetString(cvar, std::get<const char*>(value));
|
||||
break;
|
||||
case PRESET_ENTRY_TYPE_CPP_STRING:
|
||||
CVarSetString(cvar, std::get<std::string>(value).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +70,7 @@ void DrawPresetSelector(PresetType presetTypeId) {
|
|||
if (selectedPresetId != 0) {
|
||||
applyPreset(selectedPresetDef.entries);
|
||||
}
|
||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
}
|
||||
ImGui::PopStyleVar(1);
|
||||
}
|
||||
|
|