Merge remote-tracking branch 'upstream/develop' into NoMS

This commit is contained in:
Patrick12115 2024-02-03 15:25:10 -05:00
commit e5b4e2eb3c
67 changed files with 1641 additions and 731 deletions

View File

@ -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 ninja-build

View File

@ -13,22 +13,37 @@ jobs:
with: with:
submodules: true submodules: true
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.11
with: 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 - name: Install dependencies
if: ${{ !vars.LINUX_RUNNER }} if: ${{ !vars.LINUX_RUNNER }}
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) 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 - name: Install latest SDL
if: ${{ !vars.LINUX_RUNNER }} if: ${{ !vars.LINUX_RUNNER }}
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz if [ ! -d "SDL2-2.28.5" ]; then
tar -xzf SDL2-2.26.1.tar.gz wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz
cd SDL2-2.26.1 tar -xzf SDL2-2.28.5.tar.gz
./configure fi
cd SDL2-2.28.5
./configure --enable-hidapi-libusb
make -j 10 make -j 10
sudo make install sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ 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" 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 --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
cmake --build build-cmake --config Release --target GenerateSohOtr cmake --build build-cmake --config Release --target GenerateSohOtr
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: soh.otr name: soh.otr
path: soh.otr path: soh.otr
@ -50,9 +65,12 @@ jobs:
with: with:
submodules: true submodules: true
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.11
with: 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 - name: Install gtar wrapper
if: ${{ !vars.MAC_RUNNER }} if: ${{ !vars.MAC_RUNNER }}
run: | run: |
@ -85,7 +103,7 @@ jobs:
sudo port install $(cat .github/workflows/macports-deps.txt) sudo port install $(cat .github/workflows/macports-deps.txt)
brew install ninja brew install ninja
- name: Download soh.otr - name: Download soh.otr
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: soh.otr name: soh.otr
- name: Build SoH - name: Build SoH
@ -99,7 +117,7 @@ jobs:
mv _packages/*.dmg SoH.dmg mv _packages/*.dmg SoH.dmg
mv README.md readme.txt mv README.md readme.txt
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: soh-mac name: soh-mac
path: | path: |
@ -128,17 +146,32 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) sudo apt-get install -y $(cat .github/workflows/apt-deps.txt)
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.11
with: 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 - name: Install latest SDL
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz if [ ! -d "SDL2-2.28.5" ]; then
tar -xzf SDL2-2.26.1.tar.gz wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz
cd SDL2-2.26.1 tar -xzf SDL2-2.28.5.tar.gz
./configure fi
cd SDL2-2.28.5
./configure --enable-hidapi-libusb
make -j 10 make -j 10
sudo make install sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
@ -146,15 +179,17 @@ jobs:
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" 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 if [ ! -d "SDL2_net-2.2.0" ]; then
tar -xzf SDL2_net-2.2.0.tar.gz 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 cd SDL2_net-2.2.0
./configure ./configure
make -j 10 make -j 10
sudo make install sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Download soh.otr - name: Download soh.otr
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: soh.otr name: soh.otr
- name: Build SoH - name: Build SoH
@ -170,7 +205,7 @@ jobs:
CC: gcc-${{ matrix.gcc }} CC: gcc-${{ matrix.gcc }}
CXX: g++-${{ matrix.gcc }} CXX: g++-${{ matrix.gcc }}
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: soh-linux-${{ matrix.archive-suffix }} name: soh-linux-${{ matrix.archive-suffix }}
path: | path: |
@ -180,7 +215,7 @@ jobs:
needs: generate-soh-otr needs: generate-soh-otr
runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
container: container:
image: devkitpro/devkita64:latest image: devkitpro/devkita64:20240120
steps: steps:
- name: Install dependencies - name: Install dependencies
run: | run: |
@ -193,9 +228,12 @@ jobs:
with: with:
submodules: true submodules: true
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.11
with: 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 - name: Build SoH
run: | 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 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 +242,11 @@ jobs:
mv build-switch/soh/*.nro soh.nro mv build-switch/soh/*.nro soh.nro
mv README.md readme.txt mv README.md readme.txt
- name: Download soh.otr - name: Download soh.otr
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: soh.otr name: soh.otr
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: soh-switch name: soh-switch
path: | path: |
@ -230,9 +268,12 @@ jobs:
with: with:
submodules: true submodules: true
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.11
with: 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 - name: Build SoH
run: | 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 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 +286,11 @@ jobs:
DEVKITPRO: /opt/devkitpro DEVKITPRO: /opt/devkitpro
DEVKITPPC: /opt/devkitpro/devkitPPC DEVKITPPC: /opt/devkitpro/devkitPPC
- name: Download soh.otr - name: Download soh.otr
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: soh.otr name: soh.otr
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: soh-wiiu name: soh-wiiu
path: | path: |
@ -270,15 +311,25 @@ jobs:
with: with:
submodules: true submodules: true
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.11
with: with:
key: ${{ runner.os }}-ccache variant: sccache
- name: vcpkg max-size: "1G"
uses: johnwason/vcpkg-action@v5 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: with:
pkgs: zlib bzip2 libpng sdl2 sdl2-net glew glfw3 save-always: true
token: ${{ github.token }} key: ${{ runner.os }}-build-${{ github.ref }}-${{ github.sha }}
triplet: 'x64-windows-static' restore-keys: |
${{ runner.os }}-build-${{ github.ref }}
${{ runner.os }}-build-
path: |
build-windows
vcpkg
- name: Configure Developer Command Prompt - name: Configure Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1 uses: ilammy/msvc-dev-cmd@v1
- name: Build SoH - name: Build SoH
@ -286,7 +337,7 @@ jobs:
VCPKG_ROOT: ${{github.workspace}}/vcpkg VCPKG_ROOT: ${{github.workspace}}/vcpkg
run: | run: |
set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH" 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 cmake --build build-windows --config Release --parallel 10
mkdir soh-windows mkdir soh-windows
@ -299,12 +350,12 @@ jobs:
mv ./build-windows/gamecontrollerdb.txt ./soh-windows/gamecontrollerdb.txt mv ./build-windows/gamecontrollerdb.txt ./soh-windows/gamecontrollerdb.txt
mv ./x64/Release/assets ./soh-windows mv ./x64/Release/assets ./soh-windows
- name: Download soh.otr - name: Download soh.otr
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: soh.otr name: soh.otr
path: soh-windows path: soh-windows
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: soh-windows name: soh-windows
path: soh-windows path: soh-windows

View File

@ -8,5 +8,9 @@ if(MSVC)
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL") 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_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() endif()

View File

@ -14,13 +14,17 @@ add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/utf-8>) add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/utf-8>)
if (CMAKE_SYSTEM_NAME STREQUAL "Windows") if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
include(CMake/automate-vcpkg.cmake) include(CMake/automate-vcpkg.cmake)
set(VCPKG_TRIPLET x64-windows-static) set(VCPKG_TRIPLET x64-windows-static)
set(VCPKG_TARGET_TRIPLET x64-windows-static) set(VCPKG_TARGET_TRIPLET x64-windows-static)
vcpkg_bootstrap() vcpkg_bootstrap()
vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3) vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3)
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache")
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
endif()
endif() endif()
################################################################################ ################################################################################

@ -1 +1 @@
Subproject commit 04b85b95fab07a394b62dcd28a502a3040f08e0c Subproject commit 44adc47b4da529e72d968b14cab94aefd8260f22

@ -1 +1 @@
Subproject commit 15d57d806e39d7f19783e26acc1a062d402169c7 Subproject commit 0833afad66e96d2ec4bbc410186d7247dc243ee2

View File

@ -8,5 +8,9 @@ if(MSVC)
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL") 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_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() endif()

View File

@ -328,7 +328,7 @@ endif()
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
Boost 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 URL_HASH SHA256=205666dea9f6a7cfed87c7a6dfbeb52a2c1b9de55712c9c1a87735d7181452b6
SOURCE_SUBDIR "null" # Set to a nonexistent directory so boost is not built (we don't need to build it) 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 DOWNLOAD_EXTRACT_TIMESTAMP false # supress timestamp warning, not needed since the url wont change

View File

@ -4,4 +4,4 @@
*.cfg *.cfg
*.vtx.inc *.vtx.inc
*.dlist.inc *.dlist.inc
*.txt !*.png

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

View File

@ -744,7 +744,6 @@ typedef struct {
/* 0x0134 */ char** doActionSegment; /* 0x0134 */ char** doActionSegment;
/* 0x0138 */ u8* iconItemSegment; /* 0x0138 */ u8* iconItemSegment;
/* 0x013C */ char** mapSegment; /* 0x013C */ char** mapSegment;
char** mapSegmentName;
/* 0x0140 */ u8 mapPalette[32]; /* 0x0140 */ u8 mapPalette[32];
/* 0x0160 */ DmaRequest dmaRequest_160; /* 0x0160 */ DmaRequest dmaRequest_160;
/* 0x0180 */ DmaRequest dmaRequest_180; /* 0x0180 */ DmaRequest dmaRequest_180;
@ -815,6 +814,10 @@ typedef struct {
/* 0x026C */ u8 dinsNayrus; // "m_magic"; din's fire and nayru's love /* 0x026C */ u8 dinsNayrus; // "m_magic"; din's fire and nayru's love
/* 0x026D */ u8 all; // "another"; enables all item restrictions /* 0x026D */ u8 all; // "another"; enables all item restrictions
} 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 } InterfaceContext; // size = 0x270
typedef struct { typedef struct {

View File

@ -12,6 +12,7 @@
#include <Utils/StringHelper.h> #include <Utils/StringHelper.h>
#include "../../UIWidgets.hpp" #include "../../UIWidgets.hpp"
#include "AudioCollection.h" #include "AudioCollection.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
Vec3f pos = { 0.0f, 0.0f, 0.0f }; Vec3f pos = { 0.0f, 0.0f, 0.0f };
f32 freqScale = 1.0f; f32 freqScale = 1.0f;
@ -79,6 +80,11 @@ void UpdateCurrentBGM(u16 seqKey, SeqType seqType) {
void RandomizeGroup(SeqType type) { void RandomizeGroup(SeqType type) {
std::vector<u16> values; 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 // use a while loop to add duplicates if we don't have enough included sequences
while (values.size() < AuthenticCountBySequenceType(type)) { while (values.size() < AuthenticCountBySequenceType(type)) {
for (const auto& seqData : AudioCollection::Instance->GetIncludedSequences()) { for (const auto& seqData : AudioCollection::Instance->GetIncludedSequences()) {
@ -123,6 +129,34 @@ 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) { void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequenceType) {
const std::string cvarKey = AudioCollection::Instance->GetCvarKey(sfxKey); const std::string cvarKey = AudioCollection::Instance->GetCvarKey(sfxKey);
const std::string hiddenKey = "##" + cvarKey; const std::string hiddenKey = "##" + cvarKey;
@ -163,6 +197,8 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
const std::string hiddenTabId = "##" + tabId; const std::string hiddenTabId = "##" + tabId;
const std::string resetAllButton = "Reset All" + hiddenTabId; const std::string resetAllButton = "Reset All" + hiddenTabId;
const std::string randomizeAllButton = "Randomize 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())) { if (ImGui::Button(resetAllButton.c_str())) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
@ -184,6 +220,28 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) {
ReplayCurrentBGM(); 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);
LUS::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);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) {
ReplayCurrentBGM();
}
}
ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit); ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
@ -350,6 +408,19 @@ void DrawTypeChip(SeqType type) {
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
void AudioEditorRegisterOnSceneInitHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
if (CVarGetInteger("gAudioEditor.RandomizeAllOnNewScene", 0)) {
AudioEditor_RandomizeAll();
}
});
}
void AudioEditor::InitElement() {
AudioEditorRegisterOnSceneInitHook();
}
void AudioEditor::DrawElement() { void AudioEditor::DrawElement() {
AudioCollection::Instance->InitializeShufflePool(); AudioCollection::Instance->InitializeShufflePool();
@ -359,6 +430,28 @@ void AudioEditor::DrawElement() {
return; 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::BeginTabBar("SfxContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
if (ImGui::BeginTabItem("Background Music")) { if (ImGui::BeginTabItem("Background Music")) {
Draw_SfxTab("backgroundMusic", SEQ_BGM_WORLD); Draw_SfxTab("backgroundMusic", SEQ_BGM_WORLD);
@ -431,6 +524,10 @@ void AudioEditor::DrawElement() {
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
} }
ImGui::NewLine();
UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", "gAudioEditor.RandomizeAllOnNewScene");
UIWidgets::Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene.");
ImGui::NewLine(); ImGui::NewLine();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
UIWidgets::PaddedSeparator(); UIWidgets::PaddedSeparator();
@ -625,3 +722,19 @@ void AudioEditor_ResetAll() {
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
ReplayCurrentBGM(); ReplayCurrentBGM();
} }
void AudioEditor_LockAll() {
for (auto type : allTypes) {
LockGroup(AudioCollection::Instance->GetAllSequences(), type);
}
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
void AudioEditor_UnlockAll() {
for (auto type : allTypes) {
UnlockGroup(AudioCollection::Instance->GetAllSequences(), type);
}
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}

View File

@ -14,13 +14,15 @@ class AudioEditor : public LUS::GuiWindow {
using LUS::GuiWindow::GuiWindow; using LUS::GuiWindow::GuiWindow;
void DrawElement() override; void DrawElement() override;
void InitElement() override {}; void InitElement() override;
void UpdateElement() override {}; void UpdateElement() override {};
~AudioEditor() {}; ~AudioEditor() {};
}; };
void AudioEditor_RandomizeAll(); void AudioEditor_RandomizeAll();
void AudioEditor_ResetAll(); void AudioEditor_ResetAll();
void AudioEditor_LockAll();
void AudioEditor_UnlockAll();
extern "C" { extern "C" {
#endif #endif

View File

@ -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);
}
}

View File

@ -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

View File

@ -22,6 +22,22 @@ void SohInputEditorWindow::InitElement() {
mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT }; mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT };
mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
mModifierButtonsBitmasks = { BTN_MODIFIER1, BTN_MODIFIER2 }; mModifierButtonsBitmasks = { BTN_MODIFIER1, BTN_MODIFIER2 };
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");
} }
#define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929 #define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929
@ -1017,14 +1033,6 @@ void SohInputEditorWindow::DrawAddLEDMappingButton(uint8_t port) {
} }
} }
void SohInputEditorWindow::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() - SCALE_IMGUI_SIZE(22));
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - SCALE_IMGUI_SIZE(15));
ImGui::SmallButton("?");
UIWidgets::Tooltip(helptext.c_str());
}
void SohInputEditorWindow::DrawLEDSection(uint8_t port) { void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
for (auto [id, mapping] : for (auto [id, mapping] :
LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->GetAllLEDMappings()) { LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->GetAllLEDMappings()) {
@ -1063,11 +1071,11 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
}; };
UIWidgets::PaddedText("Source"); UIWidgets::PaddedText("Source");
UIWidgets::EnhancementCombobox("gLedColorSource", ledSources, LED_SOURCE_TUNIC_ORIGINAL); UIWidgets::EnhancementCombobox("gLedColorSource", ledSources, LED_SOURCE_TUNIC_ORIGINAL);
DrawHelpIcon("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when " UIWidgets::Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when "
"health < 40%. Green otherwise.\n\n" "health < 40%. Green otherwise.\n\n"
"Tunics: colors will mirror currently equipped tunic, whether original or the current " "Tunics: colors will mirror currently equipped tunic, whether original or the current "
"values in Cosmetics Editor.\n\n" "values in Cosmetics Editor.\n\n"
"Custom: single, solid color"); "Custom: single, solid color");
if (CVarGetInteger("gLedColorSource", 1) == LED_SOURCE_CUSTOM) { if (CVarGetInteger("gLedColorSource", 1) == LED_SOURCE_CUSTOM) {
UIWidgets::Spacer(3); UIWidgets::Spacer(3);
auto port1Color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 }); auto port1Color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 });
@ -1087,12 +1095,12 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
} }
UIWidgets::PaddedEnhancementSliderFloat("Brightness: %.1f %%", "##LED_Brightness", "gLedBrightness", 0.0f, UIWidgets::PaddedEnhancementSliderFloat("Brightness: %.1f %%", "##LED_Brightness", "gLedBrightness", 0.0f,
1.0f, "", 1.0f, true, true); 1.0f, "", 1.0f, true, true);
DrawHelpIcon("Sets the brightness of controller LEDs. 0% brightness = LEDs off."); UIWidgets::Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off.");
UIWidgets::PaddedEnhancementCheckbox( UIWidgets::PaddedEnhancementCheckbox(
"Critical Health Override", "gLedCriticalOverride", true, true, "Critical Health Override", "gLedCriticalOverride", true, true,
CVarGetInteger("gLedColorSource", LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH, CVarGetInteger("gLedColorSource", LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH,
"Override redundant for health source.", UIWidgets::CheckboxGraphics::Cross, true); "Override redundant for health source.", UIWidgets::CheckboxGraphics::Cross, true);
DrawHelpIcon("Shows red color when health is critical, otherwise displays according to color source."); UIWidgets::Tooltip("Shows red color when health is critical, otherwise displays according to color source.");
} }
ImGui::TreePop(); ImGui::TreePop();
} }
@ -1430,6 +1438,273 @@ void SohInputEditorWindow::DrawLEDDeviceIcons(uint8_t portIndex) {
} }
} }
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);
}
}
typedef uint32_t N64ButtonMask;
void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) {
buttons.push_back(std::make_pair(mask, name));
buttonNames[mask] = std::prev(buttons.end());
}
// 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};
// Draw a button mapping setting consisting of a padded label and button dropdown.
// excludedButtons indicates which buttons are unavailable to choose from.
void SohInputEditorWindow::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 SohInputEditorWindow::DrawOcarinaControlPanel() {
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);
LUS::GuiWindow::BeginGroupPanel("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();
LUS::GuiWindow::EndGroupPanel(0);
TableHelper::NextCol();
LUS::GuiWindow::BeginGroupPanel("Modifiers", ImGui::GetContentRegionAvail());
labelWidth = ImGui::CalcTextSize(ocarinaSongDisable.label).x + 10;
DrawMapping(ocarinaSongDisable, labelWidth, disableMask);
DrawMapping(ocarinaSharp, labelWidth, disableMask);
DrawMapping(ocarinaFlat, labelWidth, disableMask);
LUS::GuiWindow::EndGroupPanel(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);
}
LUS::GuiWindow::BeginGroupPanel("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();
}
LUS::GuiWindow::EndGroupPanel(0);
ImGui::EndTable();
}
void SohInputEditorWindow::DrawCameraControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
LUS::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming");
UIWidgets::Tooltip("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");
UIWidgets::Tooltip("Changes the left stick to move the player while in first person mode");
}
UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", "gInvertAimingXAxis");
UIWidgets::Tooltip("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);
UIWidgets::Tooltip("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);
UIWidgets::Tooltip("Inverts the Shield Aiming Y Axis");
UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", "gInvertShieldAimingXAxis");
UIWidgets::Tooltip("Inverts the Shield Aiming X Axis");
UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", "gInvertZAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming");
UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", "gDisableAutoCenterViewFirstPerson");
UIWidgets::Tooltip("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);
LUS::GuiWindow::EndGroupPanel(0);
UIWidgets::Spacer(0);
cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
LUS::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera");
UIWidgets::Tooltip("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");
UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free camera");
UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("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);
LUS::GuiWindow::EndGroupPanel(0);
}
void SohInputEditorWindow::DrawDpadControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
LUS::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause");
UIWidgets::Tooltip("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\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");
UIWidgets::Tooltip("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");
UIWidgets::Tooltip("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");
LUS::GuiWindow::EndGroupPanel(0);
}
void SohInputEditorWindow::DrawMiscControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
LUS::GuiWindow::BeginGroupPanel("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);
UIWidgets::Tooltip("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 speed modifiers", "gEnableWalkModify", true, false);
UIWidgets::Tooltip("Hold the assigned button to change the maximum walking or swimming speed");
if (CVarGetInteger("gEnableWalkModify", 0)) {
UIWidgets::Spacer(5);
LUS::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false);
LUS::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false);
UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
LUS::GuiWindow::EndGroupPanel(0);
LUS::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1", "gSwimModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2", "gSwimModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
LUS::GuiWindow::EndGroupPanel(0);
LUS::GuiWindow::EndGroupPanel(0);
}
ImGui::EndDisabled();
UIWidgets::Spacer(0);
UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL");
UIWidgets::Tooltip("Speak to Navi with L but enter first-person camera with C-Up");
LUS::GuiWindow::EndGroupPanel(0);
}
void SohInputEditorWindow::DrawLinkTab() { void SohInputEditorWindow::DrawLinkTab() {
uint8_t portIndex = 0; uint8_t portIndex = 0;
if (ImGui::BeginTabItem(StringHelper::Sprintf("Link (P1)###port%d", portIndex).c_str())) { if (ImGui::BeginTabItem(StringHelper::Sprintf("Link (P1)###port%d", portIndex).c_str())) {
@ -1516,6 +1791,46 @@ void SohInputEditorWindow::DrawLinkTab() {
DrawButtonDeviceIcons(portIndex, mModifierButtonsBitmasks); DrawButtonDeviceIcons(portIndex, mModifierButtonsBitmasks);
} }
if (ImGui::CollapsingHeader("Ocarina Controls")) {
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
DrawOcarinaControlPanel();
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
}
if (ImGui::CollapsingHeader("Camera Controls")) {
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
DrawCameraControlPanel();
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
}
if (ImGui::CollapsingHeader("D-Pad Controls")) {
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
DrawDpadControlPanel();
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
}
if (ImGui::CollapsingHeader("Miscellaneous Controls")) {
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
DrawMiscControlPanel();
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
}
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::PopStyleColor(); ImGui::PopStyleColor();

View File

@ -10,6 +10,15 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <set> #include <set>
#include <list>
typedef uint32_t N64ButtonMask;
typedef struct {
const char* label;
const char* cVarName;
N64ButtonMask defaultBtn;
} CustomButtonMap;
class SohInputEditorWindow : public LUS::GuiWindow { class SohInputEditorWindow : public LUS::GuiWindow {
public: public:
@ -51,6 +60,17 @@ class SohInputEditorWindow : public LUS::GuiWindow {
void DrawRemoveGyroMappingButton(uint8_t port, std::string id); void DrawRemoveGyroMappingButton(uint8_t port, std::string id);
void DrawAddGyroMappingButton(uint8_t port); 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 mGameInputBlockTimer;
int32_t mMappingInputBlockTimer; int32_t mMappingInputBlockTimer;
int32_t mRumbleTimer; int32_t mRumbleTimer;
@ -84,6 +104,4 @@ class SohInputEditorWindow : public LUS::GuiWindow {
bool mInputEditorPopupOpen; bool mInputEditorPopupOpen;
void DrawSetDefaultsButton(uint8_t portIndex); void DrawSetDefaultsButton(uint8_t portIndex);
void DrawClearAllButton(uint8_t portIndex); void DrawClearAllButton(uint8_t portIndex);
void DrawHelpIcon(const std::string& helptext);
}; };

View File

@ -67,6 +67,7 @@ typedef enum {
GROUP_EQUIPMENT, GROUP_EQUIPMENT,
GROUP_CONSUMABLE, GROUP_CONSUMABLE,
GROUP_HUD, GROUP_HUD,
GROUP_KALEIDO,
GROUP_TITLE, GROUP_TITLE,
GROUP_NPC, GROUP_NPC,
GROUP_WORLD, GROUP_WORLD,
@ -75,6 +76,7 @@ typedef enum {
GROUP_SPIN_ATTACK, GROUP_SPIN_ATTACK,
GROUP_TRAILS, GROUP_TRAILS,
GROUP_NAVI, GROUP_NAVI,
GROUP_IVAN,
} CosmeticGroup; } CosmeticGroup;
std::map<CosmeticGroup, const char*> groupLabels = { std::map<CosmeticGroup, const char*> groupLabels = {
@ -85,6 +87,7 @@ std::map<CosmeticGroup, const char*> groupLabels = {
{ GROUP_EQUIPMENT, "Equipment" }, { GROUP_EQUIPMENT, "Equipment" },
{ GROUP_CONSUMABLE, "Consumables" }, { GROUP_CONSUMABLE, "Consumables" },
{ GROUP_HUD, "HUD" }, { GROUP_HUD, "HUD" },
{ GROUP_KALEIDO, "Pause Menu" },
{ GROUP_TITLE, "Title Screen" }, { GROUP_TITLE, "Title Screen" },
{ GROUP_NPC, "NPCs" }, { GROUP_NPC, "NPCs" },
{ GROUP_WORLD, "World" }, { GROUP_WORLD, "World" },
@ -93,6 +96,7 @@ std::map<CosmeticGroup, const char*> groupLabels = {
{ GROUP_SPIN_ATTACK, "Spin Attack" }, { GROUP_SPIN_ATTACK, "Spin Attack" },
{ GROUP_TRAILS, "Trails" }, { GROUP_TRAILS, "Trails" },
{ GROUP_NAVI, "Navi" }, { GROUP_NAVI, "Navi" },
{ GROUP_IVAN, "Ivan" }
}; };
typedef struct { typedef struct {
@ -265,6 +269,38 @@ static std::map<std::string, CosmeticOption> cosmeticOptions = {
COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false),
COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true),
COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusA", "Quest StatusColor A", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusB", "Quest StatusColor B", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusC", "Quest StatusColor C", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusD", "Quest StatusColor D", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectA", "Map Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveA", "Save A", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveB", "Save B", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveC", "Save C", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveD", "Save D", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_NamePanel", "Name Panel", GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false),
COSMETIC_OPTION("Title_FileChoose", "File Choose", GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), COSMETIC_OPTION("Title_FileChoose", "File Choose", GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false),
COSMETIC_OPTION("Title_NintendoLogo", "Nintendo Logo", GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), COSMETIC_OPTION("Title_NintendoLogo", "Nintendo Logo", GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true),
COSMETIC_OPTION("Title_N64LogoRed", "N64 Red", GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), COSMETIC_OPTION("Title_N64LogoRed", "N64 Red", GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true),
@ -317,6 +353,9 @@ static std::map<std::string, CosmeticOption> cosmeticOptions = {
COSMETIC_OPTION("Navi_PropsPrimary", "Props Primary", GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), COSMETIC_OPTION("Navi_PropsPrimary", "Props Primary", GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false),
COSMETIC_OPTION("Navi_PropsSecondary", "Props Secondary", GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), COSMETIC_OPTION("Navi_PropsSecondary", "Props Secondary", GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true),
COSMETIC_OPTION("Ivan_IdlePrimary", "Ivan Idle Primary", GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false),
COSMETIC_OPTION("Ivan_IdleSecondary", "Ivan Idle Secondary", GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true),
COSMETIC_OPTION("NPC_FireKeesePrimary", "Fire Keese Primary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), COSMETIC_OPTION("NPC_FireKeesePrimary", "Fire Keese Primary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false),
COSMETIC_OPTION("NPC_FireKeeseSecondary", "Fire Keese Secondary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), COSMETIC_OPTION("NPC_FireKeeseSecondary", "Fire Keese Secondary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true),
COSMETIC_OPTION("NPC_IceKeesePrimary", "Ice Keese Primary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), COSMETIC_OPTION("NPC_IceKeesePrimary", "Ice Keese Primary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false),
@ -1626,6 +1665,8 @@ void RandomizeColor(CosmeticOption& cosmeticOption) {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_NPCSecondary"), 1.0f); CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_NPCSecondary"), 1.0f);
} else if (cosmeticOption.label == "Props Primary") { } else if (cosmeticOption.label == "Props Primary") {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_PropsSecondary"), 1.0f); CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_PropsSecondary"), 1.0f);
} else if (cosmeticOption.label == "Ivan Idle Primary") {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Ivan_IdleSecondary"), 0.5f);
} else if (cosmeticOption.label == "Level 1 Secondary") { } else if (cosmeticOption.label == "Level 1 Secondary") {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level1Primary"), 2.0f); CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level1Primary"), 2.0f);
} else if (cosmeticOption.label == "Level 2 Secondary") { } else if (cosmeticOption.label == "Level 2 Secondary") {
@ -1794,14 +1835,11 @@ void CosmeticsEditorWindow::DrawElement() {
} }
UIWidgets::EnhancementCheckbox("Sync Rainbow colors", "gCosmetics.RainbowSync"); UIWidgets::EnhancementCheckbox("Sync Rainbow colors", "gCosmetics.RainbowSync");
UIWidgets::EnhancementSliderFloat("Rainbow Speed: %.3f", "##rainbowSpeed", "gCosmetics.RainbowSpeed", 0.03f, 1.0f, "", 0.6f, false, true); UIWidgets::EnhancementSliderFloat("Rainbow Speed: %.3f", "##rainbowSpeed", "gCosmetics.RainbowSpeed", 0.03f, 1.0f, "", 0.6f, false, true);
UIWidgets::EnhancementCheckbox("Randomize All on New Scene", "gCosmetics.RandomizeAllOnNewScene");
UIWidgets::Tooltip("Enables randomizing all unlocked cosmetics when you enter a new scene.");
if (ImGui::Button("Randomize All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { if (ImGui::Button("Randomize All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) {
for (auto& [id, cosmeticOption] : cosmeticOptions) { CosmeticsEditor_RandomizeAll();
if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0))) {
RandomizeColor(cosmeticOption);
}
}
ApplyOrResetCustomGfxPatches();
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Reset All", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { if (ImGui::Button("Reset All", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) {
@ -1861,6 +1899,7 @@ void CosmeticsEditorWindow::DrawElement() {
if (ImGui::BeginTabItem("World & NPCs")) { if (ImGui::BeginTabItem("World & NPCs")) {
DrawCosmeticGroup(GROUP_WORLD); DrawCosmeticGroup(GROUP_WORLD);
DrawCosmeticGroup(GROUP_NAVI); DrawCosmeticGroup(GROUP_NAVI);
DrawCosmeticGroup(GROUP_IVAN);
DrawCosmeticGroup(GROUP_NPC); DrawCosmeticGroup(GROUP_NPC);
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
@ -1873,10 +1912,16 @@ void CosmeticsEditorWindow::DrawElement() {
DrawCosmeticGroup(GROUP_TITLE); DrawCosmeticGroup(GROUP_TITLE);
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
if (ImGui::BeginTabItem("HUD Placement")) { if (ImGui::BeginTabItem("HUD Placement")) {
Draw_Placements(); Draw_Placements();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
if (ImGui::BeginTabItem("Pause Menu")) {
DrawCosmeticGroup(GROUP_KALEIDO);
ImGui::EndTabItem();
}
ImGui::EndTabBar(); ImGui::EndTabBar();
} }
ImGui::End(); ImGui::End();
@ -1894,6 +1939,14 @@ void RegisterOnGameFrameUpdateHook() {
}); });
} }
void Cosmetics_RegisterOnSceneInitHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
if (CVarGetInteger("gCosmetics.RandomizeAllOnNewScene", 0)) {
CosmeticsEditor_RandomizeAll();
}
});
}
void CosmeticsEditorWindow::InitElement() { void CosmeticsEditorWindow::InitElement() {
// Convert the `current color` into the format that the ImGui color picker expects // Convert the `current color` into the format that the ImGui color picker expects
for (auto& [id, cosmeticOption] : cosmeticOptions) { for (auto& [id, cosmeticOption] : cosmeticOptions) {
@ -1911,6 +1964,7 @@ void CosmeticsEditorWindow::InitElement() {
RegisterOnLoadGameHook(); RegisterOnLoadGameHook();
RegisterOnGameFrameUpdateHook(); RegisterOnGameFrameUpdateHook();
Cosmetics_RegisterOnSceneInitHook();
} }
void CosmeticsEditor_RandomizeAll() { void CosmeticsEditor_RandomizeAll() {

View File

@ -8,6 +8,7 @@ extern "C" {
#include "objects/object_gi_soldout/object_gi_soldout.h" #include "objects/object_gi_soldout/object_gi_soldout.h"
#include "objects/object_ik/object_ik.h" #include "objects/object_ik/object_ik.h"
#include "objects/object_link_child/object_link_child.h" #include "objects/object_link_child/object_link_child.h"
#include "objects/object_ru2/object_ru2.h"
uint32_t ResourceMgr_GameHasMasterQuest(); uint32_t ResourceMgr_GameHasMasterQuest();
uint32_t ResourceMgr_GameHasOriginal(); uint32_t ResourceMgr_GameHasOriginal();
@ -187,10 +188,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() { void ApplyAuthenticGfxPatches() {
PatchDekuStickTextureOverflow(); PatchDekuStickTextureOverflow();
PatchFreezardTextureOverflow(); PatchFreezardTextureOverflow();
PatchIronKnuckleTextureOverflow(); PatchIronKnuckleTextureOverflow();
PatchPrincessRutoEaring();
} }
// Patches the Sold Out GI DL to render the texture in the mirror boundary // Patches the Sold Out GI DL to render the texture in the mirror boundary

View File

@ -38,6 +38,7 @@ typedef enum {
TEXT_CARPET_SALESMAN_1 = 0x6077, TEXT_CARPET_SALESMAN_1 = 0x6077,
TEXT_CARPET_SALESMAN_2 = 0x6078, TEXT_CARPET_SALESMAN_2 = 0x6078,
TEXT_MARKET_GUARD_NIGHT = 0x7003, TEXT_MARKET_GUARD_NIGHT = 0x7003,
TEXT_FISHERMAN_LEAVE = 0x409E,
TEXT_SHEIK_NEED_HOOK = 0x700F, TEXT_SHEIK_NEED_HOOK = 0x700F,
TEXT_SHEIK_HAVE_HOOK = 0x7010, TEXT_SHEIK_HAVE_HOOK = 0x7010,
TEXT_SCRUB_RANDOM = 0x9000, TEXT_SCRUB_RANDOM = 0x9000,

View File

@ -730,6 +730,62 @@ void RegisterPatchNoMSHandler() {
}); });
} }
void UpdatePatchHand() {
if ((CVarGetInteger("gEnhancements.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("gEnhancements.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("gEnhancements.ResetNaviTimer", 0)) {
gSaveContext.naviTimer = 0;
}
});
}
f32 triforcePieceScale; f32 triforcePieceScale;
void RegisterTriforceHunt() { void RegisterTriforceHunt() {
@ -1133,6 +1189,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("gHurtContainer", 0));
});
}
void RegisterRandomizedEnemySizes() { void RegisterRandomizedEnemySizes() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
// Randomized Enemy Sizes // Randomized Enemy Sizes
@ -1291,6 +1370,7 @@ void InitMods() {
RegisterBonkDamage(); RegisterBonkDamage();
RegisterMenuPathFix(); RegisterMenuPathFix();
RegisterMirrorModeHandler(); RegisterMirrorModeHandler();
RegisterResetNaviTimer();
RegisterTriforceHunt(); RegisterTriforceHunt();
RegisterGrantGanonsBossKey(); RegisterGrantGanonsBossKey();
RegisterEnemyDefeatCounts(); RegisterEnemyDefeatCounts();
@ -1300,4 +1380,6 @@ void InitMods() {
RegisterToTMedallions(); RegisterToTMedallions();
NameTag_RegisterHooks(); NameTag_RegisterHooks();
RegisterPatchNoMSHandler(); RegisterPatchNoMSHandler();
RegisterPatchHandHandler();
RegisterHurtContainerModeHandler();
} }

View File

@ -9,9 +9,11 @@ extern "C" {
void UpdateDirtPathFixState(int32_t sceneNum); void UpdateDirtPathFixState(int32_t sceneNum);
void UpdateMirrorModeState(int32_t sceneNum); void UpdateMirrorModeState(int32_t sceneNum);
void UpdateHurtContainerModeState(bool newState);
void PatchToTMedallions(); void PatchToTMedallions();
void UpdatePermanentHeartLossState(); void UpdatePermanentHeartLossState();
void InitMods(); void InitMods();
void UpdatePatchHand();
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -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) { void applyPreset(std::vector<PresetEntry> entries) {
for(auto& [cvar, type, value] : entries) { for(auto& [cvar, type, value] : entries) {
switch (type) { switch (type) {
@ -24,6 +32,9 @@ void applyPreset(std::vector<PresetEntry> entries) {
case PRESET_ENTRY_TYPE_STRING: case PRESET_ENTRY_TYPE_STRING:
CVarSetString(cvar, std::get<const char*>(value)); CVarSetString(cvar, std::get<const char*>(value));
break; break;
case PRESET_ENTRY_TYPE_CPP_STRING:
CVarSetString(cvar, std::get<std::string>(value).c_str());
break;
} }
} }
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <map> #include <map>
#include <string>
#include <vector> #include <vector>
#include <variant> #include <variant>
#include <cstdint> #include <cstdint>
@ -11,6 +12,7 @@ enum PresetEntryType {
PRESET_ENTRY_TYPE_S32, PRESET_ENTRY_TYPE_S32,
PRESET_ENTRY_TYPE_FLOAT, PRESET_ENTRY_TYPE_FLOAT,
PRESET_ENTRY_TYPE_STRING, PRESET_ENTRY_TYPE_STRING,
PRESET_ENTRY_TYPE_CPP_STRING,
}; };
enum PresetType { enum PresetType {
@ -36,15 +38,19 @@ enum RandomizerPreset {
typedef struct PresetEntry { typedef struct PresetEntry {
const char* cvar; const char* cvar;
PresetEntryType type; PresetEntryType type;
std::variant<int32_t, float, const char*> value; std::variant<int32_t, float, const char*, std::string> value;
} PresetEntry; } PresetEntry;
std::string FormatLocations(std::vector<RandomizerCheck> locs);
#define PRESET_ENTRY_S32(cvar, value) \ #define PRESET_ENTRY_S32(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_S32, value } { cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_FLOAT(cvar, value) \ #define PRESET_ENTRY_FLOAT(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_FLOAT, value } { cvar, PRESET_ENTRY_TYPE_FLOAT, value }
#define PRESET_ENTRY_STRING(cvar, value) \ #define PRESET_ENTRY_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_STRING, value } { cvar, PRESET_ENTRY_TYPE_STRING, value }
#define PRESET_ENTRY_CPP_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_CPP_STRING, value }
void DrawPresetSelector(PresetType presetType); void DrawPresetSelector(PresetType presetType);
void clearCvars(std::vector<const char*> cvarsToClear); void clearCvars(std::vector<const char*> cvarsToClear);
@ -70,6 +76,7 @@ const std::vector<const char*> enhancementsCvars = {
"gForgeTime", "gForgeTime",
"gClimbSpeed", "gClimbSpeed",
"gFasterBlockPush", "gFasterBlockPush",
"gCrawlSpeed",
"gFasterHeavyBlockLift", "gFasterHeavyBlockLift",
"gNoForcedNavi", "gNoForcedNavi",
"gSkulltulaFreeze", "gSkulltulaFreeze",
@ -136,6 +143,7 @@ const std::vector<const char*> enhancementsCvars = {
"gInjectItemCounts", "gInjectItemCounts",
"gDayGravePull", "gDayGravePull",
"gDampeAllNight", "gDampeAllNight",
"gQuitFishingAtDoor",
"gSkipSwimDeepEndAnim", "gSkipSwimDeepEndAnim",
"gSkipScarecrow", "gSkipScarecrow",
"gBlueFireArrows", "gBlueFireArrows",
@ -184,6 +192,14 @@ const std::vector<const char*> enhancementsCvars = {
"gBombchuBowlingNoSmallCucco", "gBombchuBowlingNoSmallCucco",
"gBombchuBowlingNoBigCucco", "gBombchuBowlingNoBigCucco",
"gBombchuBowlingAmmunition", "gBombchuBowlingAmmunition",
"gCustomizeOcarinaGame",
"gInstantOcarinaGameWin",
"gOcarinaGameNoteSpeed",
"gOcarinaUnlimitedFailTime",
"gOcarinaGameStartingNotes",
"gOcarinaGameRoundOneNotes",
"gOcarinaGameRoundTwoNotes",
"gOcarinaGameRoundThreeNotes",
"gCreditsFix", "gCreditsFix",
"gSilverRupeeJingleExtend", "gSilverRupeeJingleExtend",
"gStaticExplosionRadius", "gStaticExplosionRadius",
@ -256,6 +272,8 @@ const std::vector<const char*> cheatCvars = {
"gWalkSpeedToggle", "gWalkSpeedToggle",
"gWalkModifierOne", "gWalkModifierOne",
"gWalkModifierTwo", "gWalkModifierTwo",
"gSwimModifierOne",
"gSwimModifierTwo",
"gGoronPot", "gGoronPot",
"gDampeWin", "gDampeWin",
"gCustomizeShootingGallery", "gCustomizeShootingGallery",
@ -783,6 +801,13 @@ const std::vector<PresetEntry> randomizerPresetEntries = {
// Adult Minimum Weight (8 to 13) // Adult Minimum Weight (8 to 13)
PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6), PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6),
// Customize Lost Woods Ocarina Game Behavior
PRESET_ENTRY_S32("gCustomizeOcarinaGame", 1),
// Start With Five Notes
PRESET_ENTRY_S32("gOcarinaGameStartingNotes", 5),
// Round One Notes
PRESET_ENTRY_S32("gOcarinaGameRoundOneNotes", 5),
// Visual Stone of Agony // Visual Stone of Agony
PRESET_ENTRY_S32("gVisualAgony", 1), PRESET_ENTRY_S32("gVisualAgony", 1),
// Pull grave during the day // Pull grave during the day
@ -871,7 +896,8 @@ const std::vector<PresetEntry> spockRacePresetEntries = {
PRESET_ENTRY_S32("gRandomizeDampeHint", 1), PRESET_ENTRY_S32("gRandomizeDampeHint", 1),
PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN),
PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1), PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1),
PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "78,143,144,229,"), PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations(
{ RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })),
PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN), PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN),
PRESET_ENTRY_S32("gRandomizeFullWallets", 1), PRESET_ENTRY_S32("gRandomizeFullWallets", 1),
PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP),
@ -963,7 +989,8 @@ const std::vector<PresetEntry> spockRaceNoLogicPresetEntries = {
PRESET_ENTRY_S32("gRandomizeDampeHint", 1), PRESET_ENTRY_S32("gRandomizeDampeHint", 1),
PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN),
PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1), PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1),
PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "78,143,144,229,"), PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations(
{ RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })),
PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN), PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN),
PRESET_ENTRY_S32("gRandomizeFullWallets", 1), PRESET_ENTRY_S32("gRandomizeFullWallets", 1),
PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP),
@ -1016,7 +1043,7 @@ const std::vector<PresetEntry> s6PresetEntries = {
PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1), PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1),
PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 4), PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 4),
PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN),
PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "48,"), PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations({ RC_DEKU_THEATER_MASK_OF_TRUTH })),
PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_CLOSED_DEKU), PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_CLOSED_DEKU),
PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP),
PRESET_ENTRY_S32("gRandomizeGerudoFortress", RO_GF_FAST), PRESET_ENTRY_S32("gRandomizeGerudoFortress", RO_GF_FAST),

View File

@ -40,7 +40,7 @@ void AreaTable_Init_FireTemple() {
}, { }, {
//Exits //Exits
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}), Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(HOVER_BOOTS) || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}));}}), Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && (LogicFireBossDoorJump || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}))) || CanUse(HOVER_BOOTS));}}),
}); });
areaTable[FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { areaTable[FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {

View File

@ -536,7 +536,7 @@ namespace Logic {
Fish = HasBottle && FishAccess; Fish = HasBottle && FishAccess;
Fairy = HasBottle && FairyAccess; Fairy = HasBottle && FairyAccess;
FoundBombchus = (BombchuDrop || Bombchus || Bombchus5 || Bombchus10 || Bombchus20); FoundBombchus = (BombchuDrop || Bombchus || Bombchus5 || Bombchus10 || Bombchus20) && (BombBag || BombchusInLogic);
CanPlayBowling = (BombchusInLogic && FoundBombchus) || (!BombchusInLogic && BombBag); CanPlayBowling = (BombchusInLogic && FoundBombchus) || (!BombchusInLogic && BombBag);
HasBombchus = (BuyBombchus10 || BuyBombchus20 || (AmmoDrops.Is(AMMODROPS_BOMBCHU) && FoundBombchus)); HasBombchus = (BuyBombchus10 || BuyBombchus20 || (AmmoDrops.Is(AMMODROPS_BOMBCHU) && FoundBombchus));

View File

@ -4221,7 +4221,7 @@ void RandomizerSettingsWindow::DrawElement() {
break; break;
case RO_LACS_GREG_REWARD: case RO_LACS_GREG_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount",
"gRandomizeLacsStoneCount", 1, 4, "", 4, true, true, false); "gRandomizeLacsStoneCount", 1, 4, "", 3, true, true, false);
break; break;
case RO_LACS_WILDCARD_REWARD: case RO_LACS_WILDCARD_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount",
@ -4250,7 +4250,7 @@ void RandomizerSettingsWindow::DrawElement() {
break; break;
case RO_LACS_GREG_REWARD: case RO_LACS_GREG_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount",
"gRandomizeLacsMedallionCount", 1, 7, "", 7, true, true, false); "gRandomizeLacsMedallionCount", 1, 7, "", 6, true, true, false);
break; break;
case RO_LACS_WILDCARD_REWARD: case RO_LACS_WILDCARD_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount",
@ -4279,7 +4279,7 @@ void RandomizerSettingsWindow::DrawElement() {
break; break;
case RO_LACS_GREG_REWARD: case RO_LACS_GREG_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount",
"gRandomizeLacsRewardCount", 1, 10, "", 10, true, true, false); "gRandomizeLacsRewardCount", 1, 10, "", 9, true, true, false);
break; break;
case RO_LACS_WILDCARD_REWARD: case RO_LACS_WILDCARD_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount",
@ -4308,7 +4308,7 @@ void RandomizerSettingsWindow::DrawElement() {
break; break;
case RO_LACS_GREG_REWARD: case RO_LACS_GREG_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount",
"gRandomizeLacsDungeonCount", 1, 9, "", 9, true, true, false); "gRandomizeLacsDungeonCount", 1, 9, "", 8, true, true, false);
break; break;
case RO_LACS_WILDCARD_REWARD: case RO_LACS_WILDCARD_REWARD:
UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount",

View File

@ -412,10 +412,31 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
void DrawItemCount(ItemTrackerItem item) { void DrawItemCount(ItemTrackerItem item) {
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
int textSize = CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13);
ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item); ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item);
ImVec2 p = ImGui::GetCursorScreenPos(); ImVec2 p = ImGui::GetCursorScreenPos();
int32_t trackerNumberDisplayMode = CVarGetInteger("gItemTrackerCapacityTrack", ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); int32_t trackerNumberDisplayMode = CVarGetInteger("gItemTrackerCapacityTrack", ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY);
int32_t trackerKeyNumberDisplayMode = CVarGetInteger("gItemTrackerKeyTrack", KEYS_COLLECTED_MAX); int32_t trackerKeyNumberDisplayMode = CVarGetInteger("gItemTrackerKeyTrack", KEYS_COLLECTED_MAX);
float textScalingFactor = static_cast<float>(iconSize) / 36.0f;
uint32_t actualItemId = INV_CONTENT(item.id);
bool hasItem = actualItemId != ITEM_NONE;
if (CVarGetInteger("gTrackers.ItemTracker.HookshotIdentifier", 0)) {
if ((actualItemId == ITEM_HOOKSHOT || actualItemId == ITEM_LONGSHOT) && hasItem) {
// Calculate the scaled position for the text
ImVec2 textPos = ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(item.id == ITEM_HOOKSHOT ? "H" : "L").x *
textScalingFactor / 2) + 8 * textScalingFactor, p.y - 22 * textScalingFactor);
ImGui::SetCursorScreenPos(textPos);
ImGui::SetWindowFontScale(textScalingFactor);
ImGui::Text(item.id == ITEM_HOOKSHOT ? "H" : "L");
ImGui::SetWindowFontScale(1.0f); // Reset font scale to the original state
}
}
ImGui::SetWindowFontScale(textSize / 13.0f);
if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) {
std::string currentString = ""; std::string currentString = "";
@ -671,7 +692,7 @@ void DrawDungeonItem(ItemTrackerItem item) {
ImVec2 p = ImGui::GetCursorScreenPos(); ImVec2 p = ImGui::GetCursorScreenPos();
std::string dungeonName = itemTrackerDungeonShortNames[item.data]; std::string dungeonName = itemTrackerDungeonShortNames[item.data];
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + 16))); ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13) + 3)));
ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor); ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor);
ImGui::Text("%s", dungeonName.c_str()); ImGui::Text("%s", dungeonName.c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
@ -800,7 +821,7 @@ void DrawItemsInACircle(std::vector<ItemTrackerItem> items) {
float angle = (float)i / items.size() * 2.0f * M_PI; float angle = (float)i / items.size() * 2.0f * M_PI;
float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f;
float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f;
ImGui::SetCursorPos(ImVec2(x - 14, y + 4)); ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger("gItemTrackerIconSize", 36) - 8) / 2.0f, y + 4));
items[i].drawFunc(items[i]); items[i].drawFunc(items[i]);
} }
} }
@ -1127,6 +1148,7 @@ void ItemTrackerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator(); UIWidgets::PaddedSeparator();
UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36); UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36);
UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12); UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12);
UIWidgets::EnhancementSliderInt("Text size : %dpx", "##ITEMTRACKERTEXTSIZE", "gTrackers.ItemTracker.ItemTrackerTextSize", 1, 30, "", 13);
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
@ -1167,7 +1189,7 @@ void ItemTrackerSettingsWindow::DrawElement() {
shouldUpdateVectors = true; shouldUpdateVectors = true;
} }
if (CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { if (CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) {
if (UIWidgets::PaddedEnhancementCheckbox("Circle display", "gItemTrackerDungeonRewardsCircle", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { if (UIWidgets::PaddedEnhancementCheckbox("Circle display", "gItemTrackerDungeonRewardsCircle", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, false)) {
shouldUpdateVectors = true; shouldUpdateVectors = true;
} }
} }
@ -1200,6 +1222,10 @@ void ItemTrackerSettingsWindow::DrawElement() {
shouldUpdateVectors = true; shouldUpdateVectors = true;
} }
} }
UIWidgets::EnhancementCheckbox("Show Hookshot Identifiers", "gTrackers.ItemTracker.HookshotIdentifier");
UIWidgets::InsertHelpHoverText("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot.");
UIWidgets::Spacer(0);
ImGui::PopStyleVar(1); ImGui::PopStyleVar(1);
ImGui::EndTable(); ImGui::EndTable();

View File

@ -207,6 +207,9 @@ extern "C" void Randomizer_InitSaveFile() {
gSaveContext.randomizerInf[i] = 0; gSaveContext.randomizerInf[i] = 0;
} }
// Reset triforce pieces collected
gSaveContext.triforcePiecesCollected = 0;
gSaveContext.cutsceneIndex = 0; // no intro cutscene gSaveContext.cutsceneIndex = 0; // no intro cutscene
// Starts pending ice traps out at 0 before potentially incrementing them down the line. // Starts pending ice traps out at 0 before potentially incrementing them down the line.
gSaveContext.pendingIceTrapCount = 0; gSaveContext.pendingIceTrapCount = 0;
@ -442,8 +445,5 @@ extern "C" void Randomizer_InitSaveFile() {
gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth
} }
// Reset triforce pieces collected
gSaveContext.triforcePiecesCollected = 0;
SetStartingItems(); SetStartingItems();
} }

View File

@ -115,7 +115,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() {
const bool disabled_resolutionSlider = (CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) && const bool disabled_resolutionSlider = (CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) &&
CVarGetInteger("gAdvancedResolution.Enabled", 0)) || CVarGetInteger("gAdvancedResolution.Enabled", 0)) ||
CVarGetInteger("gLowResMode", 0); CVarGetInteger("gLowResMode", 0);
if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f%%", "##IMul", "gInternalResolution", 0.5f,
2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) {
LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier( LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(
CVarGetFloat("gInternalResolution", 1)); CVarGetFloat("gInternalResolution", 1));

View File

@ -29,7 +29,6 @@
#include <dr_libs/wav.h> #include <dr_libs/wav.h>
#include <AudioPlayer.h> #include <AudioPlayer.h>
#include "Enhancements/speechsynthesizer/SpeechSynthesizer.h" #include "Enhancements/speechsynthesizer/SpeechSynthesizer.h"
#include "Enhancements/controls/GameControlEditor.h"
#include "Enhancements/controls/SohInputEditorWindow.h" #include "Enhancements/controls/SohInputEditorWindow.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/audio/AudioCollection.h" #include "Enhancements/audio/AudioCollection.h"
@ -318,6 +317,8 @@ OTRGlobals::OTRGlobals() {
context->InitWindow(sohInputEditorWindow); context->InitWindow(sohInputEditorWindow);
context->InitAudio(); context->InitAudio();
SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion);
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Animation, "Animation", std::make_shared<LUS::AnimationFactory>()); context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Animation, "Animation", std::make_shared<LUS::AnimationFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_PlayerAnimation, "PlayerAnimation", std::make_shared<LUS::PlayerAnimationFactory>()); context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_PlayerAnimation, "PlayerAnimation", std::make_shared<LUS::PlayerAnimationFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Room, "Room", std::make_shared<LUS::SceneFactory>()); // Is room scene? maybe? context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Room, "Room", std::make_shared<LUS::SceneFactory>()); // Is room scene? maybe?
@ -1213,8 +1214,7 @@ extern "C" uint64_t GetUnixTimestamp() {
auto time = std::chrono::system_clock::now(); auto time = std::chrono::system_clock::now();
auto since_epoch = time.time_since_epoch(); auto since_epoch = time.time_since_epoch();
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch); auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch);
long now = millis.count(); return (uint64_t)millis.count();
return now;
} }
// C->C++ Bridge // C->C++ Bridge
@ -2563,8 +2563,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
randoInf = RAND_INF_MERCHANTS_CARPET_SALESMAN; randoInf = RAND_INF_MERCHANTS_CARPET_SALESMAN;
} }
messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_ON_HINT); messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_ON_HINT);
} else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && } else if (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT) {
(textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
} else if (textId == TEXT_CURSED_SKULLTULA_PEOPLE) { } else if (textId == TEXT_CURSED_SKULLTULA_PEOPLE) {
actorParams = GET_PLAYER(play)->targetActor->params; actorParams = GET_PLAYER(play)->targetActor->params;
@ -2629,6 +2628,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger("gMarketSneak", 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger("gMarketSneak", 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT); messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT);
} }
if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger("gQuitFishingAtDoor", 0)) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE);
}
font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition();
switch (gSaveContext.language) { switch (gSaveContext.language) {
case LANGUAGE_FRA: case LANGUAGE_FRA:
@ -2674,6 +2676,24 @@ extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* repla
gfx_register_blended_texture(name, mask, replacement); gfx_register_blended_texture(name, mask, replacement);
} }
extern "C" void Gfx_UnregisterBlendedTexture(const char* name) {
gfx_unregister_blended_texture(name);
}
extern "C" void Gfx_TextureCacheDelete(const uint8_t* texAddr) {
char* imgName = (char*)texAddr;
if (texAddr == nullptr) {
return;
}
if (ResourceMgr_OTRSigCheck(imgName)) {
texAddr = (const uint8_t*)GetResourceDataByNameHandlingMQ(imgName);
}
gfx_texture_cache_delete(texAddr);
}
void SoH_ProcessDroppedFiles(std::string filePath) { void SoH_ProcessDroppedFiles(std::string filePath) {
try { try {
std::ifstream configStream(filePath); std::ifstream configStream(filePath);

View File

@ -176,6 +176,8 @@ void Entrance_InitEntranceTrackingData(void);
void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex); void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex);
void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex); void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex);
void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement); void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement);
void Gfx_UnregisterBlendedTexture(const char* name);
void Gfx_TextureCacheDelete(const uint8_t* addr);
void SaveManager_ThreadPoolWait(); void SaveManager_ThreadPoolWait();
void CheckTracker_OnMessageClose(); void CheckTracker_OnMessageClose();

View File

@ -116,7 +116,6 @@ namespace SohGui {
std::shared_ptr<LUS::GuiWindow> mInputEditorWindow; std::shared_ptr<LUS::GuiWindow> mInputEditorWindow;
std::shared_ptr<AudioEditor> mAudioEditorWindow; std::shared_ptr<AudioEditor> mAudioEditorWindow;
std::shared_ptr<GameControlEditor::GameControlEditorWindow> mGameControlEditorWindow;
std::shared_ptr<CosmeticsEditorWindow> mCosmeticsEditorWindow; std::shared_ptr<CosmeticsEditorWindow> mCosmeticsEditorWindow;
std::shared_ptr<ActorViewerWindow> mActorViewerWindow; std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
std::shared_ptr<ColViewerWindow> mColViewerWindow; std::shared_ptr<ColViewerWindow> mColViewerWindow;
@ -164,8 +163,6 @@ namespace SohGui {
mAudioEditorWindow = std::make_shared<AudioEditor>("gAudioEditor.WindowOpen", "Audio Editor"); mAudioEditorWindow = std::make_shared<AudioEditor>("gAudioEditor.WindowOpen", "Audio Editor");
gui->AddGuiWindow(mAudioEditorWindow); gui->AddGuiWindow(mAudioEditorWindow);
mGameControlEditorWindow = std::make_shared<GameControlEditor::GameControlEditorWindow>("gGameControlEditorEnabled", "Game Control Editor");
gui->AddGuiWindow(mGameControlEditorWindow);
mCosmeticsEditorWindow = std::make_shared<CosmeticsEditorWindow>("gCosmeticsEditorEnabled", "Cosmetics Editor"); mCosmeticsEditorWindow = std::make_shared<CosmeticsEditorWindow>("gCosmeticsEditorEnabled", "Cosmetics Editor");
gui->AddGuiWindow(mCosmeticsEditorWindow); gui->AddGuiWindow(mCosmeticsEditorWindow);
mActorViewerWindow = std::make_shared<ActorViewerWindow>("gActorViewerEnabled", "Actor Viewer"); mActorViewerWindow = std::make_shared<ActorViewerWindow>("gActorViewerEnabled", "Actor Viewer");
@ -211,7 +208,6 @@ namespace SohGui {
mColViewerWindow = nullptr; mColViewerWindow = nullptr;
mActorViewerWindow = nullptr; mActorViewerWindow = nullptr;
mCosmeticsEditorWindow = nullptr; mCosmeticsEditorWindow = nullptr;
mGameControlEditorWindow = nullptr;
mAudioEditorWindow = nullptr; mAudioEditorWindow = nullptr;
mInputEditorWindow = nullptr; mInputEditorWindow = nullptr;
mStatsWindow = nullptr; mStatsWindow = nullptr;

View File

@ -11,7 +11,6 @@
#include <stdio.h> #include <stdio.h>
#include "SohMenuBar.h" #include "SohMenuBar.h"
#include "Enhancements/audio/AudioEditor.h" #include "Enhancements/audio/AudioEditor.h"
#include "Enhancements/controls/GameControlEditor.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/actorViewer.h"
#include "Enhancements/debugger/colViewer.h" #include "Enhancements/debugger/colViewer.h"

View File

@ -21,7 +21,6 @@
#include "Enhancements/audio/AudioEditor.h" #include "Enhancements/audio/AudioEditor.h"
#include "Enhancements/controls/GameControlEditor.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/actorViewer.h"
#include "Enhancements/debugger/colViewer.h" #include "Enhancements/debugger/colViewer.h"
@ -180,7 +179,6 @@ void DrawShipMenu() {
} }
extern std::shared_ptr<LUS::GuiWindow> mInputEditorWindow; extern std::shared_ptr<LUS::GuiWindow> mInputEditorWindow;
extern std::shared_ptr<GameControlEditor::GameControlEditorWindow> mGameControlEditorWindow;
extern std::shared_ptr<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow> mAdvancedResolutionSettingsWindow; extern std::shared_ptr<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow> mAdvancedResolutionSettingsWindow;
void DrawSettingsMenu() { void DrawSettingsMenu() {
@ -241,11 +239,6 @@ void DrawSettingsMenu() {
mInputEditorWindow->ToggleVisibility(); mInputEditorWindow->ToggleVisibility();
} }
} }
if (mGameControlEditorWindow) {
if (ImGui::Button(GetWindowButtonText("Additional Controller Options", CVarGetInteger("gGameControlEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
mGameControlEditorWindow->ToggleVisibility();
}
}
UIWidgets::PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::PopStyleColor(1); ImGui::PopStyleColor(1);
ImGui::PopStyleVar(3); ImGui::PopStyleVar(3);
@ -273,8 +266,10 @@ void DrawSettingsMenu() {
2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) {
LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1)); LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1));
} }
UIWidgets::Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing"); UIWidgets::Tooltip("Resolution scale. Multiplies output resolution by this value, on each axis relative to window size.\n"
#endif "Lower values may improve performance.\n"
"Values above 100% can be used for super-sampling, as an intensive but highly effective form of anti-aliasing.\n\n"
"Default: 100%");
if (mAdvancedResolutionSettingsWindow) { if (mAdvancedResolutionSettingsWindow) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f));
@ -288,14 +283,28 @@ void DrawSettingsMenu() {
ImGui::PopStyleColor(1); ImGui::PopStyleColor(1);
ImGui::PopStyleVar(3); ImGui::PopStyleVar(3);
} }
#else
#ifndef __WIIU__ // macOS: Internal resolution is currently disabled in libultraship.
if (UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, false)) { ImGui::BeginGroup();
LUS::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); ImGui::Text("Internal Resolution: 100.0%%");
}; UIWidgets::Spacer(0);
UIWidgets::Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); ImGui::Text(" " ICON_FA_INFO_CIRCLE " Not available on this system.");
UIWidgets::Spacer(0);
ImGui::EndGroup();
#endif #endif
#ifndef __WIIU__
if (UIWidgets::PaddedEnhancementSliderInt(
(CVarGetInteger("gMSAAValue", 1) == 1) ? "Anti-aliasing (MSAA): Off" : "Anti-aliasing (MSAA): %d",
"##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, false)) {
LUS::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1));
}
UIWidgets::Tooltip("Activates MSAA (multi-sample anti-aliasing) from 2x up to 8x, to smooth the edges of rendered geometry.\n"
"Higher sample count will result in smoother edges on models, but may reduce performance.\n\n"
"Recommended: 2x or 4x");
#endif
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
{ // FPS Slider { // FPS Slider
const int minFps = 20; const int minFps = 20;
static int maxFps; static int maxFps;
@ -369,26 +378,27 @@ void DrawSettingsMenu() {
bool matchingRefreshRate = bool matchingRefreshRate =
CVarGetInteger("gMatchRefreshRate", 0) && LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() != LUS::WindowBackend::DX11; CVarGetInteger("gMatchRefreshRate", 0) && LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() != LUS::WindowBackend::DX11;
UIWidgets::PaddedEnhancementSliderInt( UIWidgets::PaddedEnhancementSliderInt(
(currentFps == 20) ? "FPS: Original (20)" : "FPS: %d", (currentFps == 20) ? "Frame Rate: Original (20 fps)" : "Frame Rate: %d fps",
"##FPSInterpolation", "gInterpolationFPS", minFps, maxFps, "", 20, true, true, false, matchingRefreshRate); "##FPSInterpolation", "gInterpolationFPS", minFps, maxFps, "", 20, true, true, false, matchingRefreshRate);
#endif #endif
if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) {
UIWidgets::Tooltip( UIWidgets::Tooltip(
"Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is purely " "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics.\n"
"visual and does not impact game logic, execution of glitches etc.\n\n" "This is purely visual and does not impact game logic, execution of glitches etc.\n"
"A higher target FPS than your monitor's refresh rate will waste resources, and might give a worse result." "Higher frame rate settings may impact CPU performance."
); "\n\n " ICON_FA_INFO_CIRCLE
" There is no need to set this above your monitor's refresh rate. Doing so will waste resources and may give a worse result.");
} else { } else {
UIWidgets::Tooltip( UIWidgets::Tooltip(
"Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is purely " "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics.\n"
"visual and does not impact game logic, execution of glitches etc." "This is purely visual and does not impact game logic, execution of glitches etc.\n"
); "Higher frame rate settings may impact CPU performance.");
} }
} // END FPS Slider } // END FPS Slider
if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) {
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
if (ImGui::Button("Match Refresh Rate")) { if (ImGui::Button("Match Frame Rate to Refresh Rate")) {
int hz = LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); int hz = LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
if (hz >= 20 && hz <= 360) { if (hz >= 20 && hz <= 360) {
CVarSetInteger("gInterpolationFPS", hz); CVarSetInteger("gInterpolationFPS", hz);
@ -396,17 +406,22 @@ void DrawSettingsMenu() {
} }
} }
} else { } else {
UIWidgets::PaddedEnhancementCheckbox("Match Refresh Rate", "gMatchRefreshRate", true, false); UIWidgets::PaddedEnhancementCheckbox("Match Frame Rate to Refresh Rate", "gMatchRefreshRate", true, false);
} }
UIWidgets::Tooltip("Matches interpolation value to the current game's window refresh rate"); UIWidgets::Tooltip("Matches interpolation value to the game window's current refresh rate.");
if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) {
UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS", UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS",
"##ExtraLatencyThreshold", "gExtraLatencyThreshold", 0, 360, "", 80, true, true, false); "##ExtraLatencyThreshold", "gExtraLatencyThreshold", 0, 360, "", 80, true, true, false);
UIWidgets::Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to work on one frame while GPU works on the previous frame.\nThis setting should be used when your computer is too slow to do CPU + GPU work in time."); UIWidgets::Tooltip(
"(For DirectX backend only)\n\n"
"When Interpolation FPS (Frame Rate) setting is at least this threshold, add one frame of delay (e.g. 16.6 ms for 60 FPS) in order to avoid jitter."
"This setting allows the CPU to work on one frame while GPU works on the previous frame.\n"
"This setting should be used when your computer is too slow to do CPU + GPU work in time.");
} }
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
ImGui::Text("ImGui Menu Scale"); ImGui::Text("ImGui Menu Scale");
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextColored({ 0.85f, 0.35f, 0.0f, 1.0f }, "(Experimental)"); ImGui::TextColored({ 0.85f, 0.35f, 0.0f, 1.0f }, "(Experimental)");
@ -455,6 +470,7 @@ void DrawSettingsMenu() {
if (LUS::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) { if (LUS::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) {
UIWidgets::PaddedEnhancementCheckbox("Enable Vsync", "gVsyncEnabled", true, false); UIWidgets::PaddedEnhancementCheckbox("Enable Vsync", "gVsyncEnabled", true, false);
UIWidgets::Tooltip("Activate vertical sync, to prevent screen tearing.");
} }
if (LUS::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) { if (LUS::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) {
@ -462,17 +478,21 @@ void DrawSettingsMenu() {
} }
if (LUS::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) { if (LUS::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) {
UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows", "gEnableMultiViewports", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows (Needs reload)", "gEnableMultiViewports", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload to take effect."); UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload to take effect.");
} }
// If more filters are added to LUS, make sure to add them to the filters list here // If more filters are added to LUS, make sure to add them to the filters list here
ImGui::Text("Texture Filter (Needs reload)"); ImGui::Text("Texture Filtering (Needs reload)");
UIWidgets::EnhancementCombobox("gTextureFilter", filters, FILTER_THREE_POINT); UIWidgets::EnhancementCombobox("gTextureFilter", filters, FILTER_THREE_POINT);
UIWidgets::Tooltip("Texture filtering, aka texture smoothing. Requires a reload to take effect.\n\n"
"Three-Point: Replicates real N64 texture filtering.\n"
"Bilinear: If Three-Point causes poor performance, try this.\n"
"Nearest: Disables texture smoothing. (Not recommended)");
UIWidgets::Spacer(0); UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
// Draw LUS settings menu (such as Overlays Text Font)
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->DrawSettings(); LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->DrawSettings();
ImGui::EndMenu(); ImGui::EndMenu();
@ -542,6 +562,7 @@ void DrawEnhancementsMenu() {
UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, true, false, true);
UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, true, false, true);
UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, true, false, true);
UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", "gCrawlSpeed", 1, 5, "", 1, true, false, true);
UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false);
UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks");
UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false);
@ -573,6 +594,8 @@ void DrawEnhancementsMenu() {
"This doesn't work if the save was made in a grotto."); "This doesn't work if the save was made in a grotto.");
UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false);
UIWidgets::Tooltip("Prevent forced Navi conversations"); UIWidgets::Tooltip("Prevent forced Navi conversations");
UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", "gEnhancements.ResetNaviTimer", true, false);
UIWidgets::Tooltip("Resets the Navi timer on scene change. If you have already talked to her, she will try and talk to you again, instead of needing a save warp or death. ");
UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false);
UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas");
UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false); UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false);
@ -610,6 +633,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate."); UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate.");
UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false);
UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name");
UIWidgets::PaddedEnhancementCheckbox("Quit Fishing At Door", "gQuitFishingAtDoor", true, false);
UIWidgets::Tooltip("Fisherman asks if you want to quit at the door when you still have the rod");
UIWidgets::PaddedText("Time Travel with the Song of Time", true, false); UIWidgets::PaddedText("Time Travel with the Song of Time", true, false);
UIWidgets::EnhancementCombobox("gTimeTravel", timeTravelOptions, 0); UIWidgets::EnhancementCombobox("gTimeTravel", timeTravelOptions, 0);
UIWidgets::Tooltip("Allows Link to freely change age by playing the Song of Time.\n" UIWidgets::Tooltip("Allows Link to freely change age by playing the Song of Time.\n"
@ -814,6 +839,40 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult"); UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult");
ImGui::EndMenu(); ImGui::EndMenu();
} }
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Lost Woods Ocarina Game")) {
UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeOcarinaGame");
UIWidgets::Tooltip("Turn on/off changes to the lost woods ocarina game behavior");
bool disabled = !CVarGetInteger("gCustomizeOcarinaGame", 0);
static const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off";
UIWidgets::PaddedEnhancementCheckbox("Instant Win", "gInstantOcarinaGameWin", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Skips the lost woods ocarina game");
UIWidgets::PaddedEnhancementSliderInt("Note Play Speed: %dx", "##OcarinaGameNoteSpeed", "gOcarinaGameNoteSpeed", 1, 5, "", 1, true, true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Adjust the speed that the skull kids play notes");
UIWidgets::PaddedEnhancementCheckbox("Unlimited Playback Time", "gOcarinaUnlimitedFailTime", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Removes the timer to play back the song");
UIWidgets::PaddedEnhancementSliderInt("Number of Starting Notes: %d", "##OcarinaGameStartingNotes", "gOcarinaGameStartingNotes", 1, 8, "", 3, true, true, false,
disabled, disabledTooltip);
UIWidgets::Tooltip("Adjust the number of notes the skull kids play to start the first round");
int roundMin = CVarGetInteger("gOcarinaGameStartingNotes", 3);
UIWidgets::PaddedEnhancementSliderInt("Round One Notes: %d", "##OcarinaGameRoundOne",
"gOcarinaGameRoundOneNotes", roundMin, 8, "", 5, true, true,
false,
disabled, disabledTooltip);
UIWidgets::Tooltip("Adjust the number of notes you need to play to end the first round");
UIWidgets::PaddedEnhancementSliderInt("Round Two Notes: %d", "##OcarinaGameRoundTwoNotes",
"gOcarinaGameRoundTwoNotes", roundMin, 8, "", 6, true, true,
false,
disabled, disabledTooltip);
UIWidgets::Tooltip("Adjust the number of notes you need to play to end the second round");
UIWidgets::PaddedEnhancementSliderInt("Round Three Notes: %d", "##OcarinaGameRoundThreeNotes",
"gOcarinaGameRoundThreeNotes", roundMin, 8, "", 8, true, true,
false,
disabled, disabledTooltip);
UIWidgets::Tooltip("Adjust the number of notes you need to play to end the third round");
ImGui::EndMenu();
}
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
@ -1046,6 +1105,15 @@ void DrawEnhancementsMenu() {
UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false);
UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance");
} }
if (UIWidgets::PaddedEnhancementCheckbox("Show Age-Dependent Equipment", "gEnhancements.EquimentAlwaysVisible", true,
false)) {
UpdatePatchHand();
}
UIWidgets::Tooltip("Makes all equipment visible, regardless of Age.");
if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0) == 1) {
UIWidgets::PaddedEnhancementCheckbox("Scale Adult Equipment as Child", "gEnhancements.ScaleAdultEquimentAsChild", true, false);
UIWidgets::Tooltip("Scales all of the Adult Equipment, as well and moving some a bit, to fit on Child Link Better. May not work properly with some mods.");
}
UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false); UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false);
UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution");
UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false); UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false);
@ -1064,6 +1132,7 @@ void DrawEnhancementsMenu() {
PatchToTMedallions(); PatchToTMedallions();
} }
UIWidgets::Tooltip("When medallions are collected, the medallion imprints around the Master Sword pedestal in the Temple of Time will become colored"); UIWidgets::Tooltip("When medallions are collected, the medallion imprints around the Master Sword pedestal in the Temple of Time will become colored");
UIWidgets::PaddedEnhancementCheckbox("Show locked door chains on both sides of locked doors", "gShowDoorLocksOnBothSides", true, false);
UIWidgets::PaddedText("Fix Vanishing Paths", true, false); UIWidgets::PaddedText("Fix Vanishing Paths", true, false);
if (UIWidgets::EnhancementCombobox("gSceneSpecificDirtPathFix", zFightingOptions, ZFIGHT_FIX_DISABLED) && gPlayState != NULL) { if (UIWidgets::EnhancementCombobox("gSceneSpecificDirtPathFix", zFightingOptions, ZFIGHT_FIX_DISABLED) && gPlayState != NULL) {
UpdateDirtPathFixState(gPlayState->sceneNum); UpdateDirtPathFixState(gPlayState->sceneNum);
@ -1257,6 +1326,14 @@ void DrawEnhancementsMenu() {
} }
} }
UIWidgets::Spacer(0);
if (UIWidgets::PaddedEnhancementCheckbox("Hurt Container Mode", "gHurtContainer", true, false)) {
UpdateHurtContainerModeState(CVarGetInteger("gHurtContainer", 0));
}
UIWidgets::Tooltip("Changes Heart Piece and Heart Container functionality.\n\n"
"- Each Heart Container or full Heart Piece reduces Links hearts by 1.\n"
"- Can be enabled retroactively after a File has already started.");
ImGui::EndMenu(); ImGui::EndMenu();
} }

View File

@ -449,7 +449,7 @@ namespace UIWidgets {
if (changed && !(abs(oldVal - val) < 0.000001f)) { if (changed && !(abs(oldVal - val) < 0.000001f)) {
std::stringstream ss; std::stringstream ss;
ss << std::setprecision(ticks) << val; ss << std::setprecision(ticks + 1) << val;
val = std::stof(ss.str()); val = std::stof(ss.str());
CVarSetFloat(cvarName, val); CVarSetFloat(cvarName, val);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();

View File

@ -182,4 +182,9 @@ extern "C" void OTRMessage_Init()
CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w",
"Du siehst gelangweilt aus.&Willst du einen Spaziergang machen?\x1B&%gJa&Nein%w", "Du siehst gelangweilt aus.&Willst du einen Spaziergang machen?\x1B&%gJa&Nein%w",
"Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w")); "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w"));
CustomMessageManager::Instance->CreateMessage(
customMessageTableID, TEXT_FISHERMAN_LEAVE,
CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w",
"Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest du aufhören?&\x1B&%gJa&Nein%w", //TODO Used AI translation as placeholder
"Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w")); //TODO Used AI translation as placeholder
} }

View File

@ -149,6 +149,13 @@ bool Scene_CommandMeshHeader(PlayState* play, LUS::ISceneCommand* cmd) {
extern "C" void* func_800982FC(ObjectContext* objectCtx, s32 bankIndex, s16 objectId); extern "C" void* func_800982FC(ObjectContext* objectCtx, s32 bankIndex, s16 objectId);
bool OTRfunc_800982FC(ObjectContext* objectCtx, s32 bankIndex, s16 objectId) {
objectCtx->status[bankIndex].id = -objectId;
return false;
}
bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) { bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) {
// LUS::SetObjectList* cmdObj = static_pointer_cast<LUS::SetObjectList>(cmd); // LUS::SetObjectList* cmdObj = static_pointer_cast<LUS::SetObjectList>(cmd);
LUS::SetObjectList* cmdObj = (LUS::SetObjectList*)cmd; LUS::SetObjectList* cmdObj = (LUS::SetObjectList*)cmd;
@ -164,49 +171,30 @@ bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) {
void* nextPtr; void* nextPtr;
k = 0; k = 0;
// i = play->objectCtx.unk_09; i = play->objectCtx.unk_09;
i = 0;
firstStatus = &play->objectCtx.status[0]; firstStatus = &play->objectCtx.status[0];
status = &play->objectCtx.status[i]; status = &play->objectCtx.status[i];
for (int i = 0; i < cmdObj->objects.size(); i++) { // Loop until a mismatch in the object lists
bool alreadyIncluded = false; // Then clear all object ids past that in the context object list and kill actors for those objects
for (i = play->objectCtx.unk_09, k = 0; i < play->objectCtx.num; i++, k++) {
for (int j = 0; j < play->objectCtx.num; j++) { if (play->objectCtx.status[i].id != cmdObj->objects[k]) {
if (play->objectCtx.status[j].id == cmdObj->objects[i]) { for (j = i; j < play->objectCtx.num; j++) {
alreadyIncluded = true; play->objectCtx.status[j].id = OBJECT_INVALID;
break;
} }
}
if (!alreadyIncluded) {
play->objectCtx.status[play->objectCtx.num++].id = cmdObj->objects[i];
func_80031A28(play, &play->actorCtx); func_80031A28(play, &play->actorCtx);
break;
} }
} }
/* // Continuing from the last index, add the remaining object ids from the command object list
while (i < play->objectCtx.num) { for (; k < cmdObj->objects.size(); k++, i++) {
if (status->id != *objectEntry) { if (i < OBJECT_EXCHANGE_BANK_MAX - 1) {
status2 = &play->objectCtx.status[i]; OTRfunc_800982FC(&play->objectCtx, i, cmdObj->objects[k]);
for (j = i; j < play->objectCtx.num; j++) {
status2->id = OBJECT_INVALID;
status2++;
}
play->objectCtx.num = i;
func_80031A28(play, &play->actorCtx);
continue;
} }
i++;
k++;
objectEntry++;
status++;
} }
play->objectCtx.num = i; play->objectCtx.num = i;
*/
return false; return false;
} }

View File

@ -2066,15 +2066,39 @@ void func_800EE404(void) {
void Audio_OcaMemoryGameStart(u8 minigameRound) { void Audio_OcaMemoryGameStart(u8 minigameRound) {
u8 i; u8 i;
if (minigameRound > 2) { // #region SOH [Enhancement]
minigameRound = 2; if (CVarGetInteger("gCustomizeOcarinaGame", 0)) {
} u8 startingNotes = 3;
u8 roundOneCount = CVarGetInteger("gOcarinaGameRoundOneNotes", 5);
u8 roundTwoCount = CVarGetInteger("gOcarinaGameRoundTwoNotes", 6);
u8 roundThreeCount = CVarGetInteger("gOcarinaGameRoundThreeNotes", 8);
u8 modMinigameNoteCnts[] = { roundOneCount, roundTwoCount, roundThreeCount };
sOcaMinigameAppendPos = 0;
sOcaMinigameEndPos = sOcaMinigameNoteCnts[minigameRound];
for (i = 0; i < 3; i++) { startingNotes = CVarGetInteger("gOcarinaGameStartingNotes", 3);
Audio_OcaMemoryGameGenNote();
if (minigameRound > 2) {
minigameRound = 2;
}
sOcaMinigameAppendPos = 0;
sOcaMinigameEndPos = modMinigameNoteCnts[minigameRound];
for (i = 0; i < startingNotes; i++) {
Audio_OcaMemoryGameGenNote();
}
// #endregion
} else {
if (minigameRound > 2) {
minigameRound = 2;
}
sOcaMinigameAppendPos = 0;
sOcaMinigameEndPos = sOcaMinigameNoteCnts[minigameRound];
for (i = 0; i < 3; i++) {
Audio_OcaMemoryGameGenNote();
}
} }
} }
@ -2093,11 +2117,24 @@ s32 Audio_OcaMemoryGameGenNote(void) {
rndNote = sOcarinaNoteValues[(rnd + 1) % 5]; rndNote = sOcarinaNoteValues[(rnd + 1) % 5];
} }
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].noteIdx = rndNote; // #region SOH [Enhancement]
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].unk_02 = 0x2D; if (CVarGetInteger("gCustomizeOcarinaGame", 0)) {
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].volume = 0x50; int noteSpeed = 0x2D;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].vibrato = 0; noteSpeed = noteSpeed / CVarGetInteger("gOcarinaGameNoteSpeed", 1);
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].tone = 0;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].noteIdx = rndNote;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].unk_02 = noteSpeed;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].volume = 0x50;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].vibrato = 0;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].tone = 0;
// #endregion
} else {
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].noteIdx = rndNote;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].unk_02 = 0x2D;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].volume = 0x50;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].vibrato = 0;
sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].tone = 0;
}
sOcaMinigameAppendPos++; sOcaMinigameAppendPos++;

View File

@ -1239,8 +1239,7 @@ void Actor_Init(Actor* actor, PlayState* play) {
CollisionCheck_InitInfo(&actor->colChkInfo); CollisionCheck_InitInfo(&actor->colChkInfo);
actor->floorBgId = BGCHECK_SCENE; actor->floorBgId = BGCHECK_SCENE;
ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f);
//if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
{
//Actor_SetObjectDependency(play, actor); //Actor_SetObjectDependency(play, actor);
actor->init(actor, play); actor->init(actor, play);
actor->init = NULL; actor->init = NULL;
@ -2881,11 +2880,19 @@ s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) {
if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) { if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) {
var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3; var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3;
if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 2.0f) && // #region SoH [Widescreen support]
(((arg2->y + actor->uncullZoneDownward) * var) > -2.0f) && // Doors will cull quite noticeably on wider screens. For these actors the zone is increased
(((arg2->y - actor->uncullZoneScale) * var) < 2.0f)) { f32 limit = 1.0f;
if (((actor->id == ACTOR_EN_DOOR) || (actor->id == ACTOR_DOOR_SHUTTER)) && CVarGetInteger("gIncreaseDoorUncullZones", 1)) {
limit = 2.0f;
}
if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < limit) &&
(((arg2->y + actor->uncullZoneDownward) * var) > -limit) &&
(((arg2->y - actor->uncullZoneScale) * var) < limit)) {
return true; return true;
} }
// #endregion
} }
return false; return false;
@ -3149,6 +3156,9 @@ void Actor_FreeOverlay(ActorDBEntry* dbEntry) {
osSyncPrintf(VT_RST); osSyncPrintf(VT_RST);
} }
// SoH: Flag to check if actors are being spawned from the actor entry list
// This flag is checked against to allow actors which dont have an objectBankIndex in the objectCtx slot/status array to spawn
// An example of what this fixes, is that it allows hookshot to be used as child
int gMapLoading = 0; int gMapLoading = 0;
Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ, Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ,

View File

@ -1902,7 +1902,7 @@ s32 BgCheck_CheckWallImpl(CollisionContext* colCtx, u16 xpFlags, Vec3f* posResul
s32 bgId2; s32 bgId2;
f32 nx, ny, nz; // unit normal of polygon f32 nx, ny, nz; // unit normal of polygon
if (CVarGetInteger("gNoClip", 0) != 0) { if (CVarGetInteger("gNoClip", 0) && actor != NULL && actor->id == ACTOR_PLAYER) {
return false; return false;
} }

View File

@ -7887,7 +7887,7 @@ s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 flags) {
} }
} }
// Clear free camera if an action is performed that would move the camera (targeting, first person, talking) // Clear free look if an action is performed that would move the camera (targeting, first person, talking)
if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1 && if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1 &&
((mode >= CAM_MODE_TARGET && mode <= CAM_MODE_BATTLE) || ((mode >= CAM_MODE_TARGET && mode <= CAM_MODE_BATTLE) ||
(mode >= CAM_MODE_FIRSTPERSON && mode <= CAM_MODE_CLIMBZ) || mode == CAM_MODE_HANGZ || (mode >= CAM_MODE_FIRSTPERSON && mode <= CAM_MODE_CLIMBZ) || mode == CAM_MODE_HANGZ ||

View File

@ -524,7 +524,6 @@ void Map_Init(PlayState* play) {
interfaceCtx->unk_25A = -1; interfaceCtx->unk_25A = -1;
interfaceCtx->mapSegment = GAMESTATE_ALLOC_MC(&play->state, 2 * sizeof(char*)); interfaceCtx->mapSegment = GAMESTATE_ALLOC_MC(&play->state, 2 * sizeof(char*));
interfaceCtx->mapSegmentName = GAMESTATE_ALLOC_MC(&play->state, 2 * sizeof(char*));
// " texture initialization scene_data_ID=%d mapSegment=%x" // " texture initialization scene_data_ID=%d mapSegment=%x"
osSyncPrintf("\n\n\n テクスチャ初期化 scene_data_ID=%d\nmapSegment=%x\n\n", play->sceneNum, osSyncPrintf("\n\n\n テクスチャ初期化 scene_data_ID=%d\nmapSegment=%x\n\n", play->sceneNum,
interfaceCtx->mapSegment, play); interfaceCtx->mapSegment, play);

View File

@ -3361,8 +3361,13 @@ void Message_Update(PlayState* play) {
} }
if ((s32)(gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000) { if ((s32)(gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000) {
gSaveContext.inventory.questItems ^= 0x40000000; gSaveContext.inventory.questItems ^= 0x40000000;
gSaveContext.healthCapacity += 0x10; if (!CVarGetInteger("gHurtContainer", 0)) {
gSaveContext.health += 0x10; gSaveContext.healthCapacity += 0x10;
gSaveContext.health += 0x10;
} else {
gSaveContext.healthCapacity -= 0x10;
gSaveContext.health -= 0x10;
}
} }
if (msgCtx->ocarinaAction != OCARINA_ACTION_CHECK_NOWARP_DONE) { if (msgCtx->ocarinaAction != OCARINA_ACTION_CHECK_NOWARP_DONE) {
if (sLastPlayedSong == OCARINA_SONG_SARIAS) { if (sLastPlayedSong == OCARINA_SONG_SARIAS) {

View File

@ -70,6 +70,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
f32 tempRand; f32 tempRand;
Unique9OnePointCs* csInfo = ONEPOINT_CS_INFO(csCam); Unique9OnePointCs* csInfo = ONEPOINT_CS_INFO(csCam);
// #region SOH [Enhancement]
//the default is 90, lower values necessary to prevent camera swing as animation speeds up
s16 camCrawlTemp = CVarGetInteger("gCrawlSpeed", 1);
s16 camCrawlTimer = D_8012042C / camCrawlTemp;
// #endregion
switch (csId) { switch (csId) {
case 1020: case 1020:
if (timer < 20) { if (timer < 20) {
@ -330,13 +336,26 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
case 9601: case 9601:
Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3);
Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting);
OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120398); if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, camCrawlTimer, D_80120308, D_80120398);
} else {
OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120398);
}
break; break;
case 9602: case 9602:
Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); // #region SOH [Enhancement]
Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120434); Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3);
break; Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting);
OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, camCrawlTimer, D_80120308, D_80120434);
break;
// #endregion
} else {
Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3);
Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting);
OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120434);
break;
}
case 4175: case 4175:
csInfo->keyFrames = D_8012147C; csInfo->keyFrames = D_8012147C;
csInfo->keyFrameCnt = 4; csInfo->keyFrameCnt = 4;

View File

@ -2278,8 +2278,13 @@ u8 Item_Give(PlayState* play, u8 item) {
gSaveContext.sohStats.heartPieces++; gSaveContext.sohStats.heartPieces++;
return Return_Item(item, MOD_NONE, ITEM_NONE); return Return_Item(item, MOD_NONE, ITEM_NONE);
} else if (item == ITEM_HEART_CONTAINER) { } else if (item == ITEM_HEART_CONTAINER) {
gSaveContext.healthCapacity += 0x10; if (!CVarGetInteger("gHurtContainer", 0)) {
gSaveContext.health += 0x10; gSaveContext.healthCapacity += 0x10;
gSaveContext.health += 0x10;
} else {
gSaveContext.healthCapacity -= 0x10;
gSaveContext.health -= 0x10;
}
gSaveContext.sohStats.heartContainers++; gSaveContext.sohStats.heartContainers++;
return Return_Item(item, MOD_NONE, ITEM_NONE); return Return_Item(item, MOD_NONE, ITEM_NONE);
} else if (item == ITEM_HEART) { } else if (item == ITEM_HEART) {

View File

@ -600,13 +600,23 @@ void Player_SetModelsForHoldingShield(Player* this) {
if ((CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || if ((CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) ||
!Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) { !Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) {
this->rightHandType = PLAYER_MODELTYPE_RH_SHIELD; this->rightHandType = PLAYER_MODELTYPE_RH_SHIELD;
this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][gSaveContext.linkAge]; if (LINK_IS_CHILD && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_MIRROR)) {
this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][0];
} else if (LINK_IS_ADULT && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_DEKU)) {
this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][1];
} else {
this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][gSaveContext.linkAge];
}
if (this->sheathType == PLAYER_MODELTYPE_SHEATH_18) { if (this->sheathType == PLAYER_MODELTYPE_SHEATH_18) {
this->sheathType = PLAYER_MODELTYPE_SHEATH_16; this->sheathType = PLAYER_MODELTYPE_SHEATH_16;
} else if (this->sheathType == PLAYER_MODELTYPE_SHEATH_19) { } else if (this->sheathType == PLAYER_MODELTYPE_SHEATH_19) {
this->sheathType = PLAYER_MODELTYPE_SHEATH_17; this->sheathType = PLAYER_MODELTYPE_SHEATH_17;
} }
this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge]; this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge];
if ((CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_CHILD &&
gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI) {
this->sheathDLists = &sPlayerDListGroups[this->sheathType][0];
}
this->modelAnimType = PLAYER_ANIMTYPE_2; this->modelAnimType = PLAYER_ANIMTYPE_2;
this->itemAction = -1; this->itemAction = -1;
} }
@ -618,11 +628,39 @@ void Player_SetModels(Player* this, s32 modelGroup) {
this->leftHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_LEFT_HAND]; this->leftHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_LEFT_HAND];
this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][gSaveContext.linkAge]; this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][gSaveContext.linkAge];
if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) {
if (LINK_IS_CHILD &&
(this->leftHandType == PLAYER_MODELTYPE_LH_HAMMER ||
((this->leftHandType == PLAYER_MODELTYPE_LH_SWORD || this->leftHandType == PLAYER_MODELTYPE_LH_BGS) &&
(gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)))) {
this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][0];
}
if (LINK_IS_ADULT && (this->leftHandType == PLAYER_MODELTYPE_LH_BOOMERANG ||
(this->leftHandType == PLAYER_MODELTYPE_LH_SWORD && gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KOKIRI))) {
this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][1];
}
}
// Right hand // Right hand
this->rightHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_RIGHT_HAND]; this->rightHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_RIGHT_HAND];
this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][gSaveContext.linkAge]; this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][gSaveContext.linkAge];
if (CVarGetInteger("gBowSlingShotAmmoFix", 0) && this->rightHandType == 11) { // If holding Bow/Slingshot this->rightHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_RIGHT_HAND];
this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][gSaveContext.linkAge];
if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) {
if (LINK_IS_CHILD &&
(this->rightHandType == PLAYER_MODELTYPE_RH_HOOKSHOT ||
(this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD && this->currentShield == PLAYER_SHIELD_MIRROR))) {
this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][0];
}
if (LINK_IS_ADULT &&
(this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD && this->currentShield == PLAYER_SHIELD_DEKU)) {
this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][1];
}
}
if ((CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && this->rightHandType == 11) { // If holding Bow/Slingshot
this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][Player_HoldsSlingshot(this)]; this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][Player_HoldsSlingshot(this)];
} }
@ -630,6 +668,23 @@ void Player_SetModels(Player* this, s32 modelGroup) {
this->sheathType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_SHEATH]; this->sheathType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_SHEATH];
this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge]; this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge];
if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) {
if (LINK_IS_CHILD &&
(this->currentShield == PLAYER_SHIELD_HYLIAN || this->currentShield == PLAYER_SHIELD_MIRROR) &&
((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER) ||
(gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS))) {
this->sheathDLists = &sPlayerDListGroups[this->sheathType][0];
} else if (LINK_IS_CHILD && this->currentShield == PLAYER_SHIELD_MIRROR && gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KOKIRI &&
this->sheathType == PLAYER_MODELTYPE_SHEATH_18) {
this->sheathDLists = &sPlayerDListGroups[this->sheathType][0];
} else if (LINK_IS_ADULT && this->currentShield == PLAYER_SHIELD_DEKU) {
this->sheathDLists = &sPlayerDListGroups[this->sheathType][1];
} else if (LINK_IS_CHILD && this->sheathType == PLAYER_MODELTYPE_SHEATH_17 &&
((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER) || (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS))) {
this->sheathDLists = &sPlayerDListGroups[this->sheathType][0];
}
}
// Waist // Waist
this->waistDLists = &sPlayerDListGroups[gPlayerModelTypes[modelGroup][4]][gSaveContext.linkAge]; this->waistDLists = &sPlayerDListGroups[gPlayerModelTypes[modelGroup][4]][gSaveContext.linkAge];
@ -1188,6 +1243,42 @@ void func_8008F87C(PlayState* play, Player* this, SkelAnime* skelAnime, Vec3f* p
s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
Player* this = (Player*)thisx; Player* this = (Player*)thisx;
if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0) && CVarGetInteger("gEnhancements.ScaleAdultEquimentAsChild", 0) && LINK_IS_CHILD) {
if (limbIndex == PLAYER_LIMB_L_HAND) {
if ((gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI && sLeftHandType == PLAYER_MODELTYPE_LH_SWORD) ||
(sLeftHandType == PLAYER_MODELTYPE_LH_BGS) || (sLeftHandType == PLAYER_MODELTYPE_LH_HAMMER)) {
Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY);
}
}
if (limbIndex == PLAYER_LIMB_R_HAND) {
if ((this->currentShield == PLAYER_SHIELD_MIRROR && sRightHandType == PLAYER_MODELTYPE_RH_SHIELD) ||
(this->currentShield == PLAYER_SHIELD_HYLIAN && (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER ||
gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS)) || (sRightHandType == PLAYER_MODELTYPE_RH_HOOKSHOT) ||
(sRightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT && Player_HoldsBow(this))) {
Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY);
}
}
if (limbIndex == PLAYER_LIMB_SHEATH) {
if ((this->currentShield == PLAYER_SHIELD_MIRROR ||
(this->currentShield == PLAYER_SHIELD_HYLIAN &&
(gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER ||
gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS))) &&
((this->sheathType == PLAYER_MODELTYPE_SHEATH_16) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_17) ||
(this->sheathType == PLAYER_MODELTYPE_SHEATH_18) ||
(this->sheathType == PLAYER_MODELTYPE_SHEATH_19))) {
Matrix_Translate(218, -100, 62, MTXMODE_APPLY);
Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY);
}
if ((this->currentShield == PLAYER_SHIELD_DEKU &&
gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI &&
(this->sheathType == PLAYER_MODELTYPE_SHEATH_16 ||
this->sheathType == PLAYER_MODELTYPE_SHEATH_17))) {
Matrix_Translate(218, -100, 62, MTXMODE_APPLY);
Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY);
}
}
}
if (limbIndex == PLAYER_LIMB_ROOT) { if (limbIndex == PLAYER_LIMB_ROOT) {
sLeftHandType = this->leftHandType; sLeftHandType = this->leftHandType;
sRightHandType = this->rightHandType; sRightHandType = this->rightHandType;
@ -1305,9 +1396,11 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx**
(gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) { (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) {
dLists += PLAYER_SHIELD_MAX * 4; dLists += PLAYER_SHIELD_MAX * 4;
} }
} else if (!LINK_IS_ADULT && ((this->sheathType == PLAYER_MODELTYPE_SHEATH_16) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_17)) && } else if (!CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) {
(gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) { if (!LINK_IS_ADULT && ((this->sheathType == PLAYER_MODELTYPE_SHEATH_16) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_17)) &&
dLists = &sSheathWithSwordDLs[PLAYER_SHIELD_MAX * 4]; (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) {
dLists = &sSheathWithSwordDLs[PLAYER_SHIELD_MAX * 4];
}
} }
if (dLists[sDListsLodOffset] != NULL) { if (dLists[sDListsLodOffset] != NULL) {
@ -1345,7 +1438,7 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G
*dList = sFirstPersonLeftForearmDLs[gSaveContext.linkAge]; *dList = sFirstPersonLeftForearmDLs[gSaveContext.linkAge];
} else if (limbIndex == PLAYER_LIMB_L_HAND) { } else if (limbIndex == PLAYER_LIMB_L_HAND) {
s32 handOutDlIndex = gSaveContext.linkAge; s32 handOutDlIndex = gSaveContext.linkAge;
if (CVarGetInteger("gBowSlingShotAmmoFix", 0) && LINK_IS_ADULT && Player_HoldsSlingshot(this)) { if ((CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_ADULT && Player_HoldsSlingshot(this)) {
handOutDlIndex = 1; handOutDlIndex = 1;
} }
*dList = sFirstPersonLeftHandDLs[handOutDlIndex]; *dList = sFirstPersonLeftHandDLs[handOutDlIndex];
@ -1355,7 +1448,7 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G
*dList = sFirstPersonForearmDLs[gSaveContext.linkAge]; *dList = sFirstPersonForearmDLs[gSaveContext.linkAge];
} else if (limbIndex == PLAYER_LIMB_R_HAND) { } else if (limbIndex == PLAYER_LIMB_R_HAND) {
s32 firstPersonWeaponIndex = gSaveContext.linkAge; s32 firstPersonWeaponIndex = gSaveContext.linkAge;
if (CVarGetInteger("gBowSlingShotAmmoFix", 0)) { if (CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) {
if (Player_HoldsBow(this)) { if (Player_HoldsBow(this)) {
firstPersonWeaponIndex = 0; firstPersonWeaponIndex = 0;
} else if (Player_HoldsSlingshot(this)) { } else if (Player_HoldsSlingshot(this)) {
@ -1755,7 +1848,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve
Matrix_Get(&this->shieldMf); Matrix_Get(&this->shieldMf);
} else if ((this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT) || (this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT_2)) { } else if ((this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT) || (this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT_2)) {
s32 stringModelToUse = gSaveContext.linkAge; s32 stringModelToUse = gSaveContext.linkAge;
if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){ if (CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) {
stringModelToUse = Player_HoldsSlingshot(this); stringModelToUse = Player_HoldsSlingshot(this);
} }
BowStringData* stringData = &sBowStringData[stringModelToUse]; BowStringData* stringData = &sBowStringData[stringModelToUse];

View File

@ -83,9 +83,10 @@ void Object_UpdateBank(ObjectContext* objectCtx) {
RomFile* objectFile; RomFile* objectFile;
size_t size; size_t size;
/*
for (i = 0; i < objectCtx->num; i++) { for (i = 0; i < objectCtx->num; i++) {
if (status->id < 0) { if (status->id < 0) {
/*
if (status->dmaRequest.vromAddr == 0) { if (status->dmaRequest.vromAddr == 0) {
osCreateMesgQueue(&status->loadQueue, &status->loadMsg, 1); osCreateMesgQueue(&status->loadQueue, &status->loadMsg, 1);
objectFile = &gObjectTable[-status->id]; objectFile = &gObjectTable[-status->id];
@ -96,10 +97,12 @@ void Object_UpdateBank(ObjectContext* objectCtx) {
} else if (!osRecvMesg(&status->loadQueue, NULL, OS_MESG_NOBLOCK)) { } else if (!osRecvMesg(&status->loadQueue, NULL, OS_MESG_NOBLOCK)) {
status->id = -status->id; status->id = -status->id;
} }
*/
status->id = -status->id;
} }
status++; status++;
} }
*/
} }
s32 Object_GetIndex(ObjectContext* objectCtx, s16 objectId) { s32 Object_GetIndex(ObjectContext* objectCtx, s16 objectId) {

View File

@ -10,10 +10,6 @@
#include <stdlib.h> // malloc #include <stdlib.h> // malloc
#include <string.h> // memcpy #include <string.h> // memcpy
// OTRTODO: Replace usage of this method when we can clear the cache
// for a single texture without the need of a DL opcode in the render code
void gfx_texture_cache_clear();
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
#define LAVA_TEX_WIDTH 32 #define LAVA_TEX_WIDTH 32
@ -123,7 +119,9 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() {
sMaskTexLava[i] = maskVal; sMaskTexLava[i] = maskVal;
} }
} }
Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, NULL); Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, NULL);
Gfx_TextureCacheDelete(sMaskTexLava);
return; return;
} }
@ -165,7 +163,9 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() {
} }
} }
gfx_texture_cache_clear(); Gfx_TextureCacheDelete(sMaskTexLava);
Gfx_TextureCacheDelete(sLavaWavyTex);
Gfx_TextureCacheDelete(sLavaFloorModifiedTex);
} }
void func_808C12C4(u8* arg1, s16 arg2) { void func_808C12C4(u8* arg1, s16 arg2) {
@ -228,6 +228,7 @@ void func_808C1554_Raw(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
} }
free(sp54); free(sp54);
Gfx_TextureCacheDelete(sLavaWavyTexRaw);
} }
// Modified to support CPU modified texture with the resource system // Modified to support CPU modified texture with the resource system
@ -255,6 +256,8 @@ void func_808C1554(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
temp_s3[i + temp2] = sp54[i + i2]; temp_s3[i + temp2] = sp54[i + i2];
} }
} }
Gfx_TextureCacheDelete(sLavaWavyTex);
} }
void func_808C17C8(PlayState* play, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, f32 arg4, s16 arg5) { void func_808C17C8(PlayState* play, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, f32 arg4, s16 arg5) {
@ -373,6 +376,13 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) {
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016990, sMaskTex32x16, NULL); Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016990, sMaskTex32x16, NULL);
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016E10, sMaskTex32x16, NULL); Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016E10, sMaskTex32x16, NULL);
// Clear cache for masks
Gfx_TextureCacheDelete(sMaskTex8x16);
Gfx_TextureCacheDelete(sMaskTex8x32);
Gfx_TextureCacheDelete(sMaskTex16x16);
Gfx_TextureCacheDelete(sMaskTex16x32);
Gfx_TextureCacheDelete(sMaskTex32x16);
BossDodongo_RegisterBlendedLavaTextureUpdate(); BossDodongo_RegisterBlendedLavaTextureUpdate();
// Register alt listener to update the blended lava for the replacement texture based on alt path // Register alt listener to update the blended lava for the replacement texture based on alt path
@ -1206,6 +1216,7 @@ void BossDodongo_Update(Actor* thisx, PlayState* play2) {
} }
} else { } else {
sMaskTexLava[new_var] = 1; sMaskTexLava[new_var] = 1;
Gfx_TextureCacheDelete(sMaskTexLava);
} }
this->unk_1C2 += 37; this->unk_1C2 += 37;
@ -1345,18 +1356,6 @@ void BossDodongo_Draw(Actor* thisx, PlayState* play) {
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTex32x16); gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTex32x16);
} }
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTexLava);
// Using WORK_DISP to invalidate these textures as they are used in drawing the scene textures which happens
// before actors are drawn. WORK_DISP comes before POLAY_OPA_DISP. It is probably not meant for this, but it
// at least works for now.
// Alternatively, having a way to invalidate just these pointers from the Update func should be sufficient.
if (sLavaFloorModifiedTexRaw != NULL) {
gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTexRaw);
} else {
gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTex);
}
if ((this->unk_1C0 >= 2) && (this->unk_1C0 & 1)) { if ((this->unk_1C0 >= 2) && (this->unk_1C0 & 1)) {
POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 255, 255, 0, 900, 1099); POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 255, 255, 0, 900, 1099);
} else { } else {

View File

@ -192,11 +192,11 @@ void DemoGj_Explode(DemoGj* this, PlayState* play, Vec3f* initialPos, Vec3f* dir
phi_s0 = 0x21; phi_s0 = 0x21;
} }
Gfx* gfx = ResourceMgr_LoadGfxByName(gGanonRubbleDL); // SoH [Port] Changed from &gGanonsCastleRubbleAroundArenaDL[28] to gGanonRubbleDL as it seems this was an error in the original rom/decomp
// Other calls to EffectSsKakera_Spawn with OBJECT_GEFF use gGanonRubbleDL, so this change is to match that
EffectSsKakera_Spawn(play, &explosionPos, &velocity, initialPos, -200, phi_s0, 10, 10, 0, EffectSsKakera_Spawn(play, &explosionPos, &velocity, initialPos, -200, phi_s0, 10, 10, 0,
Rand_ZeroOne() * 20.0f + 20.0f, 20, 300, (s32)(Rand_ZeroOne() * 30.0f) + 30, -1, Rand_ZeroOne() * 20.0f + 20.0f, 20, 300, (s32)(Rand_ZeroOne() * 30.0f) + 30, -1,
OBJECT_GEFF, gfx); OBJECT_GEFF, gGanonRubbleDL);
theta += 0x2AAA; theta += 0x2AAA;
} }

View File

@ -101,6 +101,9 @@ void EnDntJiji_Destroy(Actor* thisx, PlayState* play) {
} }
void EnDntJiji_SetFlower(EnDntJiji* this, PlayState* play) { void EnDntJiji_SetFlower(EnDntJiji* this, PlayState* play) {
// SOH: Due to removed object dependencies, parent was still NULL when Init was called. In order to properly set
// stage, redo it here now that we are a frame later.
this->stage = (EnDntDemo*)this->actor.parent;
if (this->actor.bgCheckFlags & 1) { if (this->actor.bgCheckFlags & 1) {
this->flowerPos = this->actor.world.pos; this->flowerPos = this->actor.world.pos;
this->actionFunc = EnDntJiji_SetupWait; this->actionFunc = EnDntJiji_SetupWait;

View File

@ -349,7 +349,15 @@ void EnDoor_Draw(Actor* thisx, PlayState* play) {
} }
} }
if (this->lockTimer != 0) { if (this->lockTimer != 0) {
if (CVarGetInteger("gShowDoorLocksOnBothSides", 0)) {
Matrix_Push();
}
Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL); Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL);
if (CVarGetInteger("gShowDoorLocksOnBothSides", 0)) {
Matrix_Pop();
Matrix_RotateZYX(0, 0x8000, 0, MTXMODE_APPLY);
Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL);
}
} }
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);

View File

@ -1027,8 +1027,8 @@ void EnGirlA_BuyEvent_ObtainBombchuPack(PlayState* play, EnGirlA* this) {
Rupees_ChangeBy(-this->basePrice); Rupees_ChangeBy(-this->basePrice);
// Normally, buying a bombchu pack sets a flag indicating the pack is now sold out // Normally, buying a bombchu pack sets a flag indicating the pack is now sold out
// If they're in logic for rando, skip setting that flag so they can be purchased repeatedly // If we're in rando, skip setting that flag so they can be purchased repeatedly
if (IS_RANDO && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { if (IS_RANDO) {
return; return;
} }
@ -1255,8 +1255,7 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play) {
this->itemGiveFunc = itemEntry->itemGiveFunc; this->itemGiveFunc = itemEntry->itemGiveFunc;
this->buyEventFunc = itemEntry->buyEventFunc; this->buyEventFunc = itemEntry->buyEventFunc;
// If chus are in logic, make the 10 pack affordable without a wallet upgrade // If chus are in logic, make the 10 pack affordable without a wallet upgrade
if (IS_RANDO && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && if (IS_RANDO && this->getItemId == GI_BOMBCHUS_10) {
this->getItemId == GI_BOMBCHUS_10) {
this->basePrice = 99; this->basePrice = 99;
} else { } else {
this->basePrice = itemEntry->price; this->basePrice = itemEntry->price;

View File

@ -8,6 +8,8 @@
#include "objects/object_tite/object_tite.h" #include "objects/object_tite/object_tite.h"
#include "objects/object_ik/object_ik.h" #include "objects/object_ik/object_ik.h"
#include <string.h> // strcmp
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
void EnPart_Init(Actor* thisx, PlayState* play); void EnPart_Init(Actor* thisx, PlayState* play);
@ -297,11 +299,11 @@ void EnPart_Draw(Actor* thisx, PlayState* play) {
gSPSegment(POLY_OPA_DISP++, 0x08, func_80ACEAC0(play->state.gfxCtx, 255, 255, 255, 180, 180, 180)); gSPSegment(POLY_OPA_DISP++, 0x08, func_80ACEAC0(play->state.gfxCtx, 255, 255, 255, 180, 180, 180));
gSPSegment(POLY_OPA_DISP++, 0x09, func_80ACEAC0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); gSPSegment(POLY_OPA_DISP++, 0x09, func_80ACEAC0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0));
gSPSegment(POLY_OPA_DISP++, 0x0A, func_80ACEAC0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); gSPSegment(POLY_OPA_DISP++, 0x0A, func_80ACEAC0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0));
} else if ((thisx->params == 9) && (this->displayList == ResourceMgr_LoadGfxByName(object_tite_DL_002FF0))) { } else if ((thisx->params == 9) && (strcmp((const char*)this->displayList, object_tite_DL_002FF0) == 0)) {
gSPSegment(POLY_OPA_DISP++, 0x08, object_tite_Tex_001300); gSPSegment(POLY_OPA_DISP++, 0x08, object_tite_Tex_001300);
gSPSegment(POLY_OPA_DISP++, 0x09, object_tite_Tex_001700); gSPSegment(POLY_OPA_DISP++, 0x09, object_tite_Tex_001700);
gSPSegment(POLY_OPA_DISP++, 0x0A, object_tite_Tex_001900); gSPSegment(POLY_OPA_DISP++, 0x0A, object_tite_Tex_001900);
} else if ((thisx->params == 10) && (this->displayList == ResourceMgr_LoadGfxByName(object_tite_DL_002FF0))) { } else if ((thisx->params == 10) && (strcmp((const char*)this->displayList, object_tite_DL_002FF0) == 0)) {
gSPSegment(POLY_OPA_DISP++, 0x08, object_tite_Tex_001B00); gSPSegment(POLY_OPA_DISP++, 0x08, object_tite_Tex_001B00);
gSPSegment(POLY_OPA_DISP++, 0x09, object_tite_Tex_001F00); gSPSegment(POLY_OPA_DISP++, 0x09, object_tite_Tex_001F00);
gSPSegment(POLY_OPA_DISP++, 0x0A, object_tite_Tex_002100); gSPSegment(POLY_OPA_DISP++, 0x0A, object_tite_Tex_002100);

View File

@ -745,6 +745,28 @@ void EnPartner_Update(Actor* thisx, PlayState* play) {
CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
} }
if (CVarGetInteger("gCosmetics.Ivan_IdlePrimary.Changed", 0)) {
Color_RGB8 ivanColor1 = CVarGetColor24("gCosmetics.Ivan_IdlePrimary.Value", (Color_RGB8){ 255, 255, 255 });
this->innerColor.r = ivanColor1.r;
this->innerColor.g = ivanColor1.g;
this->innerColor.b = ivanColor1.b;
} else {
this->innerColor.r = 255;
this->innerColor.g = 255;
this->innerColor.b = 255;
}
if (CVarGetInteger("gCosmetics.Ivan_IdleSecondary.Changed", 0)) {
Color_RGB8 ivanColor2 = CVarGetColor24("gCosmetics.Ivan_IdleSecondary.Value", (Color_RGB8){ 0, 255, 0 });
this->outerColor.r = ivanColor2.r;
this->outerColor.g = ivanColor2.g;
this->outerColor.b = ivanColor2.b;
} else {
this->outerColor.r = 0;
this->outerColor.g = 255;
this->outerColor.b = 0;
}
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
EnPartner_UpdateLights(this, play); EnPartner_UpdateLights(this, play);

View File

@ -821,19 +821,6 @@ void func_80AF3F20(EnRu2* this, PlayState* play) {
void EnRu2_Draw(Actor* thisx, PlayState* play) { void EnRu2_Draw(Actor* thisx, PlayState* play) {
EnRu2* this = (EnRu2*)thisx; EnRu2* this = (EnRu2*)thisx;
// 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 diffrent 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.
Gfx* gfx = ResourceMgr_LoadGfxByName(gAdultRutoHeadDL);
Gfx patch = gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, COMBINED, TEXEL0, 0,
PRIM_LOD_FRAC, COMBINED);
gfx[0xA2] = patch;
if ((this->drawConfig < 0) || (this->drawConfig >= ARRAY_COUNT(sDrawFuncs)) || if ((this->drawConfig < 0) || (this->drawConfig >= ARRAY_COUNT(sDrawFuncs)) ||
(sDrawFuncs[this->drawConfig] == 0)) { (sDrawFuncs[this->drawConfig] == 0)) {
// "Draw Mode is improper!" // "Draw Mode is improper!"

View File

@ -1412,12 +1412,20 @@ void EnSkj_StartOcarinaMinigame(EnSkj* this, PlayState* play) {
EnSkj_TurnPlayer(this, player); EnSkj_TurnPlayer(this, player);
if (dialogState == TEXT_STATE_CLOSING) { if (dialogState == TEXT_STATE_CLOSING) {
func_8010BD58(play, OCARINA_ACTION_MEMORY_GAME); // #region SOH [Enhancement]
if (sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid != NULL) { if (CVarGetInteger("gInstantOcarinaGameWin", 0) && CVarGetInteger("gCustomizeOcarinaGame", 0)) {
sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid->minigameState = SKULL_KID_OCARINA_PLAY_NOTES; play->msgCtx.ocarinaMode = OCARINA_MODE_0F;
this->songFailTimer = 160;
this->actionFunc = EnSkj_WaitForPlayback;
// #endregion
} else {
func_8010BD58(play, OCARINA_ACTION_MEMORY_GAME);
if (sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid != NULL) {
sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid->minigameState = SKULL_KID_OCARINA_PLAY_NOTES;
this->songFailTimer = 160;
this->actionFunc = EnSkj_WaitForPlayback;
}
} }
this->songFailTimer = 160;
this->actionFunc = EnSkj_WaitForPlayback;
} }
} }
@ -1466,7 +1474,14 @@ void EnSkj_WaitForPlayback(EnSkj* this, PlayState* play) {
break; break;
case MSGMODE_MEMORY_GAME_PLAYER_PLAYING: case MSGMODE_MEMORY_GAME_PLAYER_PLAYING:
if (this->songFailTimer != 0) { if (this->songFailTimer != 0) {
this->songFailTimer--; // #region SOH [Enhancement]
if (CVarGetInteger("gOcarinaUnlimitedFailTime", 0) == 1 &&
CVarGetInteger("gCustomizeOcarinaGame", 0) == 1) {
// don't decrement timer
// #endregion
} else {
this->songFailTimer--;
}
} else { // took too long, game failed } else { // took too long, game failed
func_80078884(NA_SE_SY_OCARINA_ERROR); func_80078884(NA_SE_SY_OCARINA_ERROR);
Message_CloseTextbox(play); Message_CloseTextbox(play);

View File

@ -5174,6 +5174,37 @@ static Vec3s sSinkingLureLocationPos[] = {
{ 553, -48, -508 }, { 553, -48, -508 },
}; };
// #region SOH [Enhancement]
void Fishing_QuitAtDoor(Fishing* this, PlayState* play) {
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play);
switch (play->msgCtx.choiceIndex) {
case 0:
if (D_80B7E084 == 0) {
Message_ContinueTextbox(play, 0x4085);
} else if (sLinkAge == 1) {
Message_ContinueTextbox(play, 0x4092);
}
if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE_FADING) {
if (D_80B7A68C != 0) {
D_80B7A688 = 1;
D_80B7A68C = 0;
}
D_80B7E0AC = 0;
play->interfaceCtx.unk_260 = 0;
}
break;
case 1:
func_800A9F6C(0.0f, 150, 10, 10);
break;
}
}
}
// #endregion
void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
PlayState* play = play2; PlayState* play = play2;
Fishing* this = (Fishing*)thisx; Fishing* this = (Fishing*)thisx;
@ -5481,6 +5512,12 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
player->actor.world.pos.z = 1360.0f; player->actor.world.pos.z = 1360.0f;
player->actor.speedXZ = 0.0f; player->actor.speedXZ = 0.0f;
// #region SOH [Enhancement]
if (CVarGetInteger("gQuitFishingAtDoor", 0)) {
Fishing_QuitAtDoor(this, play);
}
// #endregion
if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) {
Camera* camera = Play_GetCamera(play, MAIN_CAM); Camera* camera = Play_GetCamera(play, MAIN_CAM);

View File

@ -2911,7 +2911,11 @@ s32 func_808356E8(Player* this, PlayState* play) {
} }
void func_808357E8(Player* this, Gfx** dLists) { void func_808357E8(Player* this, Gfx** dLists) {
this->leftHandDLists = &dLists[gSaveContext.linkAge]; if (LINK_IS_ADULT && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0))) {
this->leftHandDLists = &dLists[1];
} else {
this->leftHandDLists = &dLists[gSaveContext.linkAge];
}
} }
s32 func_80835800(Player* this, PlayState* play) { s32 func_80835800(Player* this, PlayState* play) {
@ -6982,9 +6986,19 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall
this->actor.world.pos.z = zVertex1 + (distToInteractWall * wallPolyNormZ); this->actor.world.pos.z = zVertex1 + (distToInteractWall * wallPolyNormZ);
func_80832224(this); func_80832224(this);
this->actor.prevPos = this->actor.world.pos; this->actor.prevPos = this->actor.world.pos;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start); // #region SOH [Enhancement]
Player_AnimReplaceApplyFlags(play, this, 0x9D); if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
// increase animation speed when entering a tunnel
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start,
((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f,
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), ANIMMODE_ONCE,
0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
// #endregion
} else {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
}
return true; return true;
} }
} }
@ -7065,16 +7079,39 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) {
if (this->linearVelocity > 0.0f) { if (this->linearVelocity > 0.0f) {
this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; this->actor.shape.rot.y = this->actor.wallYaw + 0x8000;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end); // #region SOH [Enhancement]
Player_AnimReplaceApplyFlags(play, this, 0x9D); if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM); // animation when exiting a tunnel forward
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_end,
((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f,
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_end), ANIMMODE_ONCE,
0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM);
// #endregion
} else {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM);
}
} else { } else {
this->actor.shape.rot.y = this->actor.wallYaw; this->actor.shape.rot.y = this->actor.wallYaw;
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, -1.0f, // #region SOH [Enhancement]
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, // animation when exiting a tunnel backward
0.0f); if (CVarGetInteger("gCrawlSpeed",1) > 1) {
Player_AnimReplaceApplyFlags(play, this, 0x9D); LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start,
OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM); -1.0f * ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f),
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM);
// #endregion
}
else {
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, -1.0f,
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM);
}
} }
this->currentYaw = this->actor.shape.rot.y; this->currentYaw = this->actor.shape.rot.y;
@ -11927,6 +11964,68 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) {
f32 temp1; f32 temp1;
f32 temp2; f32 temp2;
// #region SOH [Enhancement]
f32 swimMod = 1.0f;
if (CVarGetInteger("gEnableWalkModify", 0) == 1) {
if (CVarGetInteger("gWalkSpeedToggle", 0) == 1) {
if (gWalkSpeedToggle1) {
swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f);
} else if (gWalkSpeedToggle2) {
swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f);
}
} else {
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) {
swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f);
} else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) {
swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f);
}
}
temp1 = this->skelAnime.curFrame - 10.0f;
temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f * swimMod;
if (*arg1 > temp2) {
*arg1 = temp2;
}
if ((0.0f < temp1) && (temp1 < 10.0f)) {
temp1 *= 6.0f;
} else {
temp1 = 0.0f;
arg2 = 0.0f;
}
Math_AsymStepToF(arg1, arg2 * 0.8f * swimMod, temp1, (fabsf(*arg1) * 0.02f) + 0.05f);
Math_ScaledStepToS(&this->currentYaw, arg3, 1600);
// #endregion
} else {
temp1 = this->skelAnime.curFrame - 10.0f;
temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f;
if (*arg1 > temp2) {
*arg1 = temp2;
}
if ((0.0f < temp1) && (temp1 < 10.0f)) {
temp1 *= 6.0f;
} else {
temp1 = 0.0f;
arg2 = 0.0f;
}
Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f);
Math_ScaledStepToS(&this->currentYaw, arg3, 1600);
}
}
// #region SOH [Enhancement]
//Diving uses function func_8084AEEC to calculate changes both xz and y velocity (via func_8084DBC4)
//Provide original calculation for y velocity when swim speed mod is active
void SurfaceWithoutSwimMod(Player* this, f32* arg1, f32 arg2, s16 arg3) {
f32 temp1;
f32 temp2;
temp1 = this->skelAnime.curFrame - 10.0f; temp1 = this->skelAnime.curFrame - 10.0f;
temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f; temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f;
@ -11944,6 +12043,7 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) {
Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f); Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f);
Math_ScaledStepToS(&this->currentYaw, arg3, 1600); Math_ScaledStepToS(&this->currentYaw, arg3, 1600);
} }
// #endregion
void func_8084B000(Player* this) { void func_8084B000(Player* this) {
f32 phi_f18; f32 phi_f18;
@ -12562,8 +12662,15 @@ void func_8084C760(Player* this, PlayState* play) {
return; return;
} }
// player speed in a tunnel
if (!Player_TryLeavingCrawlspace(this, play)) { if (!Player_TryLeavingCrawlspace(this, play)) {
this->linearVelocity = sControlInput->rel.stick_y * 0.03f; // #region SOH [Enhancement]
if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
this->linearVelocity = sControlInput->rel.stick_y * 0.03f * CVarGetInteger("gCrawlSpeed", 1);
// #endregion
} else {
this->linearVelocity = sControlInput->rel.stick_y * 0.03f;
}
} }
} }
return; return;
@ -13098,7 +13205,14 @@ void func_8084DBC4(PlayState* play, Player* this, f32 arg2) {
Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.0f, play); Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.0f, play);
func_8084AEEC(this, &this->linearVelocity, sp2C * 0.5f, sp2A); func_8084AEEC(this, &this->linearVelocity, sp2C * 0.5f, sp2A);
func_8084AEEC(this, &this->actor.velocity.y, arg2, this->currentYaw); // Original implementation of func_8084AEEC (SurfaceWithoutSwimMod) to prevent velocity increases via swim mod which push Link into the air
// #region SOH [Enhancement]
if (CVarGetInteger("gEnableWalkModify", 0)) {
SurfaceWithoutSwimMod(this, &this->actor.velocity.y, arg2, this->currentYaw);
// #endregion
} else {
func_8084AEEC(this, &this->actor.velocity.y, arg2, this->currentYaw);
}
} }
void func_8084DC48(Player* this, PlayState* play) { void func_8084DC48(Player* this, PlayState* play) {

View File

@ -312,6 +312,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
KaleidoScope_DrawQuadTextureRGBA32(gfxCtx, gQuestIconGoldSkulltulaTex, 24, 24, 8); KaleidoScope_DrawQuadTextureRGBA32(gfxCtx, gQuestIconGoldSkulltulaTex, 24, 24, 8);
} }
// Unique index for both pulse phases
uint8_t palettePulseIdx = (mapBgPulseStage ? 40 : 20) - mapBgPulseTimer;
if ((play->sceneNum >= SCENE_DEKU_TREE) && (play->sceneNum <= SCENE_TREASURE_BOX_SHOP)) { if ((play->sceneNum >= SCENE_DEKU_TREE) && (play->sceneNum <= SCENE_TREASURE_BOX_SHOP)) {
stepR = (mapBgPulseR - mapBgPulseColors[mapBgPulseStage][0]) / mapBgPulseTimer; stepR = (mapBgPulseR - mapBgPulseColors[mapBgPulseStage][0]) / mapBgPulseTimer;
stepG = (mapBgPulseG - mapBgPulseColors[mapBgPulseStage][1]) / mapBgPulseTimer; stepG = (mapBgPulseG - mapBgPulseColors[mapBgPulseStage][1]) / mapBgPulseTimer;
@ -324,6 +327,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
interfaceCtx->mapPalette[28] = (rgba16 & 0xFF00) >> 8; interfaceCtx->mapPalette[28] = (rgba16 & 0xFF00) >> 8;
interfaceCtx->mapPalette[29] = rgba16 & 0xFF; interfaceCtx->mapPalette[29] = rgba16 & 0xFF;
interfaceCtx->mapPalettesPulse[palettePulseIdx][28] = (rgba16 & 0xFF00) >> 8;
interfaceCtx->mapPalettesPulse[palettePulseIdx][29] = rgba16 & 0xFF;
mapBgPulseTimer--; mapBgPulseTimer--;
if (mapBgPulseTimer == 0) { if (mapBgPulseTimer == 0) {
mapBgPulseStage ^= 1; mapBgPulseStage ^= 1;
@ -335,7 +341,8 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
gDPSetTextureFilter(POLY_KAL_DISP++, G_TF_POINT); gDPSetTextureFilter(POLY_KAL_DISP++, G_TF_POINT);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha);
gDPLoadTLUT_pal16(POLY_KAL_DISP++, 0, interfaceCtx->mapPalette); // Use a unique palette address per frame so the renderer/shader can cache all variations
gDPLoadTLUT_pal16(POLY_KAL_DISP++, 0, interfaceCtx->mapPalettesPulse[palettePulseIdx]);
gDPSetTextureLUT(POLY_KAL_DISP++, G_TT_RGBA16); gDPSetTextureLUT(POLY_KAL_DISP++, G_TT_RGBA16);
u8 mirroredWorld = CVarGetInteger("gMirroredWorld", 0); u8 mirroredWorld = CVarGetInteger("gMirroredWorld", 0);
@ -349,10 +356,6 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
gSPVertex(POLY_KAL_DISP++, &pauseCtx->mapPageVtx[60], 8, 0); gSPVertex(POLY_KAL_DISP++, &pauseCtx->mapPageVtx[60], 8, 0);
// The dungeon map textures are recreated each frame, so always invalidate them
gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[0]);
gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[1]);
gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_CI, MAP_48x85_TEX_WIDTH, gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_CI, MAP_48x85_TEX_WIDTH,
MAP_48x85_TEX_HEIGHT, 0, G_TX_WRAP | mirrorMode, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, MAP_48x85_TEX_HEIGHT, 0, G_TX_WRAP | mirrorMode, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);

View File

@ -1204,8 +1204,6 @@ Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, void** textures) {
return gfx; return gfx;
} }
static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT];
void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
static Color_RGB8 D_8082ACF4[12] = { static Color_RGB8 D_8082ACF4[12] = {
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 },
@ -1374,10 +1372,6 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
} }
} }
// Need to invalidate the blend mask every frame. Ideally this would be done in KaleidoScope_DrawDungeonMap
// but the reference is not shared between files
gSPInvalidateTexCache(POLY_KAL_DISP++, mapBlendMask);
if (pauseCtx->pageIndex) { // pageIndex != PAUSE_ITEM if (pauseCtx->pageIndex) { // pageIndex != PAUSE_ITEM
gDPPipeSync(OVERLAY_DISP++); gDPPipeSync(OVERLAY_DISP++);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA, G_CC_MODULATEIA); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA, G_CC_MODULATEIA);
@ -1889,11 +1883,17 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) {
gSPMatrix(POLY_KAL_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), gSPMatrix(POLY_KAL_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 90, 100, 130, 255); const Color_RGBA8 namePanelColor = CVarGetColor("gCosmetics.Kal_NamePanel.Value", (Color_RGBA8){90,100,130,255});
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, namePanelColor.r, namePanelColor.g, namePanelColor.b, namePanelColor.a);
gSPVertex(POLY_KAL_DISP++, &pauseCtx->infoPanelVtx[0], 16, 0); gSPVertex(POLY_KAL_DISP++, &pauseCtx->infoPanelVtx[0], 16, 0);
gSPDisplayList(POLY_KAL_DISP++, gItemNamePanelDL); gSPDisplayList(POLY_KAL_DISP++, gItemNamePanelDL);
if (CVarGetInteger("gUniformLR", 0) == 0) { // Restore the misplace gDPSetPrimColor
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 90, 100, 130, 255);
}
if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) && (pauseCtx->unk_1E4 == 0)) { if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) && (pauseCtx->unk_1E4 == 0)) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, D_808321A0, D_808321A2, D_808321A4, D_808321A6); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, D_808321A0, D_808321A2, D_808321A4, D_808321A6);
} else { } else {
@ -1902,6 +1902,7 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) {
} }
} }
gSPDisplayList(POLY_KAL_DISP++, gLButtonIconDL); gSPDisplayList(POLY_KAL_DISP++, gLButtonIconDL);
if (CVarGetInteger("gUniformLR", 0) == 0) { //Restore the misplace gDPSetPrimColor if (CVarGetInteger("gUniformLR", 0) == 0) { //Restore the misplace gDPSetPrimColor
@ -2311,15 +2312,15 @@ void KaleidoScope_SetView(PauseContext* pauseCtx, f32 x, f32 y, f32 z) {
func_800AAA50(&pauseCtx->view, 127); func_800AAA50(&pauseCtx->view, 127);
} }
static u8 D_8082AE48[][4] = { static u8 sPageVtxColorR[][4] = {
{ 10, 70, 70, 10 }, { 10, 90, 90, 10 }, { 80, 140, 140, 80 }, { 10, 70, 70, 10 }, { 10, 90, 90, 10 }, { 80, 140, 140, 80 },
{ 80, 120, 120, 80 }, { 80, 140, 140, 80 }, { 50, 110, 110, 50 }, { 80, 120, 120, 80 }, { 80, 140, 140, 80 }, { 50, 110, 110, 50 },
}; };
static u8 D_8082AE60[][4] = { static u8 sPageVtxColorG[][4] = {
{ 50, 100, 100, 50 }, { 50, 100, 100, 50 }, { 40, 60, 60, 40 }, { 50, 100, 100, 50 }, { 50, 100, 100, 50 }, { 40, 60, 60, 40 },
{ 80, 120, 120, 80 }, { 40, 60, 60, 40 }, { 50, 110, 110, 50 }, { 80, 120, 120, 80 }, { 40, 60, 60, 40 }, { 50, 110, 110, 50 },
}; };
static u8 D_8082AE78[][4] = { static u8 sPageVtxColorB[][4] = {
{ 80, 130, 130, 80 }, { 40, 60, 60, 40 }, { 30, 60, 60, 30 }, { 80, 130, 130, 80 }, { 40, 60, 60, 40 }, { 30, 60, 60, 30 },
{ 50, 70, 70, 50 }, { 30, 60, 60, 30 }, { 50, 110, 110, 50 }, { 50, 70, 70, 50 }, { 30, 60, 60, 30 }, { 50, 110, 110, 50 },
}; };
@ -2447,10 +2448,87 @@ static s16 D_8082B0E4[] = {
0x0019, 0x000D, 0x0001, 0x0001, 0x000D, 0x0015, 0x000F, 0x000D, 0x000C, 0x0001, 0x0000, 0x0019, 0x000D, 0x0001, 0x0001, 0x000D, 0x0015, 0x000F, 0x000D, 0x000C, 0x0001, 0x0000,
}; };
s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) { static const char* gPageVtxColorCvars[][4] = {
{
"gCosmetics.Kal_ItemSelA.Value",
"gCosmetics.Kal_ItemSelB.Value",
"gCosmetics.Kal_ItemSelC.Value",
"gCosmetics.Kal_ItemSelD.Value",
},
{
"gCosmetics.Kal_EquipSelA.Value",
"gCosmetics.Kal_EquipSelB.Value",
"gCosmetics.Kal_EquipSelC.Value",
"gCosmetics.Kal_EquipSelD.Value",
},
{
"gCosmetics.Kal_MapSelDunA.Value",
"gCosmetics.Kal_MapSelDunB.Value",
"gCosmetics.Kal_MapSelDunC.Value",
"gCosmetics.Kal_MapSelDunD.Value",
},
{
"gCosmetics.Kal_QuestStatusA.Value",
"gCosmetics.Kal_QuestStatusB.Value",
"gCosmetics.Kal_QuestStatusC.Value",
"gCosmetics.Kal_QuestStatusD.Value",
},
{
"gCosmetics.Kal_MapSelectA.Value",
"gCosmetics.Kal_MapSelectB.Value",
"gCosmetics.Kal_MapSelectC.Value",
"gCosmetics.Kal_MapSelectD.Value",
},
{
"gCosmetics.Kal_SaveA.Value",
"gCosmetics.Kal_SaveB.Value",
"gCosmetics.Kal_SaveC.Value",
"gCosmetics.Kal_SaveD.Value",
},
};
s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 pageIndex, s16 arg3) {
static s16 D_8082B110 = 0; static s16 D_8082B110 = 0;
static s16 D_8082B114 = 1; static s16 D_8082B114 = 1;
static s16 D_8082B118 = 0; static s16 D_8082B118 = 0;
static const Color_RGBA8 pageColors[][4] = {
{
{ 10, 50, 80, 255 },
{ 70, 100, 130, 255 },
{ 70, 100, 130, 255 },
{ 10, 50, 80, 255 },
},
{
{ 10, 50, 40, 255 },
{ 90, 100, 60, 255 },
{ 90, 100, 60, 255 },
{ 10, 50, 40, 255 },
},
{
{ 80,40,30, 255},
{ 140,60,60,255 },
{ 140,60,60,255 },
{ 80, 40, 30, 255 },
},
{
{ 80,80,50,255 },
{ 120,120,70,255 },
{ 120,120,70,255 },
{ 80, 80, 50, 255 },
},
{
{ 80, 40, 30, 255 },
{ 140,60,60,255 },
{ 140,60,60,255 },
{ 80, 40, 30, 255 },
},
{
{ 50,50,50,255 },
{ 110,110,110,255 },
{ 110,110,110,255 },
{ 50,50,50,255 },
},
};
PauseContext* pauseCtx = &play->pauseCtx; PauseContext* pauseCtx = &play->pauseCtx;
s16* ptr1; s16* ptr1;
s16* ptr2; s16* ptr2;
@ -2460,109 +2538,114 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) {
s16 phi_t0; s16 phi_t0;
s16 phi_a1; s16 phi_a1;
s16 phi_a2; s16 phi_a2;
s16 phi_t3; s16 colorIndex; // Also used for other things.
s16 phi_t1; s16 vtxIndex;
phi_t0 = -200; phi_t0 = -200;
for (phi_t1 = 0, phi_t3 = 0; phi_t3 < 3; phi_t3++) { for (vtxIndex = 0, colorIndex = 0; colorIndex < 3; colorIndex++) {
phi_t0 += 80; phi_t0 += 80;
for (phi_a1 = 80, phi_a2 = 0; phi_a2 < 5; phi_a2++, phi_t1 += 4, phi_a1 -= 32) { for (phi_a1 = 80, phi_a2 = 0; phi_a2 < 5; phi_a2++, vtxIndex += 4, phi_a1 -= 32) {
vtx[phi_t1 + 0].v.ob[0] = vtx[phi_t1 + 2].v.ob[0] = phi_t0; vtx[vtxIndex + 0].v.ob[0] = vtx[vtxIndex + 2].v.ob[0] = phi_t0;
vtx[phi_t1 + 1].v.ob[0] = vtx[phi_t1 + 3].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] + 80; vtx[vtxIndex + 1].v.ob[0] = vtx[vtxIndex + 3].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] + 80;
vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = phi_a1 + pauseCtx->offsetY; vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = phi_a1 + pauseCtx->offsetY;
vtx[phi_t1 + 2].v.ob[1] = vtx[phi_t1 + 3].v.ob[1] = vtx[phi_t1 + 0].v.ob[1] - 32; vtx[vtxIndex + 2].v.ob[1] = vtx[vtxIndex + 3].v.ob[1] = vtx[vtxIndex + 0].v.ob[1] - 32;
vtx[phi_t1 + 0].v.ob[2] = vtx[phi_t1 + 1].v.ob[2] = vtx[phi_t1 + 2].v.ob[2] = vtx[phi_t1 + 3].v.ob[2] = 0; vtx[vtxIndex + 0].v.ob[2] = vtx[vtxIndex + 1].v.ob[2] = vtx[vtxIndex + 2].v.ob[2] = vtx[vtxIndex + 3].v.ob[2] = 0;
vtx[phi_t1 + 0].v.flag = 0; vtx[vtxIndex + 0].v.flag = 0;
vtx[phi_t1 + 1].v.flag = 0; vtx[vtxIndex + 1].v.flag = 0;
vtx[phi_t1 + 2].v.flag = 0; vtx[vtxIndex + 2].v.flag = 0;
vtx[phi_t1 + 3].v.flag = 0; vtx[vtxIndex + 3].v.flag = 0;
vtx[phi_t1 + 0].v.tc[0] = vtx[phi_t1 + 0].v.tc[1] = vtx[phi_t1 + 1].v.tc[1] = vtx[phi_t1 + 2].v.tc[0] = 0; vtx[vtxIndex + 0].v.tc[0] = vtx[vtxIndex + 0].v.tc[1] = vtx[vtxIndex + 1].v.tc[1] = vtx[vtxIndex + 2].v.tc[0] = 0;
vtx[phi_t1 + 1].v.tc[0] = vtx[phi_t1 + 3].v.tc[0] = 0xA00; vtx[vtxIndex + 1].v.tc[0] = vtx[vtxIndex + 3].v.tc[0] = 0xA00;
vtx[phi_t1 + 2].v.tc[1] = vtx[phi_t1 + 3].v.tc[1] = 0x400; vtx[vtxIndex + 2].v.tc[1] = vtx[vtxIndex + 3].v.tc[1] = 0x400;
vtx[phi_t1 + 0].v.cn[0] = vtx[phi_t1 + 2].v.cn[0] = D_8082AE48[arg2][phi_t3 + 0]; //Color in the pages. Pages are drawn in groups. Each group is faded to the next. There are 4 total colors, 1/4 and 2/3 are the same creating a mirrored color set.
// TODO, go from 0,1,2,3 to 0,1,1,0 to only use two colors instead of 4.
Color_RGBA8 color = CVarGetColor(gPageVtxColorCvars[pageIndex][colorIndex], pageColors[pageIndex][colorIndex]);
Color_RGBA8 colorb =
CVarGetColor(gPageVtxColorCvars[pageIndex][colorIndex + 1], pageColors[pageIndex][colorIndex+1]);
vtx[vtxIndex + 0].v.cn[0] = vtx[vtxIndex + 2].v.cn[0] = color.r; // sPageVtxColorR[pageIndex][colorIndex + 0];
vtx[phi_t1 + 0].v.cn[1] = vtx[phi_t1 + 2].v.cn[1] = D_8082AE60[arg2][phi_t3 + 0]; vtx[vtxIndex + 0].v.cn[1] = vtx[vtxIndex + 2].v.cn[1] = color.g;// sPageVtxColorG[pageIndex][colorIndex + 0];
vtx[phi_t1 + 0].v.cn[2] = vtx[phi_t1 + 2].v.cn[2] = D_8082AE78[arg2][phi_t3 + 0]; vtx[vtxIndex + 0].v.cn[2] = vtx[vtxIndex + 2].v.cn[2] = color.b; // sPageVtxColorB[pageIndex][colorIndex + 0];
vtx[phi_t1 + 1].v.cn[0] = vtx[phi_t1 + 3].v.cn[0] = D_8082AE48[arg2][phi_t3 + 1]; vtx[vtxIndex + 1].v.cn[0] = vtx[vtxIndex + 3].v.cn[0] = colorb.r;//sPageVtxColorR[pageIndex][colorIndex + 1];
vtx[phi_t1 + 1].v.cn[1] = vtx[phi_t1 + 3].v.cn[1] = D_8082AE60[arg2][phi_t3 + 1]; vtx[vtxIndex + 1].v.cn[1] = vtx[vtxIndex + 3].v.cn[1] = colorb.g; // sPageVtxColorG[pageIndex][colorIndex + 1];
vtx[phi_t1 + 1].v.cn[2] = vtx[phi_t1 + 3].v.cn[2] = D_8082AE78[arg2][phi_t3 + 1]; vtx[vtxIndex + 1].v.cn[2] = vtx[vtxIndex + 3].v.cn[2] = colorb.b; // sPageVtxColorB[pageIndex][colorIndex + 1];
vtx[phi_t1 + 0].v.cn[3] = vtx[phi_t1 + 2].v.cn[3] = vtx[phi_t1 + 1].v.cn[3] = vtx[phi_t1 + 3].v.cn[3] = vtx[vtxIndex + 0].v.cn[3] = vtx[vtxIndex + 2].v.cn[3] = vtx[vtxIndex + 1].v.cn[3] = vtx[vtxIndex + 3].v.cn[3] =
pauseCtx->alpha; pauseCtx->alpha;
} }
} }
phi_s2 = phi_t1; phi_s2 = vtxIndex;
if (arg3 != 0) { if (arg3 != 0) {
ptr1 = D_8082B000[arg2]; ptr1 = D_8082B000[pageIndex];
ptr2 = D_8082B018[arg2]; ptr2 = D_8082B018[pageIndex];
ptr3 = D_8082B030[arg2]; ptr3 = D_8082B030[pageIndex];
ptr4 = D_8082B048[arg2]; ptr4 = D_8082B048[pageIndex];
for (phi_t3 = 0; phi_t3 < arg3; phi_t3++, phi_t1 += 4) { for (colorIndex = 0; colorIndex < arg3; colorIndex++, vtxIndex += 4) {
vtx[phi_t1 + 2].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] = ptr1[phi_t3]; vtx[vtxIndex + 2].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] = ptr1[colorIndex];
vtx[phi_t1 + 1].v.ob[0] = vtx[phi_t1 + 3].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] + ptr2[phi_t3]; vtx[vtxIndex + 1].v.ob[0] = vtx[vtxIndex + 3].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] + ptr2[colorIndex];
if (!((pauseCtx->state >= 8) && (pauseCtx->state <= 0x11))) { if (!((pauseCtx->state >= 8) && (pauseCtx->state <= 0x11))) {
vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = ptr3[phi_t3] + pauseCtx->offsetY; vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = ptr3[colorIndex] + pauseCtx->offsetY;
} else { } else {
vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = YREG(60 + phi_t3) + pauseCtx->offsetY; vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = YREG(60 + colorIndex) + pauseCtx->offsetY;
} }
vtx[phi_t1 + 2].v.ob[1] = vtx[phi_t1 + 3].v.ob[1] = vtx[phi_t1 + 0].v.ob[1] - ptr4[phi_t3]; vtx[vtxIndex + 2].v.ob[1] = vtx[vtxIndex + 3].v.ob[1] = vtx[vtxIndex + 0].v.ob[1] - ptr4[colorIndex];
vtx[phi_t1 + 0].v.ob[2] = vtx[phi_t1 + 1].v.ob[2] = vtx[phi_t1 + 2].v.ob[2] = vtx[phi_t1 + 3].v.ob[2] = 0; vtx[vtxIndex + 0].v.ob[2] = vtx[vtxIndex + 1].v.ob[2] = vtx[vtxIndex + 2].v.ob[2] = vtx[vtxIndex + 3].v.ob[2] = 0;
vtx[phi_t1 + 0].v.flag = vtx[phi_t1 + 1].v.flag = vtx[phi_t1 + 2].v.flag = vtx[phi_t1 + 3].v.flag = 0; vtx[vtxIndex + 0].v.flag = vtx[vtxIndex + 1].v.flag = vtx[vtxIndex + 2].v.flag = vtx[vtxIndex + 3].v.flag = 0;
vtx[phi_t1 + 0].v.tc[0] = vtx[phi_t1 + 0].v.tc[1] = vtx[phi_t1 + 1].v.tc[1] = vtx[phi_t1 + 2].v.tc[0] = 0; vtx[vtxIndex + 0].v.tc[0] = vtx[vtxIndex + 0].v.tc[1] = vtx[vtxIndex + 1].v.tc[1] = vtx[vtxIndex + 2].v.tc[0] = 0;
vtx[phi_t1 + 1].v.tc[0] = vtx[phi_t1 + 3].v.tc[0] = ptr2[phi_t3] << 5; vtx[vtxIndex + 1].v.tc[0] = vtx[vtxIndex + 3].v.tc[0] = ptr2[colorIndex] << 5;
vtx[phi_t1 + 2].v.tc[1] = vtx[phi_t1 + 3].v.tc[1] = ptr4[phi_t3] << 5; vtx[vtxIndex + 2].v.tc[1] = vtx[vtxIndex + 3].v.tc[1] = ptr4[colorIndex] << 5;
vtx[phi_t1 + 0].v.cn[0] = vtx[phi_t1 + 2].v.cn[0] = vtx[phi_t1 + 0].v.cn[1] = vtx[phi_t1 + 2].v.cn[1] = vtx[vtxIndex + 0].v.cn[0] = vtx[vtxIndex + 2].v.cn[0] = vtx[vtxIndex + 0].v.cn[1] = vtx[vtxIndex + 2].v.cn[1] =
vtx[phi_t1 + 0].v.cn[2] = vtx[phi_t1 + 2].v.cn[2] = vtx[phi_t1 + 1].v.cn[0] = vtx[phi_t1 + 3].v.cn[0] = vtx[vtxIndex + 0].v.cn[2] = vtx[vtxIndex + 2].v.cn[2] = vtx[vtxIndex + 1].v.cn[0] = vtx[vtxIndex + 3].v.cn[0] =
vtx[phi_t1 + 1].v.cn[1] = vtx[phi_t1 + 3].v.cn[1] = vtx[phi_t1 + 1].v.cn[2] = vtx[vtxIndex + 1].v.cn[1] = vtx[vtxIndex + 3].v.cn[1] = vtx[vtxIndex + 1].v.cn[2] =
vtx[phi_t1 + 3].v.cn[2] = 255; vtx[vtxIndex + 3].v.cn[2] = 255;
vtx[phi_t1 + 0].v.cn[3] = vtx[phi_t1 + 2].v.cn[3] = vtx[phi_t1 + 1].v.cn[3] = vtx[phi_t1 + 3].v.cn[3] = vtx[vtxIndex + 0].v.cn[3] = vtx[vtxIndex + 2].v.cn[3] = vtx[vtxIndex + 1].v.cn[3] = vtx[vtxIndex + 3].v.cn[3] =
pauseCtx->alpha; pauseCtx->alpha;
} }
if (arg2 == 4) { if (pageIndex == 4) {
phi_t1 -= 12; vtxIndex -= 12;
phi_t3 = gSaveContext.worldMapArea; colorIndex = gSaveContext.worldMapArea;
vtx[phi_t1 + 0].v.ob[0] = vtx[phi_t1 + 2].v.ob[0] = D_8082B060[phi_t3]; vtx[vtxIndex + 0].v.ob[0] = vtx[vtxIndex + 2].v.ob[0] = D_8082B060[colorIndex];
if (phi_t3) {} if (colorIndex) {}
vtx[phi_t1 + 1].v.ob[0] = vtx[phi_t1 + 3].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] + D_8082B08C[phi_t3]; vtx[vtxIndex + 1].v.ob[0] = vtx[vtxIndex + 3].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] + D_8082B08C[colorIndex];
vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = D_8082B0B8[phi_t3] + pauseCtx->offsetY; vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = D_8082B0B8[colorIndex] + pauseCtx->offsetY;
vtx[phi_t1 + 2].v.ob[1] = vtx[phi_t1 + 3].v.ob[1] = vtx[phi_t1 + 0].v.ob[1] - D_8082B0E4[phi_t3]; vtx[vtxIndex + 2].v.ob[1] = vtx[vtxIndex + 3].v.ob[1] = vtx[vtxIndex + 0].v.ob[1] - D_8082B0E4[colorIndex];
phi_t1 += 12; vtxIndex += 12;
if (pauseCtx->tradeQuestLocation != 0xFF) { if (pauseCtx->tradeQuestLocation != 0xFF) {
if (D_8082B114 == 0) { if (D_8082B114 == 0) {
@ -2582,14 +2665,14 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) {
D_8082B114--; D_8082B114--;
} }
phi_t3 = phi_s2 + (pauseCtx->tradeQuestLocation * 4) + 64; colorIndex = phi_s2 + (pauseCtx->tradeQuestLocation * 4) + 64;
phi_a2 = phi_s2 + 116; phi_a2 = phi_s2 + 116;
vtx[phi_a2 + 0].v.ob[0] = vtx[phi_a2 + 2].v.ob[0] = vtx[phi_t3 + 0].v.ob[0]; vtx[phi_a2 + 0].v.ob[0] = vtx[phi_a2 + 2].v.ob[0] = vtx[colorIndex + 0].v.ob[0];
vtx[phi_a2 + 1].v.ob[0] = vtx[phi_a2 + 3].v.ob[0] = vtx[phi_a2 + 0].v.ob[0] + 8; vtx[phi_a2 + 1].v.ob[0] = vtx[phi_a2 + 3].v.ob[0] = vtx[phi_a2 + 0].v.ob[0] + 8;
vtx[phi_a2 + 0].v.ob[1] = vtx[phi_a2 + 1].v.ob[1] = vtx[phi_t3 + 0].v.ob[1] - D_8082B110 + 10; vtx[phi_a2 + 0].v.ob[1] = vtx[phi_a2 + 1].v.ob[1] = vtx[colorIndex + 0].v.ob[1] - D_8082B110 + 10;
vtx[phi_a2 + 0].v.ob[2] = vtx[phi_a2 + 1].v.ob[2] = vtx[phi_a2 + 2].v.ob[2] = vtx[phi_a2 + 3].v.ob[2] = vtx[phi_a2 + 0].v.ob[2] = vtx[phi_a2 + 1].v.ob[2] = vtx[phi_a2 + 2].v.ob[2] = vtx[phi_a2 + 3].v.ob[2] =
0; 0;
@ -2598,7 +2681,7 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) {
vtx[phi_a2 + 0].v.flag = vtx[phi_a2 + 1].v.flag = vtx[phi_a2 + 2].v.flag = vtx[phi_a2 + 3].v.flag = 0; vtx[phi_a2 + 0].v.flag = vtx[phi_a2 + 1].v.flag = vtx[phi_a2 + 2].v.flag = vtx[phi_a2 + 3].v.flag = 0;
vtx[phi_t1].v.tc[0] = vtx[phi_t1].v.tc[1] = vtx[phi_a2 + 1].v.tc[1] = vtx[phi_a2 + 2].v.tc[0] = 0; vtx[vtxIndex].v.tc[0] = vtx[vtxIndex].v.tc[1] = vtx[phi_a2 + 1].v.tc[1] = vtx[phi_a2 + 2].v.tc[0] = 0;
vtx[phi_a2 + 1].v.tc[0] = vtx[phi_a2 + 3].v.tc[0] = 0x100; vtx[phi_a2 + 1].v.tc[0] = vtx[phi_a2 + 3].v.tc[0] = 0x100;
@ -2615,7 +2698,7 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) {
} }
} }
return phi_t1; return vtxIndex;
} }
static s16 D_8082B11C[] = { 0, 4, 8, 12, 24, 32, 56 }; static s16 D_8082B11C[] = { 0, 4, 8, 12, 24, 32, 56 };
@ -3325,6 +3408,7 @@ static uint8_t mapLeftTexModified[MAP_48x85_TEX_SIZE];
static uint8_t mapRightTexModified[MAP_48x85_TEX_SIZE]; static uint8_t mapRightTexModified[MAP_48x85_TEX_SIZE];
static uint8_t* mapLeftTexModifiedRaw = NULL; static uint8_t* mapLeftTexModifiedRaw = NULL;
static uint8_t* mapRightTexModifiedRaw = NULL; static uint8_t* mapRightTexModifiedRaw = NULL;
static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT];
// Load dungeon maps into the interface context // Load dungeon maps into the interface context
// SoH [General] - Modified to account for our resource system and HD textures // SoH [General] - Modified to account for our resource system and HD textures
@ -3356,19 +3440,16 @@ void KaleidoScope_LoadDungeonMap(PlayState* play) {
size_t size = (width * height) / 2; // account for CI4 size size_t size = (width * height) / 2; // account for CI4 size
// Resource size being larger than the calculated CI size means it is most likely not a CI4 texture // Resource size being larger than the calculated CI size means it is most likely not a CI4 texture
// Abort early end undo the blended effect by clearing the mask to avoid crashing // Abort early and unregister the blended effect to avoid crashing
if (size < ResourceGetTexSizeByName(interfaceCtx->mapSegmentName[0])) { if (size < ResourceGetTexSizeByName(interfaceCtx->mapSegmentName[0])) {
if (mapBlendMask[0] != 0) {
for (size_t i = 0; i < ARRAY_COUNT(mapBlendMask); i++) {
mapBlendMask[i] = 0;
}
}
interfaceCtx->mapSegment[0] = NULL; interfaceCtx->mapSegment[0] = NULL;
interfaceCtx->mapSegment[1] = NULL; interfaceCtx->mapSegment[1] = NULL;
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, NULL); Gfx_UnregisterBlendedTexture(interfaceCtx->mapSegmentName[0]);
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, NULL); Gfx_UnregisterBlendedTexture(interfaceCtx->mapSegmentName[1]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[0]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[1]);
return; return;
} }
@ -3403,6 +3484,11 @@ void KaleidoScope_LoadDungeonMap(PlayState* play) {
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, interfaceCtx->mapSegment[0]); Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, interfaceCtx->mapSegment[0]);
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, interfaceCtx->mapSegment[1]); Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, interfaceCtx->mapSegment[1]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[0]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[1]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegment[0]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegment[1]);
} }
static uint8_t registeredDungeonMapTextureHook = false; static uint8_t registeredDungeonMapTextureHook = false;
@ -3443,6 +3529,11 @@ void KaleidoScope_UpdateDungeonMap(PlayState* play) {
KaleidoScope_LoadDungeonMap(play); KaleidoScope_LoadDungeonMap(play);
Map_SetFloorPalettesData(play, pauseCtx->dungeonMapSlot - 3); Map_SetFloorPalettesData(play, pauseCtx->dungeonMapSlot - 3);
// Copy the map palette values to all pulse palettes
for (uint8_t i = 0; i < ARRAY_COUNT(interfaceCtx->mapPalettesPulse); i++) {
memcpy(interfaceCtx->mapPalettesPulse[i], interfaceCtx->mapPalette, sizeof(interfaceCtx->mapPalette));
}
s32 size = MAP_48x85_TEX_SIZE; s32 size = MAP_48x85_TEX_SIZE;
if (ResourceMgr_TexIsRaw(interfaceCtx->mapSegmentName[0])) { if (ResourceMgr_TexIsRaw(interfaceCtx->mapSegmentName[0])) {